Repository: django-cms/djangocms-link (language: python)

Issue:
get_link  will always return absolute urls instead of relative urls, making it hard to author content/test out locally
To follow up on #165

I tend to believe that the placeholder cms_page is redundant as Site.objects.get_current() will already return the correct site. And, considering that any placeholder.page.site is always the current site, when available, the code could be reduced to just

```
    def get_link(self):
        if self.internal_link:
            ref_page = self.internal_link
            link = ref_page.get_absolute_url()
            ref_page_site_id = ref_page.node.site_id
            if ref_page_site_id != Site.objects.get_current().pk:
                ref_site = Site.objects._get_site_by_id(ref_page_site_id).domain
                link = '//{}{}'.format(ref_site, link)

  ...
```

I have implemented this locally and it works like a charm, unless I missed some very specific detail :smile: 

I can provide you with a PR for this if you want.


Discussion / hints:
@silkentrance Yes, I'd agree that going through the placeholder to get a site_id in order to find the correct Site object isn't the best way to go about things.

However I don't think you can simplify `ref_page_site_id` like that. The `node` attr needs checking as it is now.
@marksweb considering that pages are always created by going through the API

https://github.com/django-cms/django-cms/blob/a3110e1ff24085373898c7d2a85f628abeb8518d/cms/api.py#L100

then the existence of the node foreign key is ensured, 

https://github.com/django-cms/django-cms/blob/a3110e1ff24085373898c7d2a85f628abeb8518d/cms/api.py#L187

even more so since the page model does not declare it to be nullable, 

https://github.com/django-cms/django-cms/blob/a3110e1ff24085373898c7d2a85f628abeb8518d/cms/models/pagemodel.py#L230

so it is a mandatory property of the page.

Therefore I tend to believe that the presented code is correct and should work under all circumstances.

Yet, looking at

https://github.com/django-cms/djangocms-link/blob/1d0417e68a05bfab55a21630d0b9b8b251d53f99/djangocms_link/models.py#L162

I am not so sure anymore. I will check the multiple usage scenarios and see what I can find...
@silkentrance Actually, I think you're right. Yesterday I was thinking back to times I've built things for menus and it's the node that you can't guarantee is attached to a page, but this is the other side of that 🤦 

By the way, I'm not sure if you're a slack user, but if you are it might be worth joining our slack [django-cms.org/slack](https://www.django-cms.org/slack)
I have played around with links in static placeholders, links in modules, links linking to pages from a different site than the current one. As of now, everything seems to be working just fine.

Fix patch:
diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 405c6ddc..00000000
--- a/.coveragerc
+++ /dev/null
@@ -1,18 +0,0 @@
-[run]
-branch = True
-source = djangocms_link
-omit =
-    migrations/*
-    tests/*
-
-[report]
-exclude_lines =
-    pragma: no cover
-    def __repr__
-    if self.debug:
-    if settings.DEBUG
-    raise AssertionError
-    raise NotImplementedError
-    if 0:
-    if __name__ == .__main__.:
-ignore_errors = True
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index d1c3a769..521cb88e 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -14,7 +14,7 @@ jobs:
         with:
           python-version: 3.9
       - name: Install flake8
-        run: pip install --upgrade flake8
+        run: pip install --upgrade flake8 flake8-pyproject
       - name: Run flake8
         uses: liskin/gh-problem-matcher-wrap@v1
         with:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 87266061..453234c2 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -24,6 +24,7 @@ repos:
     rev: 7.1.0
     hooks:
       - id: flake8
+        additional_dependencies: [Flake8-pyproject]
 
   - repo: https://github.com/pre-commit/pre-commit-hooks
     rev: v4.6.0
@@ -35,3 +36,16 @@ repos:
     rev: 5.13.2
     hooks:
       - id: isort
+
+  - repo: https://github.com/tox-dev/pyproject-fmt
+    rev: v2.5.0
+    hooks:
+    - id: pyproject-fmt
+
+  - repo: https://github.com/rstcheck/rstcheck
+    rev: v6.2.4
+    hooks:
+    - id: rstcheck
+      additional_dependencies:
+      - sphinx==6.1.3
+      - tomli==2.0.1
diff --git a/.tx/config b/.tx/config
index c9dbea70..dac38c67 100644
--- a/.tx/config
+++ b/.tx/config
@@ -1,8 +1,11 @@
 [main]
 host = https://www.transifex.com
 
-[djangocms-link.djangocms_link]
-file_filter = djangocms_link/locale/<lang>/LC_MESSAGES/django.po
-source_file = djangocms_link/locale/en/LC_MESSAGES/django.po
-source_lang = en
-type = PO
+[o:divio:p:djangocms-link:r:djangocms_link]
+file_filter            = djangocms_link/locale/<lang>/LC_MESSAGES/django.po
+source_file            = djangocms_link/locale/en/LC_MESSAGES/django.po
+source_lang            = en
+type                   = PO
+replace_edited_strings = false
+keep_translations      = false
+
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 5c709c32..4800829f 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,8 +2,20 @@
 Changelog
 =========
 
+5.0.0 (unreleased)
+==================
+
+* Major refactor
+* New re-usable LinkWidget, LinkFormField, and LinkField
+* New re-usable JSON endpoint for internal links
+* New template tags (``get_url`` tag and ``to_url`` filter) to convert link
+  fields into URLs. This allows multiple LinkFields per model
+* Fixed cross-site linking which reduces the number situations of the hostname
+  needing to be part of a link
+* Dropped django-select2 dependency in favor of django admin's autocomplete
+
 4.0.0 (2024-07-22)
-================
+==================
 
 * Added support for django CMS 4.1
 * Added support for python 3.10 to 3.12
diff --git a/MANIFEST.in b/MANIFEST.in
index 6f8e058e..d21543ea 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,4 +2,6 @@ include LICENSE
 include README.rst
 recursive-include djangocms_link/locale *
 recursive-include djangocms_link/templates *
+recursive-include djangocms_link/static *
 recursive-exclude * *.py[co]
+recursive-exclude tests *
diff --git a/README.rst b/README.rst
index 91424bda..5b34bea0 100644
--- a/README.rst
+++ b/README.rst
@@ -2,17 +2,15 @@
 django CMS Link
 ===============
 
-|pypi| |build| |coverage|
+|pypi| |coverage| |python| |django| |djangocms| |djangocms4|
 
-**django CMS Link** is a plugin for `django CMS <http://django-cms.org>`_ that
+**django CMS Link** is a plugin for `django CMS <https://django-cms.org>`_ that
 allows you to add links on your site.
 
 This plugin supports child plugins. If you add an other plugin as a
 child it will take this content instead of the link name as the content of the link.
 
-This addon is compatible with `Divio Cloud <http://divio.com>`_ and is also available on the
-`django CMS Marketplace <https://marketplace.django-cms.org/en/addons/browse/djangocms-link/>`_
-for easy installation.
+This addon is compatible with `Divio Cloud <http://divio.com>`_.
 
 .. image:: preview.gif
 
@@ -39,12 +37,13 @@ Documentation
 See ``REQUIREMENTS`` in the `setup.py <https://github.com/divio/djangocms-link/blob/master/setup.py>`_
 file for additional dependencies:
 
-|python| |django| |djangocms|
+django CMS Link has a weak dependency on django Filer. If
+`django Filer <http://django-filer.readthedocs.io/en/latest/installation.html>`_
+is installed and configured appropriately, django CMS Link will allow linking
+files.
 
 * Django Filer 1.7 or higher
-
-Make sure `django Filer <http://django-filer.readthedocs.io/en/latest/installation.html>`_
-is installed and configured appropriately.
+* djangocms-atrributes-field 1.0 or higher
 
 
 Installation
@@ -60,6 +59,9 @@ For a manual install:
 Configuration
 -------------
 
+Link templates
+..............
+
 Note that the provided templates are very minimal by design. You are encouraged
 to adapt and override them to your project's requirements.
 
@@ -73,11 +75,89 @@ setting:
         ('feature', _('Featured Version')),
     ]
 
-You'll need to create the `feature` folder inside ``templates/djangocms_link/``
+You'll need to create the ``feature`` folder inside ``templates/djangocms_link/``
 otherwise you will get a *template does not exist* error. You can do this by
 copying the ``default`` folder inside that directory and renaming it to
 ``feature``.
 
+Link types
+...........
+
+By default, django CMS Link provides three major link types: internal, external,
+and file link (if django-filer is installed).
+
+Phone links or email links can be entered by using the ``tel:`` or ``mailto:``
+scheme, respectively, in the external link field.
+
+By changing the ``DJANGOCMS_LINK_ALLOWED_LINK_TYPES`` setting you can limit
+the type of links accepted. The default is::
+
+    DJANGOCMS_LINK_ALLOWED_LINK_TYPES = [
+        'internal_link',  # Pages and other models
+        'external_link',  # Hand-typed URLs
+        'file_link',      # Files from django-filer
+        'tel',            # Phone numbers as external links using the tel: scheme
+        'mailto',         # Email addresses as external links using the mailto: scheme
+        'anchor',         # Anchors in the current page as external links using #
+    ]
+
+Linkable models
+...............
+
+*Added in version 5:*
+
+By default, django CMS Link will autodetect which Django or Django CMS models it
+can create internal links to. To make a model appear in the list of internal
+links, you need to
+
+* register a model admin for the model and provide a ``search_fields``
+  attribute. django CMS Link uses the same search logic as the Django admin.
+* provide a ``get_absolute_url()`` method on the model. This method should
+  return the URL of the model instance.
+
+If you do not want to use auto detection, you can provide a list of models
+in the ``DJANGOCMS_LINKABLE_MODELS`` setting using dotted strings::
+
+    DJANGOCMS_LINKABLE_MODELS = [
+        'myapp.mymodel',
+    ]
+
+Attention: ``Page`` objects are always linkable.
+
+django CMS Link will use the model admin's ``get_queryset`` method to retrieve
+the list of objects. If you want to add custom filters, sorting or site
+handling, you can add a ``get_link_queryset`` method to the model admin::
+
+    class MyModelAdmin(admin.ModelAdmin):
+        def get_link_queryset(self, request, site_id):
+            """Only used by djangocms-link: returns queryset to select link targets from."""
+            qs = self.get_queryset(request)
+            return qs.filter(is_public=True)
+
+Large search-sets
+..................
+
+If you have a large number of internally linkable models, you can use the
+``DJANGOCMS_LINK_MINIMUM_INPUT_LENGTH`` setting to require a minimum number of
+characters typed before the search is triggered. The higher the number, the
+smaller the average result set size. The default is 0::
+
+    # Require at least 2 characters to be typed before searching for pages
+    DJANGOCMS_LINK_MINIMUM_INPUT_LENGTH = 2
+
+By default django CMS Link will paginate the search results. You can change the
+page size by setting the ``DJANGOCMS_LINK_PAGINATE_BY`` setting.
+The default is 50::
+
+    # Show 100 results per "page"
+    DJANGOCMS_LINK_PAGINATE_BY = 100
+
+Note, that in the admin paginated search results repeat the modle verbose name.
+
+
+Non-standard hostnames
+......................
+
 To support environments where non-standard URLs would otherwise work, this
 project supports the defining of an additional RegEx pattern for validating the
 host-portion of the URL.
@@ -98,16 +178,53 @@ Either of these might accept a URL such as:
 If left undefined, the normal Django URLValidator will be used.
 
 
-Django Select2
-~~~~~~~~~~~~~~
+Link fields
+-----------
 
-This plugin supports `django-select2 <https://github.com/applegrew/django-select2#installation>`_
-for simpler use of internal links. You need to manually enable it by:
+*Added in version 5:*
 
-* run ``pip install django-select2``
-* add ``django_select2`` to your ``INSTALLED_APPS``
-* add ``url(r'^select2/', include('django_select2.urls')),`` to your ``urls.py``
-* set ``DJANGOCMS_LINK_USE_SELECT2 = True`` in your ``settings.py``
+django CMS Link provides a re-usable link model field, form field and form
+widget. This allows you to use the link field in your own models or admin forms.
+
+.. code-block:: python
+
+    from djangocms_link.fields import LinkField, LinkFormField, LinkWidget
+
+    class MyModel(models.Model):
+        link = LinkField()  # or LinkField(blank=True) for optional links
+
+    class MyForm(forms.Form):
+        link = LinkFormField(required=False)
+
+``LinkField`` is a subclass of ``JSONField`` and stores the link data as
+``djangocms_link.helpers.LinkDict``, a direct subclass of ``dict``.
+(An empty link will be ``{}``.)
+
+To render the link field in a template, convert the ``LinkDict`` to string,
+use the ``LinkDict`` property ``url`` or the new template tag ``to_url``.
+The ``type`` property returns the link type::
+
+    {# Variant 1 #}
+    {% if obj.link %}
+        <a href="{{ obj.link }}">Link available</a>  {# str(obj.link) gives the URL #}
+    {% endif %}
+
+    {# Variant 2 #}
+    {% if obj.link %}
+        <a href="{{ obj.link.url }}">Link</a>  {# explicitly get the URL #}
+    {% endif %}
+
+    {% if obj.link.type == "external_link" %}  {# evaluate link type #}
+        <a href="{{ obj.link.url }}">External link</a>
+    {% endif %}
+
+
+To turn the ``LinkField``'s ``LinkDict`` dictionary into a URL in python code,
+use the ``url`` property. (It will hit the database if needed. Results are
+cached.)::
+
+    obj = MyModel.objects.first()
+    url = obj.link.url
 
 
 Running Tests
@@ -118,35 +235,45 @@ You can run tests by executing::
     virtualenv env
     source env/bin/activate
     pip install -r tests/requirements.txt
-    python setup.py test
+    pytest
 
 
-.. |pypi| image:: https://badge.fury.io/py/djangocms-link.svg
-    :target: http://badge.fury.io/py/djangocms-link
-.. |build| image:: https://travis-ci.org/divio/djangocms-link.svg?branch=master
-    :target: https://travis-ci.org/divio/djangocms-link
-.. |coverage| image:: https://codecov.io/gh/divio/djangocms-link/branch/master/graph/badge.svg
-    :target: https://codecov.io/gh/divio/djangocms-link
-
-.. |python| image:: https://img.shields.io/badge/python-3.5+-blue.svg
-    :target: https://pypi.org/project/djangocms-link/
-.. |django| image:: https://img.shields.io/badge/django-2.2,%203.0,%203.1-blue.svg
-    :target: https://www.djangoproject.com/
-.. |djangocms| image:: https://img.shields.io/badge/django%20CMS-3.7%2B-blue.svg
-    :target: https://www.django-cms.org/
-
+Upgrading from version 4 or lower
+---------------------------------
 
-Updating from `cmsplugin-filer <https://github.com/django-cms/cmsplugin-filer>`_
---------------------------------------------------------------------------------
+django CMS Link 5 is a rewrite of the plugin. If you are updating from
+version 4 or lower, you will notice
 
-Historically, `cmsplugin-filer` was used to create file, folder, image, link, teaser & video plugins on your django CMS projects. Now `cmsplugin-filer` has been archived, you can still migrate your old instances without having to copy them manually to the new `djangocms-<file|picture|link|...>` plugins.
+* the **new re-usable link widget**, greatly simplifying the user interface
+* an **improved management of multi-site situations**, essentially avoiding the
+  unnecessary additon of the host name to the URL in plugin instances that
+  are not in a page placeholder (such as links on aliases or static placeholder)
+* a **re-usable admin endpoint** for querying available links which can be used
+  by other apps such as djangocms-text.
+* Links are generated by template tags or template filters instead of the
+  model's ``get_link()`` method. This allows multiple links in future models. The
+  ``get_link()`` method on the plugin's model is still available for backwards
+  compatibility.
 
-There's a third-party management command that supports your migration:
+Migrations should automatically existing plugin instances to the new model
+fields.
 
-`migrate_cmsplugin_filer.py <https://gist.github.com/corentinbettiol/84a6ea7e4d047fc01861b0af15fd60f0>`_
+**WARNING:** We strongly recommend to backup your database before updating to
+version 5. The migration is tested but they do remove unused fields from
+the database. If you encounter any issues, please report them on
+`GitHub <https://github.com/django-cms/djangocms-link/issues>`_.
 
-This management command is only a starting point. It *has* worked out of the box for some people, but we encourage you to read the code, understand what it does, and test it on a development environment before running it on your production server.
+.. |pypi| image:: https://badge.fury.io/py/djangocms-link.svg
+    :target: http://badge.fury.io/py/djangocms-link
+.. |coverage| image:: https://codecov.io/gh/django-cms/djangocms-link/branch/master/graph/badge.svg
+    :target: https://codecov.io/gh/django-cms/djangocms-link
 
-The management command is only configured to transfer your `cmsplugin_link`, `cmsplugin_file`, `cmsplugin_folder` and `cmsplugin_image` plugins to modern `djangocms_*` plugins. If you need to transfer other `cmsplugin_*` plugins, you'll have to write your own code.
+.. |python| image:: https://img.shields.io/badge/python-3.10+-blue.svg
+    :target: https://pypi.org/project/djangocms-link/
+.. |django| image:: https://img.shields.io/badge/django-4.2,%205.0,%205.1-blue.svg
+    :target: https://www.djangoproject.com/
+.. |djangocms| image:: https://img.shields.io/badge/django%20CMS-3.11%2B-blue.svg
+    :target: https://www.django-cms.org/
+.. |djangocms4| image:: https://img.shields.io/badge/django%20CMS-4-blue.svg
+    :target: https://www.django-cms.org/
 
-Alternatively you can use the `deprecate_cmsplugin_filer <https://github.com/ImaginaryLandscape/deprecate_cmsplugin_filer>`_ app, which only adds a small migration that transfer the old `cmsplugin-filer` plugins instances to the new `djangocms-<file|picture|link|...>` plugins.
diff --git a/djangocms_link/__init__.py b/djangocms_link/__init__.py
index d6497a81..10daf977 100644
--- a/djangocms_link/__init__.py
+++ b/djangocms_link/__init__.py
@@ -1,1 +1,1 @@
-__version__ = '4.0.0'
+__version__ = "5.0.0a1"
diff --git a/djangocms_link/admin.py b/djangocms_link/admin.py
new file mode 100644
index 00000000..f2b10a11
--- /dev/null
+++ b/djangocms_link/admin.py
@@ -0,0 +1,273 @@
+from django.apps import apps
+from django.conf import settings
+from django.contrib import admin
+from django.core.exceptions import FieldError, PermissionDenied
+from django.db.models import OuterRef, Q, Subquery
+from django.http import Http404, JsonResponse
+from django.urls import path
+from django.utils.translation import gettext as _
+from django.views.generic.list import BaseListView
+
+from cms import __version__
+from cms.models import Page
+from cms.utils import get_language_from_request
+
+from . import models
+from .fields import LinkFormField, LinkWidget
+from .helpers import get_manager
+
+
+_version = int(__version__.split(".")[0])
+if _version >= 4:
+    from cms.admin.utils import GrouperModelAdmin
+    from cms.models import PageContent
+else:
+    from cms.models import Title as PageContent
+
+    class GrouperModelAdmin:
+        pass
+
+
+REGISTERED_ADMIN = []  # Will be set by djangocms_link.apps.DjangoCmsLinkConfig.ready
+
+
+class AdminUrlsView(BaseListView):
+    """Handle AutocompleteWidget's AJAX requests for data."""
+
+    paginate_by = getattr(settings, "DJANGOCMS_LINK_PAGINATE_BY", 50)
+    admin_site = None
+
+    def get(self, request, *args, **kwargs):
+        """
+        Return a JsonResponse with search results as defined in
+        serialize_result(), by default:
+        {
+            results: [{id: "123" text: "foo"}],
+            pagination: {more: true}
+        }
+        """
+        if request.GET.get("g"):
+            # Get name of a reference
+            return self.get_reference(request)
+
+        self.term, self.language, self.site = self.process_request(request)
+
+        if not self.has_perm(request):
+            raise PermissionDenied
+
+        qs_list = [self.get_queryset()]
+        self.add_admin_querysets(qs_list)
+        self.object_list = self.get_paginated_multi_qs(qs_list)
+        context = self.get_context_data()
+        results = self.get_optgroups(context)
+        return JsonResponse(
+            {
+                "results": results,
+                "pagination": {"more": context["page_obj"].has_next()},
+            }
+        )
+
+    def get_page(self):
+        page_kwarg = self.page_kwarg
+        page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
+        try:
+            page_number = int(page)
+        except ValueError:
+            raise Http404(
+                _("Page is not “last”, nor can it be converted to an int.")
+            )
+        return page_number
+
+    def get_paginated_multi_qs(self, qs_list):
+        """
+        Paginate multiple querysets and return a result list.
+        """
+        if len(qs_list) == 1:
+            # Only one qs, just use regular pagination
+            return qs_list[0]
+        # Slize all querysets, evaluate and join them into a list
+        max_items = self.get_page() * self.paginate_by
+        return sum((list(qs[:max_items]) for qs in qs_list), start=[])
+
+    def get_reference(self, request):
+        try:
+            model_str, pk = request.GET.get("g").split(":")
+            app, model = model_str.split(".")
+            model = apps.get_model(app, model)
+            model_admin = self.admin_site._registry.get(model)
+            if model_str == "cms.page" and _version >= 4 or model_admin is None:
+                obj = get_manager(model).get(pk=pk)
+                if model_str == "cms.page":
+                    language = get_language_from_request(request)
+                    obj.__link_text__ = obj.get_admin_content(language).title
+                return JsonResponse(self.serialize_result(obj))
+
+            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))
+        except Exception as e:
+            return JsonResponse({"error": str(e)})
+
+    def get_optgroups(self, context):
+        results = []
+        model = {}
+        previous_model = None
+        for obj in context["object_list"]:
+            if obj._meta.verbose_name_plural != previous_model or not model:
+                if model:  # Don't add the initial empty model
+                    results.append(model)
+                previous_model = obj._meta.verbose_name_plural
+                model = {
+                    "text": previous_model.capitalize(),
+                    "children": [],
+                }
+            model["children"].append(self.serialize_result(obj))
+        if model:
+            results.append(model)
+        return results
+
+    def serialize_result(self, obj):
+        """
+        Convert the provided model object to a dictionary that is added to the
+        results list.
+        """
+        return {
+            "id": f"{obj._meta.app_label}.{obj._meta.model_name}:{obj.pk}",
+            "text": getattr(obj, "__link_text__", str(obj)) or str(obj),
+            "url": obj.get_absolute_url(),
+            "verbose_name": str(obj._meta.verbose_name).capitalize(),
+        }
+
+    def get_queryset(self):
+        """Return queryset based on ModelAdmin.get_search_results()."""
+        try:
+            # django CMS 4.2+
+            qs = (
+                PageContent.admin_manager.filter(language=self.language)
+                .filter(
+                    Q(title__icontains=self.term) | Q(menu_title__icontains=self.term)
+                )
+                .current_content()
+            )
+            qs = (
+                Page.objects.filter(pk__in=qs.values_list("page_id", flat=True))
+                .order_by("path")
+                .annotate(
+                    __link_text__=Subquery(
+                        qs.filter(page_id=OuterRef("pk")).values("title")[:1]
+                    )
+                )
+            )
+            if self.site:
+                qs = qs.filter(site_id=self.site)
+        except (AttributeError, FieldError):
+            # django CMS 3.11 - 4.1
+            qs = (
+                get_manager(PageContent, current_content=True)
+                .filter(language=self.language)
+                .filter(
+                    Q(title__icontains=self.term) | Q(menu_title__icontains=self.term)
+                )
+            )
+            qs = (
+                Page.objects.filter(pk__in=qs.values_list("page_id", flat=True))
+                .order_by("node__path")
+                .annotate(
+                    __link_text__=Subquery(
+                        qs.filter(page_id=OuterRef("pk")).values("title")[:1]
+                    )
+                )
+            )
+            if self.site:
+                qs = qs.filter(node__site_id=self.site)
+        return qs
+
+    def add_admin_querysets(self, qs):
+        for model_admin in REGISTERED_ADMIN:
+            try:
+                # hack: GrouperModelAdmin expects a language to be temporarily set
+                if isinstance(model_admin, GrouperModelAdmin):  # pragma: no cover
+                    model_admin.language = self.language
+                if hasattr(model_admin, "get_link_queryset"):
+                    # Allow model admins to define get_link_queryset to do additional
+                    # filtering, sorting and potentially custom site selection
+                    new_qs = model_admin.get_link_queryset(self.request, self.site)
+                else:
+                    new_qs = model_admin.get_queryset(self.request)
+                    if hasattr(model_admin.model, "site") and self.site:
+                        new_qs = new_qs.filter(
+                            Q(site_id=self.site) | Q(site__isnull=True)
+                        )
+                    elif hasattr(model_admin.model, "sites") and self.site:
+                        new_qs = new_qs.filter(sites__id=self.site)
+                new_qs, search_use_distinct = model_admin.get_search_results(
+                    self.request, new_qs, self.term
+                )
+                if search_use_distinct:  # pragma: no cover
+                    new_qs = new_qs.distinct()
+
+                qs.append(new_qs)
+            except Exception:  # pragma: no cover
+                # Still report back remaining urls even if one model fails
+                pass
+
+        return qs
+
+    def process_request(self, request):
+        """
+        Validate request integrity, extract and return request parameters.
+        """
+        term = request.GET.get("term", request.GET.get("q", "")).strip("  ").lower()
+        site = request.GET.get(
+            "app_label", ""
+        )  # Django admin's app_label is abused as site id
+        try:
+            site = int(site)
+        except ValueError:
+            site = None
+        language = get_language_from_request(request)
+        return term, language, site
+
+    def has_perm(self, request, obj=None):
+        """Check if user has permission to access the related model."""
+        if obj is None:
+            return True
+        model_admin = self.admin_site._registry.get(obj.__class__)
+        if model_admin is None:
+            return False
+        return model_admin.has_view_permission(request, obj=obj)
+
+
+class LinkAdmin(admin.ModelAdmin):
+    """The LinkAdmin class provides the endpoint for getting the urls. It is not visible in the
+    admin interface."""
+
+    global_link_form_widget = LinkWidget
+    global_link_form_field = LinkFormField
+    global_link_url_name = None
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.global_link_url_name = f"{self.opts.app_label}_{self.opts.model_name}_urls"
+
+    def has_module_permission(self, request):  # pragma: no cover
+        # Remove from admin
+        return False
+
+    def get_urls(self):
+        # Only url endpoint public, do not call super().get_urls()
+        return [
+            path(
+                "urls",
+                self.admin_site.admin_view(self.url_view),
+                name=self.global_link_url_name,
+            ),
+        ]
+
+    def url_view(self, request):
+        return AdminUrlsView.as_view(admin_site=self.admin_site)(request)
+
+
+admin.site.register(models.Link, LinkAdmin)
diff --git a/djangocms_link/apps.py b/djangocms_link/apps.py
new file mode 100644
index 00000000..475df7bd
--- /dev/null
+++ b/djangocms_link/apps.py
@@ -0,0 +1,50 @@
+from django.apps import AppConfig, apps
+from django.conf import settings
+from django.contrib.admin import ModelAdmin
+from django.core.exceptions import ImproperlyConfigured
+from django.utils.translation import gettext_lazy as _
+
+
+class DjangoCmsLinkConfig(AppConfig):
+    name = "djangocms_link"
+    verbose_name = _("django CMS Link")
+
+    def ready(self):
+        # Only scan admins after all apps are loaded
+        from django.contrib import admin
+
+        from djangocms_link import admin as link_admin
+
+        linkable_models = getattr(settings, "DJANGOCMS_LINKABLE_MODELS", "auto")
+
+        if linkable_models == "auto":  # pragma: no cover
+            # Autoconfig? Check the admin registry for suitable admins
+            link_admin.REGISTERED_ADMIN = []
+            for _admin in admin.site._registry.values():
+                if _admin.model._meta.app_label == "cms":
+                    # Skip CMS models
+                    continue
+                # search_fields need to be defined in the ModelAdmin class, and the model needs to have
+                # a get_absolute_url method.
+                if getattr(_admin, "search_fields", []) and hasattr(
+                    _admin.model, "get_absolute_url"
+                ):
+                    link_admin.REGISTERED_ADMIN.append(_admin)
+        else:
+            # turn model config into model admin instances
+            admins = []
+            for model in linkable_models:
+                if isinstance(model, str):
+                    model = apps.get_model(model)
+                    if not hasattr(model, "get_absolute_url"):  # pragma: no cover
+                        raise ImproperlyConfigured(
+                            f"{model.__name__} needs to implement get_absolute_url method"
+                        )
+                    admin = admin.site._registry[model]
+                    if admin not in admins:
+                        admins.append(admin)
+                elif not isinstance(model, ModelAdmin):  # pragma: no cover
+                    raise ImproperlyConfigured(
+                        'DJANGOCMS_LINK_LINKABLE_MODELS must be a list of string "app_label.model_name"'
+                    )
+            link_admin.REGISTERED_ADMIN = admins
diff --git a/djangocms_link/cms_plugins.py b/djangocms_link/cms_plugins.py
index bba3f8df..cd42e21d 100644
--- a/djangocms_link/cms_plugins.py
+++ b/djangocms_link/cms_plugins.py
@@ -1,72 +1,57 @@
-from django.contrib.sites.models import Site
+from django.contrib.sites.shortcuts import get_current_site
 from django.utils.translation import gettext_lazy as _
 
 from cms.plugin_base import CMSPluginBase
 from cms.plugin_pool import plugin_pool
 
-from .forms import LinkForm
+from .helpers import get_link
 from .models import Link
 
 
 class LinkPlugin(CMSPluginBase):
     model = Link
-    form = LinkForm
-    name = _('Link')
+    name = _("Link")
     text_enabled = True
+    text_icon = (
+        '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-link-45deg" '
+        'viewBox="0 0 16 16"><path d="M4.715 6.542 3.343 7.914a3 3 0 1 0 4.243 4.243l1.828-1.829A3 3 0 0 0 8.586 '
+        "5.5L8 6.086a1 1 0 0 0-.154.199 2 2 0 0 1 .861 3.337L6.88 11.45a2 2 0 1 1-2.83-2.83l.793-.792a4 4 0 0 "
+        '1-.128-1.287z"/><path d="M6.586 4.672A3 3 0 0 0 7.414 9.5l.775-.776a2 2 0 0 1-.896-3.346L9.12 3.55a2 2 0 '
+        '1 1 2.83 2.83l-.793.792c.112.42.155.855.128 1.287l1.372-1.372a3 3 0 1 0-4.243-4.243z"/></svg>'
+    )
     allow_children = True
 
     fieldsets = [
-        (None, {
-            'fields': (
-                'name',
-                ('external_link', 'internal_link'),
-            )
-        }),
-        (_('Link settings'), {
-            'classes': ('collapse',),
-            'fields': (
-                ('mailto', 'phone'),
-                ('anchor', 'target'),
-                ('file_link'),
-            ),
-        }),
-        (_('Advanced settings'), {
-            'classes': ('collapse',),
-            'fields': (
-                'template',
-                'attributes',
-            )
-        }),
+        (
+            None,
+            {
+                "fields": (
+                    "name",
+                    "link",
+                    "target",
+                )
+            },
+        ),
+        (
+            _("Advanced settings"),
+            {
+                "classes": ("collapse",),
+                "fields": (
+                    "template",
+                    "attributes",
+                ),
+            },
+        ),
     ]
 
-    @classmethod
-    def get_render_queryset(cls):
-        queryset = super().get_render_queryset()
-        return queryset.select_related('internal_link')
-
     def get_render_template(self, context, instance, placeholder):
-        return f'djangocms_link/{instance.template}/link.html'
+        return f"djangocms_link/{instance.template}/link.html"
 
     def render(self, context, instance, placeholder):
-        context['link'] = instance.get_link()
+        context["link"] = get_link(
+            instance.link, getattr(get_current_site(context["request"]), "id", None)
+        )
         return super().render(context, instance, placeholder)
 
-    def get_form(self, request, obj=None, **kwargs):
-        form_class = super().get_form(request, obj, **kwargs)
-
-        if obj and obj.page and hasattr(obj.page, 'site') and obj.page.site:
-            site = obj.page.site
-        elif self.page and hasattr(self.page, 'site') and self.page.site:
-            site = self.page.site
-        else:
-            site = Site.objects.get_current()
-
-        class Form(form_class):
-            def __init__(self, *args, **kwargs):
-                super().__init__(*args, **kwargs)
-                self.for_site(site)
-
-        return Form
-
 
 plugin_pool.register_plugin(LinkPlugin)
diff --git a/djangocms_link/fields.py b/djangocms_link/fields.py
index 53e8865d..8fee574b 100644
--- a/djangocms_link/fields.py
+++ b/djangocms_link/fields.py
@@ -1,13 +1,384 @@
+from __future__ import annotations
+
+import json
+
+from django.apps import apps
 from django.conf import settings
+from django.contrib.admin import site
+from django.contrib.admin.widgets import SELECT2_TRANSLATIONS, AutocompleteSelect
+from django.contrib.sites.models import Site
+from django.db import models
+from django.db.models import JSONField, ManyToOneRel
+from django.forms import Field, MultiWidget, Select, TextInput, URLInput
+from django.utils.translation import get_language
+from django.utils.translation import gettext_lazy as _
+
+from cms.utils.urlutils import admin_reverse
+
+from djangocms_link.helpers import LinkDict, get_manager
+
+
+try:
+    from filer.fields.file import AdminFileWidget, FilerFileField
+    from filer.models import File
+except (ModuleNotFoundError, ImportError):  # pragma: no cover
+    File = None
+
+from djangocms_link.validators import AnchorValidator, ExtendedURLValidator
+
+
+MINIMUM_INPUT_LENGTH = getattr(settings, "DJANGOCMS_LINK_MINIMUM_INPUT_LENGTH", 0)
+
+
+class LinkAutoCompleteWidget(AutocompleteSelect):
+    def __init__(self, attrs: dict | None = None):
+        super().__init__(None, None, attrs)
+
+    def get_internal_obj(self, values: list[str | None]) -> list[models.Model | None]:
+        internal_obj = []
+        for value in values:
+            if value:
+                model_path, pk = value.split(":", 1)
+                model = apps.get_model(*model_path.split(".", 1))
+                internal_obj.append(get_manager(model).filter(pk=pk).first())
+            else:
+                internal_obj.append(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
+                )
+            )
+        return groups
+
+    def get_url(self):
+        return admin_reverse("djangocms_link_link_urls")
+
+    def build_attrs(self, base_attrs: dict, extra_attrs: dict | None = None) -> dict:
+        """
+        Set select2's AJAX attributes.
+
+        Attributes can be set using the html5 data attribute.
+        Nested attributes require a double dash as per
+        https://select2.org/configuration/data-attributes#nested-subkey-options
+        """
+        attrs = super(Select, self).build_attrs(base_attrs, extra_attrs=extra_attrs)
+        attrs.setdefault("class", "")
+        i18n_name = getattr(
+            self, "i18n_name", SELECT2_TRANSLATIONS.get(get_language())
+        )  # Django 3.2 compat
+        attrs.update(
+            {
+                "data-ajax--cache": "true",
+                "data-ajax--delay": 250,
+                "data-ajax--type": "GET",
+                "data-ajax--url": self.get_url(),
+                "data-theme": "admin-autocomplete",
+                "data-allow-clear": json.dumps(not self.is_required),
+                "data-placeholder": "",  # Allows clearing of the input.
+                "data-minimum-input-length": MINIMUM_INPUT_LENGTH,
+                "lang": i18n_name,
+                "class": attrs["class"]
+                + (" " if attrs["class"] else "")
+                + "admin-autocomplete",
+            }
+        )
+        return attrs
+
+
+class SiteAutocompleteSelect(AutocompleteSelect):
+    no_sites = None
+
+    def __init__(self, attrs: dict | None = None):
+        # Hack: Pretend that the user is selecting a site for a Page object
+        # and use Django admin's autocomplete widget
+        try:
+            from cms.models.pagemodel import TreeNode
+
+            field = TreeNode._meta.get_field("site")
+        except ImportError:  # pragma: no cover
+            # django CMS 4.2+
+            from cms.models import Page
+
+            field = Page._meta.get_field("site")
+        super().__init__(field, site, attrs)
+
+    def optgroups(self, name: str, value: str, attr: dict | None = None):
+        default = (None, [], 0)
+        groups = [default]
+        has_selected = False
+        selected_choices = set(value)
+        default[1].append(self.create_option(name, "", "", False, 0))
+
+        site = Site.objects.get_current()
+        option_value, option_label = site.pk, str(site)
+
+        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
+            )
+        )
+        return groups
+
+
+# Configure the LinkWidget
+link_types = {
+    "internal_link": _("Internal link"),
+    "external_link": _("External link/anchor"),
+}
+if File:
+    link_types["file_link"] = _("File link")
+
+# Get the allowed link types from the settings
+allowed_link_types = getattr(
+    settings,
+    "DJANGOCMS_LINK_ALLOWED_LINK_TYPES",
+    ("internal_link", "external_link", "file_link", "anchor", "mailto", "tel"),
+)
+
+# Adjust example uri schemes to allowed link types
+example_uri_scheme = (
+    "'https://'"
+    + (", 'tel:'" if "tel" in allowed_link_types else "")
+    + (", or 'mailto:'" if "mailto" in allowed_link_types else "")
+)
+
+# Show anchor sub-widget only for internal_link
+_mapping = {key: key for key in link_types.keys()}
+_mapping["anchor"] = "internal_link"
+
+# Remove disallowed link types
+link_types = {
+    key: value for key, value in link_types.items() if key in allowed_link_types
+}
+
+# Create the available widgets
+_available_widgets = {
+    "always": Select(
+        choices=list(link_types.items()),
+        attrs={
+            "class": "js-link-widget-selector",
+            "data-help": _(
+                "No destination selected. Use the dropdown to select a destination."
+            ),
+        },
+    ),  # Link type selector
+    "external_link": URLInput(
+        attrs={
+            "widget": "external_link",
+            "placeholder": _("https://example.com or #anchor"),
+            "data-help": _(
+                "Provide a link to an external URL, including the schema such as {}. "
+                "Optionally, add an #anchor (including the #) to scroll to."
+            ).format(example_uri_scheme),
+        },
+    ),  # External link input
+    "internal_link": LinkAutoCompleteWidget(
+        attrs={
+            "widget": "internal_link",
+            "data-help": _(
+                "Select from available internal destinations. Optionally, add an anchor to scroll to."
+            ),
+            "data-placeholder": _("Select internal destination"),
+        },
+    ),  # Internal link selector
+    "anchor": TextInput(
+        attrs={
+            "widget": "anchor",
+            "placeholder": _("#anchor"),
+            "data-help": _("Provide an anchor to scroll to."),
+        }
+    ),
+}
+if File:
+    _available_widgets["file_link"] = AdminFileWidget(
+        rel=ManyToOneRel(FilerFileField, File, "id"),
+        admin_site=site,
+        attrs={
+            "widget": "file_link",
+            "data-help": _("Select a file as destination."),
+        },
+    )
+
+
+class LinkWidget(MultiWidget):
+    template_name = "djangocms_link/admin/link_widget.html"
+    data_pos = {}
+    number_sites = None
+    default_site_selector = getattr(settings, "DJANGOCMS_LINK_SITE_SELECTOR", False)
+
+    class Media:
+        js = ("djangocms_link/link-widget.js",)
+        css = {"all": ("djangocms_link/link-widget.css",)}
+
+    def __init__(self, site_selector: bool | None = None):
+        if site_selector is None:
+            site_selector = LinkWidget.default_site_selector
+
+        widgets = [
+            widget
+            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:
+            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
+
+        # Remember which widget expets its content at which position
+        self.data_pos = {
+            widget.attrs.get("widget"): i for i, widget in enumerate(widgets)
+        }
+        super().__init__(widgets)
+
+    def get_context(self, name: str, value: str | None, attrs: dict) -> dict:
+        if not self.is_required:
+            self.widgets[0].choices = [("empty", "---------")] + self.widgets[0].choices
+        context = super().get_context(name, value, attrs)
+        context["widget"]["subwidgets"] = {
+            widget["attrs"].get("widget", "link-type-selector"): widget
+            for widget in context["widget"]["subwidgets"]
+        }
+        if File and "file_link" in allowed_link_types:
+            del context["widget"]["subwidgets"]["file_link"]
+            index = next(
+                i
+                for i, widget in enumerate(self.widgets)
+                if widget.attrs.get("widget") == "file_link"
+            )
+            context["filer_widget"] = self.widgets[index].render(
+                name + f"_{index}", value[index], attrs
+            )
+        return context
+
+
+class LinkFormField(Field):
+    widget = LinkWidget
+    external_link_validators = [
+        ExtendedURLValidator(allowed_link_types=allowed_link_types)
+    ]
+    internal_link_validators = []
+    file_link_validators = []
+    anchor_validators = [AnchorValidator()]
+
+    empty_values = [None, {}]
+
+    def __init__(self, *args, **kwargs):
+        kwargs.setdefault("help_text", _("Select a link type and provide a link."))
+        kwargs.setdefault("initial", {})
+        kwargs.pop("encoder", None)  # Passed from LinkField's JSONField parent class
+        kwargs.pop("decoder", None)  # but not needed
+        super().__init__(*args, **kwargs)
+
+    def prepare_value(self, value: dict) -> list[str | None]:
+        if isinstance(value, list):
+            return value
+        multi_value = len(self.widget.widgets) * [None]
+        if "external_link" in value:
+            pos = self._get_pos("external_link")
+            multi_value[0] = "external_link"
+            multi_value[pos] = value["external_link"]
+        elif "internal_link" in value:
+            pos = self._get_pos("internal_link")
+            anchor_pos = self._get_pos("anchor")
+            multi_value[0] = "internal_link"
+            multi_value[pos] = value["internal_link"]
+            multi_value[anchor_pos] = value.get("anchor", "")
+        elif "file_link" in value:
+            multi_value[0] = "file_link"
+            pos = self._get_pos("file_link")
+            multi_value[pos] = str(value["file_link"])
+        return multi_value
+
+    def to_python(self, value: list[str | None]) -> dict:
+        """Turn MultiWidget list data into LinkField dict format"""
+        if not value:
+            return LinkDict()
+
+        link_type = value[0]
+        pos = self._get_pos(link_type)
+        if not pos:  # No link type selected
+            return LinkDict()
+        pos_anchor = self._get_pos("anchor")
+
+        python = LinkDict({link_type: value[pos]} if value[pos] else {})
+        if python and link_type == "internal_link" and pos_anchor and value[pos_anchor]:
+            python["anchor"] = value[pos_anchor]
+        return python
+
+    def run_validators(self, value: LinkDict):
+        """Check for <link_type>_validators property and run the validators"""
+        for link_type in link_types:
+            if link_type in value:
+                self.validators = getattr(self, f"{link_type}_validators", [])
+                super().run_validators(value[link_type])
+        if "anchor" in value:
+            self.validators = getattr(self, "anchor_validators", [])
+            super().run_validators(value["anchor"])
+
+    def _get_pos(self, link_type):
+        """Returns the position of the different link type widgets"""
+        return self.widget.data_pos.get(link_type)
+
+
+class LinkField(JSONField):
+    """A link is a JSON field with a default LinkFormField"""
+
+    def __init__(self, *args, **kwargs):
+        kwargs.setdefault("default", dict)
+        kwargs.setdefault("help_text", "-")  # Help text is set by the widget
+        super().__init__(*args, **kwargs)
 
+    def formfield(self, **kwargs):
+        kwargs.setdefault("form_class", LinkFormField)
+        return super().formfield(**kwargs)
 
-def is_select2_enabled():
-    use_select2 = getattr(settings, 'DJANGOCMS_LINK_USE_SELECT2', False)
-    is_installed = 'django_select2' in settings.INSTALLED_APPS
-    return use_select2 and is_installed
+    def get_prep_value(self, value):
+        if isinstance(value, dict):
+            # Drop any cached value without changing the original value
+            return super().get_prep_value(dict(**{
+                key: val for key, val in value.items() if key != "__cache__"
+            }))
+        return super().get_prep_value(value)
 
+    def from_db_value(self, value, expression, connection):
+        value = super().from_db_value(value, expression, connection)
+        return LinkDict(value)
 
-if is_select2_enabled():
-    from djangocms_link.fields_select2 import Select2PageSearchField as PageSearchField  # noqa
-else:
-    from cms.forms.fields import PageSelectFormField as PageSearchField  # noqa
+    def to_python(self, value):
+        value = super().to_python(value)
+        return LinkDict(value)
diff --git a/djangocms_link/fields_select2.py b/djangocms_link/fields_select2.py
deleted file mode 100644
index 7b98a661..00000000
--- a/djangocms_link/fields_select2.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from django import forms
-
-from cms.models import Page
-
-from django_select2.forms import ModelSelect2Widget
-
-from djangocms_link.helpers import get_queryset_manager
-
-
-class Select2PageSearchFieldMixin:
-    search_fields = [
-        'title_set__title__icontains',
-        'title_set__menu_title__icontains',
-        'title_set__slug__icontains'
-    ]
-
-    def label_from_instance(self, obj):
-        return obj.get_title()
-
-
-class Select2PageSelectWidget(Select2PageSearchFieldMixin, ModelSelect2Widget):
-    site = None
-
-    # show entries when clicking on it
-    def build_attrs(self, base_attrs, extra_attrs=None):
-        default_attrs = {"data-minimum-input-length": 0}
-        default_attrs.update(base_attrs)
-        attrs = super().build_attrs(default_attrs, extra_attrs=extra_attrs)
-        return attrs
-
-    def get_queryset(self):
-        # django CMS < 4
-        base_queryset = get_queryset_manager(Page.objects)
-        if self.site:
-            return base_queryset.on_site(self.site)
-        return base_queryset.all()
-
-    # we need to implement jQuery ourselves, see #180
-    class Media:
-        js = (
-            "https://code.jquery.com/jquery-3.5.1.slim.min.js",
-        )
-
-
-class Select2PageSearchField(forms.ModelChoiceField):
-    widget = Select2PageSelectWidget()
-
-    def __init__(self, *args, **kwargs):
-        kwargs['queryset'] = self.widget.get_queryset()
-        super().__init__(*args, **kwargs)
diff --git a/djangocms_link/forms.py b/djangocms_link/forms.py
deleted file mode 100644
index 6700ff09..00000000
--- a/djangocms_link/forms.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from django.forms.models import ModelForm
-from django.utils.translation import gettext_lazy as _
-
-from djangocms_attributes_field.widgets import AttributesWidget
-
-from djangocms_link.helpers import get_queryset_manager
-
-from .fields import PageSearchField
-from .models import Link
-
-
-class LinkForm(ModelForm):
-    internal_link = PageSearchField(
-        label=_('Internal link'),
-        required=False,
-    )
-
-    def for_site(self, site):
-        # override the internal_link fields queryset to contains just pages for
-        # current site
-        # this will work for PageSelectFormField
-        from cms.models import Page
-        self.fields['internal_link'].queryset = get_queryset_manager(Page.objects).on_site(site)
-        # set the current site as a internal_link field instance attribute
-        # this will be used by the field later to properly set up the queryset
-        # this will work for PageSearchField
-        self.fields['internal_link'].site = site
-        self.fields['internal_link'].widget.site = site
-
-    class Meta:
-        model = Link
-        exclude = ('page', 'position', 'placeholder', 'language', 'plugin_type')
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.fields['attributes'].widget = AttributesWidget()
diff --git a/djangocms_link/helpers.py b/djangocms_link/helpers.py
index e507114c..00d4aeb4 100644
--- a/djangocms_link/helpers.py
+++ b/djangocms_link/helpers.py
@@ -1,4 +1,115 @@
-def get_queryset_manager(base):
-    if hasattr(base, "drafts"):
-        return base.drafts()
-    return base
+from __future__ import annotations
+
+from django.apps import apps
+from django.contrib.sites.models import Site
+from django.db import models
+
+
+try:
+    from filer.models import File
+except (ModuleNotFoundError, ImportError):  # pragma: no cover
+    File = None
+
+
+def get_manager(model: models.Model, current_content: bool = False) -> models.Manager:
+    if hasattr(model, "admin_manager"):
+        return (
+            model.admin_manager.current_content()
+            if current_content
+            else model.admin_manager
+        )
+    return model.objects
+
+
+def get_rel_obj(internal_link: str) -> models.Model | None:
+    if ":" in internal_link:
+        model, pk = internal_link.split(":", 1)
+        model = apps.get_model(*model.split(".", 1))
+        return get_manager(model).filter(pk=pk).first()
+
+
+def get_link(link_field_value: dict, site_id: int | None = None) -> str | None:
+    if not link_field_value:
+        return None
+    if "external_link" in link_field_value:
+        if link_field_value["external_link"].startswith("tel:"):
+            return link_field_value["external_link"].replace(" ", "")
+        return link_field_value["external_link"] or None
+
+    if "__cache__" in link_field_value:
+        return link_field_value["__cache__"] or None
+
+    if "internal_link" in link_field_value:
+        obj = get_rel_obj(link_field_value["internal_link"])
+    elif "file_link" in link_field_value:
+        obj = get_rel_obj("filer.file:" + str(link_field_value["file_link"]))
+    else:  # pragma: no cover
+        return None
+
+    if hasattr(obj, "get_absolute_url"):
+        # Access site id if possible (no db access necessary)
+        if site_id is None:
+            site_id = Site.objects.get_current().id
+        obj_site_id = getattr(
+            obj, "site_id", getattr(getattr(obj, "node", None), "site_id", None)
+        )
+        link_field_value["__cache__"] = obj.get_absolute_url()  # Can be None
+        if obj_site_id and obj_site_id != site_id:
+            ref_site = Site.objects._get_site_by_id(obj_site_id).domain
+            link_field_value["__cache__"] = (
+                f"//{ref_site}{link_field_value['__cache__']}"
+            )
+        if link_field_value["__cache__"]:
+            link_field_value["__cache__"] += link_field_value.get("anchor", "")
+    elif hasattr(obj, "url"):
+        link_field_value["__cache__"] = obj.url
+    else:
+        link_field_value["__cache__"] = None
+    return link_field_value["__cache__"]
+
+
+class LinkDict(dict):
+    """dict subclass with two additional properties: url and type to easily infer the link type and
+    the url of the link. The url property is cached to avoid multiple db lookups."""
+
+    def __init__(self, initial=None, **kwargs):
+        anchor = kwargs.pop("anchor", None)
+        super().__init__(**kwargs)
+        if initial:
+            if isinstance(initial, dict):
+                self.update(initial)
+            elif isinstance(initial, str):
+                self["external_link"] = initial
+            elif isinstance(initial, File):
+                self["file_link"] = initial.pk
+            elif isinstance(initial, models.Model):
+                self["internal_link"] = (
+                    f"{initial._meta.app_label}.{initial._meta.model_name}:{initial.pk}"
+                )
+                self["__cache__"] = initial.get_absolute_url()
+                if anchor:
+                    self["anchor"] = anchor
+                    self["__cache__"] += anchor
+
+    @property
+    def url(self):
+        return get_link(self) or ""
+
+    @property
+    def type(self):
+        for key in ("internal_link", "file_link"):
+            if key in self:
+                return key
+        if "external_link" in self:
+            if self["external_link"].startswith("tel:"):
+                return "tel"
+            if self["external_link"].startswith("mailto:"):
+                return "mailto"
+            if self["external_link"].startswith("#"):
+                return "anchor"
+            return "external_link"
+        return ""
+
+    def __str__(self):
+        """If inserted into a Django template, expand the url."""
+        return self.url
diff --git a/djangocms_link/locale/af/LC_MESSAGES/django.mo b/djangocms_link/locale/af/LC_MESSAGES/django.mo
index 73686466..419543d1 100644
Binary files a/djangocms_link/locale/af/LC_MESSAGES/django.mo and b/djangocms_link/locale/af/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/af/LC_MESSAGES/django.po b/djangocms_link/locale/af/LC_MESSAGES/django.po
index a622e683..de90c97e 100644
--- a/djangocms_link/locale/af/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/af/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Afrikaans (https://www.transifex.com/divio/teams/58664/af/)\n"
+"Language-Team: Afrikaans (https://app.transifex.com/divio/teams/58664/af/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: af\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/ar/LC_MESSAGES/django.mo b/djangocms_link/locale/ar/LC_MESSAGES/django.mo
index 73efaaee..13fdb9b8 100644
Binary files a/djangocms_link/locale/ar/LC_MESSAGES/django.mo and b/djangocms_link/locale/ar/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ar/LC_MESSAGES/django.po b/djangocms_link/locale/ar/LC_MESSAGES/django.po
index 7e188d28..cd52f0a4 100644
--- a/djangocms_link/locale/ar/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ar/LC_MESSAGES/django.po
@@ -11,122 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Bashar Ghadanfar <10.tens@gmail.com>, 2017\n"
-"Language-Team: Arabic (https://www.transifex.com/divio/teams/58664/ar/)\n"
+"Language-Team: Arabic (https://app.transifex.com/divio/teams/58664/ar/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ar\n"
 "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "رابط"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "إعدادات الربط"
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr "إعدادات متقدمة"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr "رابط داخلي"
 
-#: models.py:27
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr ""
+
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
+msgstr ""
+
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:177
+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."
+msgstr ""
+
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
+msgstr ""
+
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
+msgstr ""
+
+#: djangocms_link/fields.py:194
+msgid "#anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
+msgstr ""
+
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
+msgstr ""
+
+#: djangocms_link/fields.py:215
+msgid "Select site"
+msgstr ""
+
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
+msgstr ""
+
+#: djangocms_link/models.py:24
 msgid "Default"
 msgstr "افتراضي"
 
-#: models.py:44
+#: djangocms_link/models.py:41
 msgid "Open in new window"
 msgstr "فتح في نافذة جديدة"
 
-#: models.py:45
+#: djangocms_link/models.py:42
 msgid "Open in same window"
 msgstr "فتح في نفس النافذة"
 
-#: models.py:46
+#: djangocms_link/models.py:43
 msgid "Delegate to parent"
 msgstr "إنابة إلى الأصل"
 
-#: models.py:47
+#: djangocms_link/models.py:44
 msgid "Delegate to top"
 msgstr "إنابة إلى الأعلى"
 
-#: models.py:65
+#: djangocms_link/models.py:61
 msgid "Template"
 msgstr "قالب"
 
-#: models.py:71
+#: djangocms_link/models.py:67
 msgid "Display name"
 msgstr "الاسم الظاهر"
 
-#: models.py:77
-msgid "External link"
-msgstr "رابط خارجي"
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr "يغلَّب على الرابط الخارجي في حال إضافته."
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr "مثبت الرابط"
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-"يُلحق حصراً بآخر الرابط الداخلي أو الخارجي. يجب أن <em>لا</em> يُسبق بالرمز "
-"\"#\"."
-
-#: models.py:109
-msgid "Email address"
-msgstr "بريد إلكتروني"
-
-#: models.py:114
-msgid "Phone"
-msgstr "هاتف"
-
-#: models.py:120
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr "المستهدَف"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr "صفات"
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr "<link is missing>"
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr "يمكن إعطاء واحداً فقط من {0} أو {1}."
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr "يُرجى تزويد رابط."
+#: djangocms_link/models.py:118
+msgid "Link is required."
+msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr "%(anchor_field_verbose_name)s غير مسموح به سويا‏ً مع %(field_name)s"
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
+msgstr ""
 
-#~ msgid "At least one link is required."
-#~ msgstr "مطلوب رابط واحد على الأقل."
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
+msgstr ""
diff --git a/djangocms_link/locale/be/LC_MESSAGES/django.mo b/djangocms_link/locale/be/LC_MESSAGES/django.mo
index 8b27f89b..1e7e8ff5 100644
Binary files a/djangocms_link/locale/be/LC_MESSAGES/django.mo and b/djangocms_link/locale/be/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/be/LC_MESSAGES/django.po b/djangocms_link/locale/be/LC_MESSAGES/django.po
index 7b8e73a1..1e010511 100644
--- a/djangocms_link/locale/be/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/be/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Belarusian (https://www.transifex.com/divio/teams/58664/be/)\n"
+"Language-Team: Belarusian (https://app.transifex.com/divio/teams/58664/be/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: be\n"
 "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/bg/LC_MESSAGES/django.mo b/djangocms_link/locale/bg/LC_MESSAGES/django.mo
index f5067d28..1377b3cc 100644
Binary files a/djangocms_link/locale/bg/LC_MESSAGES/django.mo and b/djangocms_link/locale/bg/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/bg/LC_MESSAGES/django.po b/djangocms_link/locale/bg/LC_MESSAGES/django.po
index d427bcfe..e268efcd 100644
--- a/djangocms_link/locale/bg/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/bg/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Bulgarian (https://www.transifex.com/divio/teams/58664/bg/)\n"
+"Language-Team: Bulgarian (https://app.transifex.com/divio/teams/58664/bg/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: bg\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "Връзка"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/bn/LC_MESSAGES/django.mo b/djangocms_link/locale/bn/LC_MESSAGES/django.mo
index e558c458..e9a579bd 100644
Binary files a/djangocms_link/locale/bn/LC_MESSAGES/django.mo and b/djangocms_link/locale/bn/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/bn/LC_MESSAGES/django.po b/djangocms_link/locale/bn/LC_MESSAGES/django.po
index 051f30a9..009cea72 100644
--- a/djangocms_link/locale/bn/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/bn/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Bengali (https://www.transifex.com/divio/teams/58664/bn/)\n"
+"Language-Team: Bengali (https://app.transifex.com/divio/teams/58664/bn/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: bn\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "লিংক"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/ca/LC_MESSAGES/django.mo b/djangocms_link/locale/ca/LC_MESSAGES/django.mo
index 6bdbaa87..034b2c0f 100644
Binary files a/djangocms_link/locale/ca/LC_MESSAGES/django.mo and b/djangocms_link/locale/ca/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ca/LC_MESSAGES/django.po b/djangocms_link/locale/ca/LC_MESSAGES/django.po
index 078ae3fc..223b83a1 100644
--- a/djangocms_link/locale/ca/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ca/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Catalan (https://www.transifex.com/divio/teams/58664/ca/)\n"
+"Language-Team: Catalan (https://app.transifex.com/divio/teams/58664/ca/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ca\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Enllaç"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Telèfon"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr "Es requereix com a mínim un enllaç."
diff --git a/djangocms_link/locale/cmn/LC_MESSAGES/django.mo b/djangocms_link/locale/cmn/LC_MESSAGES/django.mo
index dc22dadc..e40fe7b4 100644
Binary files a/djangocms_link/locale/cmn/LC_MESSAGES/django.mo and b/djangocms_link/locale/cmn/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/cmn/LC_MESSAGES/django.po b/djangocms_link/locale/cmn/LC_MESSAGES/django.po
index 8cadc3c8..822488c0 100644
--- a/djangocms_link/locale/cmn/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/cmn/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Chinese (Mandarin) (https://www.transifex.com/divio/teams/58664/cmn/)\n"
+"Language-Team: Chinese (Mandarin) (https://app.transifex.com/divio/teams/58664/cmn/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: cmn\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/cs/LC_MESSAGES/django.mo b/djangocms_link/locale/cs/LC_MESSAGES/django.mo
index b47fc49a..3dec9746 100644
Binary files a/djangocms_link/locale/cs/LC_MESSAGES/django.mo and b/djangocms_link/locale/cs/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/cs/LC_MESSAGES/django.po b/djangocms_link/locale/cs/LC_MESSAGES/django.po
index a9dd3d48..4269987d 100644
--- a/djangocms_link/locale/cs/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/cs/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Czech (https://www.transifex.com/divio/teams/58664/cs/)\n"
+"Language-Team: Czech (https://app.transifex.com/divio/teams/58664/cs/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: cs\n"
 "Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Odkaz"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Telefon"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr "Je vyžadován alespoň jeden odkaz."
diff --git a/djangocms_link/locale/cs_CZ/LC_MESSAGES/django.mo b/djangocms_link/locale/cs_CZ/LC_MESSAGES/django.mo
deleted file mode 100644
index 511fe1a5..00000000
Binary files a/djangocms_link/locale/cs_CZ/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/cs_CZ/LC_MESSAGES/django.po b/djangocms_link/locale/cs_CZ/LC_MESSAGES/django.po
deleted file mode 100644
index ef03c2b6..00000000
--- a/djangocms_link/locale/cs_CZ/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Czech (Czech Republic) (https://www.transifex.com/divio/teams/58664/cs_CZ/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: cs_CZ\n"
-"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/cy/LC_MESSAGES/django.mo b/djangocms_link/locale/cy/LC_MESSAGES/django.mo
index ab92bbeb..56abdc7e 100644
Binary files a/djangocms_link/locale/cy/LC_MESSAGES/django.mo and b/djangocms_link/locale/cy/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/cy/LC_MESSAGES/django.po b/djangocms_link/locale/cy/LC_MESSAGES/django.po
index fde9132f..653f6be7 100644
--- a/djangocms_link/locale/cy/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/cy/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Welsh (https://www.transifex.com/divio/teams/58664/cy/)\n"
+"Language-Team: Welsh (https://app.transifex.com/divio/teams/58664/cy/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: cy\n"
 "Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/da/LC_MESSAGES/django.mo b/djangocms_link/locale/da/LC_MESSAGES/django.mo
index 0930a153..14ccf09a 100644
Binary files a/djangocms_link/locale/da/LC_MESSAGES/django.mo and b/djangocms_link/locale/da/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/da/LC_MESSAGES/django.po b/djangocms_link/locale/da/LC_MESSAGES/django.po
index 2633931f..d3b3c20f 100644
--- a/djangocms_link/locale/da/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/da/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Danish (https://www.transifex.com/divio/teams/58664/da/)\n"
+"Language-Team: Danish (https://app.transifex.com/divio/teams/58664/da/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: da\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Link"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Telefon"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/de/LC_MESSAGES/django.mo b/djangocms_link/locale/de/LC_MESSAGES/django.mo
index 7be5340e..a4939469 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 ddbfbd95..73279e04 100644
--- a/djangocms_link/locale/de/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/de/LC_MESSAGES/django.po
@@ -6,128 +6,145 @@
 # Translators:
 # danielastreuli <daniela.streuli@divio.ch>, 2016
 # Angelo Dini <angelo.dini@divio.ch>, 2019
+# Fabian Braun <fsbraun@gmx.de>, 2024
 # 
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2019\n"
-"Language-Team: German (https://www.transifex.com/divio/teams/58664/de/)\n"
+"Last-Translator: Fabian Braun <fsbraun@gmx.de>, 2024\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"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: de\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr "django CMS Link"
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Link"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "Link-Einstellungen"
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr "Erweiterte Einstellungen"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr "Interner Link"
 
-#: models.py:27
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
+msgstr "Externer Link/Anker"
+
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr "Datei Link"
+
+#: djangocms_link/fields.py:169
+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
+msgid "https://example.com or #anchor"
+msgstr "https://beispiel.de oder #anker"
+
+#: djangocms_link/fields.py:177
+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."
+msgstr ""
+"Link zu einer externen URL angeben, inklusive Schema wie z.B. \"https://\", "
+"\"tel:\" oder \"mailto:\". Optional einen \"#anker\" hinzufügen (inklusive "
+"#)."
+
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
+msgstr ""
+"Aus den verfügbaren internen Zielen auswählen. Optional einen Anker "
+"hinzufügen."
+
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
+msgstr "Internes Ziel auswählen"
+
+#: djangocms_link/fields.py:194
+msgid "#anchor"
+msgstr "#anker"
+
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
+msgstr "Anker angeben, der angesprungen wird."
+
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
+msgstr "Datei als Ziel auswählen."
+
+#: djangocms_link/fields.py:215
+msgid "Select site"
+msgstr "Site auswählen"
+
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
+msgstr "Link-Typ auswählen und Ziel angeben."
+
+#: djangocms_link/models.py:24
 msgid "Default"
 msgstr "Standard"
 
-#: models.py:44
+#: djangocms_link/models.py:41
 msgid "Open in new window"
 msgstr "In neuem Fenster öffnen"
 
-#: models.py:45
+#: djangocms_link/models.py:42
 msgid "Open in same window"
 msgstr "Im gleichen Fenster öffnen"
 
-#: models.py:46
+#: djangocms_link/models.py:43
 msgid "Delegate to parent"
 msgstr "Zum nächsten Fenster delegieren"
 
-#: models.py:47
+#: djangocms_link/models.py:44
 msgid "Delegate to top"
 msgstr "Zum obersten Fenster delegieren"
 
-#: models.py:65
+#: djangocms_link/models.py:61
 msgid "Template"
 msgstr "Template"
 
-#: models.py:71
+#: djangocms_link/models.py:67
 msgid "Display name"
 msgstr "Anzeigename"
 
-#: models.py:77
-msgid "External link"
-msgstr "Externer Link"
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr "Überschreibt den externen Link, falls angegeben."
-
-#: models.py:93
-msgid "File link"
-msgstr "Datei Link"
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr "Nutzt eine Datei als Link."
-
-#: models.py:102
-msgid "Anchor"
-msgstr "Anker"
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-"Fügt den Wert am Ende des internen oder externen Links an. Bitte "
-"<em>kein</em> vorangehendes \"#\" Symbol angeben."
-
-#: models.py:109
-msgid "Email address"
-msgstr "E-Mail-Adresse"
-
-#: models.py:114
-msgid "Phone"
-msgstr "Telefon"
-
-#: models.py:120
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr "Verweis"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr "Attribute"
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr "<link nicht vorhanden>"
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr "Nur eines von {0} oder {1} darf angegeben werden."
+#: djangocms_link/models.py:118
+msgid "Link is required."
+msgstr "Der Link ist ein Pflichtfeld."
 
-#: models.py:258
-msgid "Please provide a link."
-msgstr "Es muss ein Link angegeben werden."
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr "%(anchor_field_verbose_name)s ist mit %(field_name)s nicht erlaubt"
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
+msgstr "Gültigen Anker angeben"
 
-#~ msgid "At least one link is required."
-#~ msgstr "Es muss mindestens ein Link angegeben werden."
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
+msgstr "Gültige Telefonnummer angeben"
diff --git a/djangocms_link/locale/el/LC_MESSAGES/django.mo b/djangocms_link/locale/el/LC_MESSAGES/django.mo
index 5a4eae66..8d934fb8 100644
Binary files a/djangocms_link/locale/el/LC_MESSAGES/django.mo and b/djangocms_link/locale/el/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/el/LC_MESSAGES/django.po b/djangocms_link/locale/el/LC_MESSAGES/django.po
index e12f62d2..f367bdd9 100644
--- a/djangocms_link/locale/el/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/el/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Greek (https://www.transifex.com/divio/teams/58664/el/)\n"
+"Language-Team: Greek (https://app.transifex.com/divio/teams/58664/el/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: el\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Σύνδεσμος"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Tηλέφωνο"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/en/LC_MESSAGES/django.mo b/djangocms_link/locale/en/LC_MESSAGES/django.mo
index 153304bd..a036668d 100644
Binary files a/djangocms_link/locale/en/LC_MESSAGES/django.mo and b/djangocms_link/locale/en/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/en/LC_MESSAGES/django.po b/djangocms_link/locale/en/LC_MESSAGES/django.po
index 6804924f..a4603d79 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: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,120 +16,124 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "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
+msgid "django CMS Link"
+msgstr ""
 
-#: cms_plugins.py:15
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Link"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "Link settings"
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr "Advanced settings"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr "Internal link"
 
-#: models.py:27
-msgid "Default"
-msgstr "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
+msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
-msgstr "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
-msgstr "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
+msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
-msgstr "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
+msgstr "https://example.com or #anchor"
 
-#: models.py:47
-msgid "Delegate to top"
-msgstr "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
+msgstr ""
 
-#: models.py:65
-msgid "Template"
-msgstr "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
+msgstr ""
 
-#: models.py:71
-msgid "Display name"
-msgstr "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
+msgstr ""
 
-#: models.py:77
-msgid "External link"
-msgstr "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
+msgstr ""
 
-#: models.py:81
-#, fuzzy
-#| msgid "Provide a valid URL to an external website."
-msgid "Provide a link to an external source."
-msgstr "Provide a valid URL to an external website."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
+msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr "If provided, overrides the external link."
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
+msgstr ""
 
-#: models.py:93
-msgid "File link"
-msgstr "File link"
+#: djangocms_link/fields.py:215
+msgid "Select site"
+msgstr "Select site"
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr "If provided links a file from the filer app."
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
+msgstr ""
 
-#: models.py:102
-msgid "Anchor"
-msgstr "Anchor"
+#: djangocms_link/models.py:24
+msgid "Default"
+msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: djangocms_link/models.py:42
+msgid "Open in same window"
 msgstr ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
 
-#: models.py:109
-msgid "Email address"
-msgstr "Email address"
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Phone"
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
-msgstr "Target"
+msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
-msgstr "Attributes"
+msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
-msgstr "<link is missing>"
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr "Only one of {0} or {1} may be given."
+msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
-msgstr "Please provide a link."
+#: djangocms_link/models.py:118
+msgid "Link is required."
+msgstr "Link is required."
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
+msgstr "Enter a valid anchor"
 
-#~ msgid "At least one link is required."
-#~ msgstr "At least one link is required."
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
+msgstr "Enter a valid phone number"
diff --git a/djangocms_link/locale/en_GB/LC_MESSAGES/django.mo b/djangocms_link/locale/en_GB/LC_MESSAGES/django.mo
index 625abdf4..8bcafdcf 100644
Binary files a/djangocms_link/locale/en_GB/LC_MESSAGES/django.mo and b/djangocms_link/locale/en_GB/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/en_GB/LC_MESSAGES/django.po b/djangocms_link/locale/en_GB/LC_MESSAGES/django.po
index a9a213d7..b3e119b9 100644
--- a/djangocms_link/locale/en_GB/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/en_GB/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: English (United Kingdom) (https://www.transifex.com/divio/teams/58664/en_GB/)\n"
+"Language-Team: English (United Kingdom) (https://app.transifex.com/divio/teams/58664/en_GB/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: en_GB\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/en_HK/LC_MESSAGES/django.mo b/djangocms_link/locale/en_HK/LC_MESSAGES/django.mo
deleted file mode 100644
index c10213f2..00000000
Binary files a/djangocms_link/locale/en_HK/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/en_HK/LC_MESSAGES/django.po b/djangocms_link/locale/en_HK/LC_MESSAGES/django.po
deleted file mode 100644
index 9dc120a1..00000000
--- a/djangocms_link/locale/en_HK/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: English (Hong Kong) (https://www.transifex.com/divio/teams/58664/en_HK/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: en_HK\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/en_US/LC_MESSAGES/django.mo b/djangocms_link/locale/en_US/LC_MESSAGES/django.mo
index 4294557a..d6531063 100644
Binary files a/djangocms_link/locale/en_US/LC_MESSAGES/django.mo and b/djangocms_link/locale/en_US/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/en_US/LC_MESSAGES/django.po b/djangocms_link/locale/en_US/LC_MESSAGES/django.po
index 8179f5e0..0075cb12 100644
--- a/djangocms_link/locale/en_US/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/en_US/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: English (United States) (https://www.transifex.com/divio/teams/58664/en_US/)\n"
+"Language-Team: English (United States) (https://app.transifex.com/divio/teams/58664/en_US/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: en_US\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/eo/LC_MESSAGES/django.mo b/djangocms_link/locale/eo/LC_MESSAGES/django.mo
index 7ab61d69..744f213f 100644
Binary files a/djangocms_link/locale/eo/LC_MESSAGES/django.mo and b/djangocms_link/locale/eo/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/eo/LC_MESSAGES/django.po b/djangocms_link/locale/eo/LC_MESSAGES/django.po
index 69fd56b9..c7d4cf08 100644
--- a/djangocms_link/locale/eo/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/eo/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Esperanto (https://www.transifex.com/divio/teams/58664/eo/)\n"
+"Language-Team: Esperanto (https://app.transifex.com/divio/teams/58664/eo/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: eo\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/es/LC_MESSAGES/django.mo b/djangocms_link/locale/es/LC_MESSAGES/django.mo
index a326e670..dee95407 100644
Binary files a/djangocms_link/locale/es/LC_MESSAGES/django.mo and b/djangocms_link/locale/es/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/es/LC_MESSAGES/django.po b/djangocms_link/locale/es/LC_MESSAGES/django.po
index 1125fd51..89e4183a 100644
--- a/djangocms_link/locale/es/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/es/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Spanish (https://www.transifex.com/divio/teams/58664/es/)\n"
+"Language-Team: Spanish (https://app.transifex.com/divio/teams/58664/es/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: es\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/es_AR/LC_MESSAGES/django.mo b/djangocms_link/locale/es_AR/LC_MESSAGES/django.mo
deleted file mode 100644
index a2c86927..00000000
Binary files a/djangocms_link/locale/es_AR/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/es_AR/LC_MESSAGES/django.po b/djangocms_link/locale/es_AR/LC_MESSAGES/django.po
deleted file mode 100644
index 7b40b976..00000000
--- a/djangocms_link/locale/es_AR/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,130 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Spanish (Argentina) (https://www.transifex.com/divio/teams/58664/es_AR/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: es_AR\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "Enlace"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr "Teléfono"
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr "Se requiere al menos un enlace"
diff --git a/djangocms_link/locale/es_BO/LC_MESSAGES/django.mo b/djangocms_link/locale/es_BO/LC_MESSAGES/django.mo
deleted file mode 100644
index 1db60479..00000000
Binary files a/djangocms_link/locale/es_BO/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/es_BO/LC_MESSAGES/django.po b/djangocms_link/locale/es_BO/LC_MESSAGES/django.po
deleted file mode 100644
index 414289d1..00000000
--- a/djangocms_link/locale/es_BO/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,130 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Spanish (Bolivia) (https://www.transifex.com/divio/teams/58664/es_BO/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: es_BO\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "Enlace"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/es_DO/LC_MESSAGES/django.mo b/djangocms_link/locale/es_DO/LC_MESSAGES/django.mo
deleted file mode 100644
index 335c84b0..00000000
Binary files a/djangocms_link/locale/es_DO/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/es_DO/LC_MESSAGES/django.po b/djangocms_link/locale/es_DO/LC_MESSAGES/django.po
deleted file mode 100644
index a2aae5f9..00000000
--- a/djangocms_link/locale/es_DO/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Spanish (Dominican Republic) (https://www.transifex.com/divio/teams/58664/es_DO/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: es_DO\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/et/LC_MESSAGES/django.mo b/djangocms_link/locale/et/LC_MESSAGES/django.mo
index 9d2a58b3..c24cbb1e 100644
Binary files a/djangocms_link/locale/et/LC_MESSAGES/django.mo and b/djangocms_link/locale/et/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/et/LC_MESSAGES/django.po b/djangocms_link/locale/et/LC_MESSAGES/django.po
index 01414b41..256d0bbe 100644
--- a/djangocms_link/locale/et/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/et/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Estonian (https://www.transifex.com/divio/teams/58664/et/)\n"
+"Language-Team: Estonian (https://app.transifex.com/divio/teams/58664/et/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: et\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Link"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Telefon"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/eu/LC_MESSAGES/django.mo b/djangocms_link/locale/eu/LC_MESSAGES/django.mo
index 1add583d..8b8f0a89 100644
Binary files a/djangocms_link/locale/eu/LC_MESSAGES/django.mo and b/djangocms_link/locale/eu/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/eu/LC_MESSAGES/django.po b/djangocms_link/locale/eu/LC_MESSAGES/django.po
index e093204a..80635513 100644
--- a/djangocms_link/locale/eu/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/eu/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Basque (https://www.transifex.com/divio/teams/58664/eu/)\n"
+"Language-Team: Basque (https://app.transifex.com/divio/teams/58664/eu/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: eu\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "Esteka"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/fa/LC_MESSAGES/django.mo b/djangocms_link/locale/fa/LC_MESSAGES/django.mo
index 8ca4d623..0bfa16e5 100644
Binary files a/djangocms_link/locale/fa/LC_MESSAGES/django.mo and b/djangocms_link/locale/fa/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/fa/LC_MESSAGES/django.po b/djangocms_link/locale/fa/LC_MESSAGES/django.po
index 99e516a3..9518c221 100644
--- a/djangocms_link/locale/fa/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/fa/LC_MESSAGES/django.po
@@ -12,120 +12,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Fariman Ghaedi <farimanghaedi@gmail.com>, 2018\n"
-"Language-Team: Persian (https://www.transifex.com/divio/teams/58664/fa/)\n"
+"Language-Team: Persian (https://app.transifex.com/divio/teams/58664/fa/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: fa\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "پیوند"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "تنظیمات لینک"
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr "تنظیمات پیشرفته"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr "لینک داخلی"
 
-#: models.py:27
-msgid "Default"
-msgstr "پیشفرض"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
+msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
-msgstr "باز کردن در پنجره تازه"
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
-msgstr "باز کردن در همان پنجره"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
+msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
-msgstr "الگو"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
+msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
-msgstr "لینک خارجی"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
+msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
-msgstr "لنگر"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
+msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
+msgstr "پیشفرض"
+
+#: djangocms_link/models.py:41
+msgid "Open in new window"
+msgstr "باز کردن در پنجره تازه"
+
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr "باز کردن در همان پنجره"
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
-msgstr "آدرس ایمیل"
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "تلفن"
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr "الگو"
 
-#: models.py:120
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr "هدف"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr "ویژگی"
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
-msgstr "لطفا یک لینک مهیا کنید"
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#~ msgid "At least one link is required."
-#~ msgstr "‌حداقل یک لینک مورد نیاز است."
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
+msgstr ""
diff --git a/djangocms_link/locale/fa_IR/LC_MESSAGES/django.mo b/djangocms_link/locale/fa_IR/LC_MESSAGES/django.mo
deleted file mode 100644
index e4d4f675..00000000
Binary files a/djangocms_link/locale/fa_IR/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/fa_IR/LC_MESSAGES/django.po b/djangocms_link/locale/fa_IR/LC_MESSAGES/django.po
deleted file mode 100644
index 6720b36d..00000000
--- a/djangocms_link/locale/fa_IR/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Persian (Iran) (https://www.transifex.com/divio/teams/58664/fa_IR/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: fa_IR\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/fi/LC_MESSAGES/django.mo b/djangocms_link/locale/fi/LC_MESSAGES/django.mo
index 80465597..5883e379 100644
Binary files a/djangocms_link/locale/fi/LC_MESSAGES/django.mo and b/djangocms_link/locale/fi/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/fi/LC_MESSAGES/django.po b/djangocms_link/locale/fi/LC_MESSAGES/django.po
index b47579c3..6e205fba 100644
--- a/djangocms_link/locale/fi/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/fi/LC_MESSAGES/django.po
@@ -12,120 +12,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Ville-Eemeli Käkelä <ville-eemeli.kakela@bitfactor.fi>, 2018\n"
-"Language-Team: Finnish (https://www.transifex.com/divio/teams/58664/fi/)\n"
+"Language-Team: Finnish (https://app.transifex.com/divio/teams/58664/fi/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: fi\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Linkki"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "Linkin asetukset"
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr "Sisäinen linkki"
 
-#: models.py:27
-msgid "Default"
-msgstr "Oletus"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
+msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
-msgstr "Avaa uuteen ikkunaan"
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
-msgstr "Avaa samaan ikkunaan"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
+msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
-msgstr "Asettelupohja"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
+msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
+msgstr ""
+
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
-msgstr "Ulkoinen linkki"
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
+msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
-msgstr "Ankkuri"
+#: djangocms_link/models.py:24
+msgid "Default"
+msgstr "Oletus"
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:41
+msgid "Open in new window"
+msgstr "Avaa uuteen ikkunaan"
+
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr "Avaa samaan ikkunaan"
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
-msgstr "Sähköpostiosoite"
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Puhelin"
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr "Asettelupohja"
 
-#: models.py:120
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr "Kohde"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr "<link is missing>"
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/fi_FI/LC_MESSAGES/django.mo b/djangocms_link/locale/fi_FI/LC_MESSAGES/django.mo
deleted file mode 100644
index 075f7626..00000000
Binary files a/djangocms_link/locale/fi_FI/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/fi_FI/LC_MESSAGES/django.po b/djangocms_link/locale/fi_FI/LC_MESSAGES/django.po
deleted file mode 100644
index f65e536f..00000000
--- a/djangocms_link/locale/fi_FI/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Finnish (Finland) (https://www.transifex.com/divio/teams/58664/fi_FI/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: fi_FI\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/fr/LC_MESSAGES/django.mo b/djangocms_link/locale/fr/LC_MESSAGES/django.mo
index 6e085c5c..f8a972ba 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 d7e15622..7bac24c0 100644
--- a/djangocms_link/locale/fr/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/fr/LC_MESSAGES/django.po
@@ -4,129 +4,141 @@
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 # 
 # Translators:
-# Doryan R, 2019
+# a270031086f2a0d3514bc0cb507b48f6, 2019
+# Florian Delizy <florian.delizy@gmail.com>, 2021
 # 
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Doryan R, 2019\n"
-"Language-Team: French (https://www.transifex.com/divio/teams/58664/fr/)\n"
+"Last-Translator: Florian Delizy <florian.delizy@gmail.com>, 2021\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"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: fr\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Lien"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "Paramètres de lien"
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr "Réglages avancés"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr "Lien interne"
 
-#: models.py:27
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr "Lien vers le fichier"
+
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
+msgstr ""
+
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:177
+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."
+msgstr ""
+
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
+msgstr ""
+
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
+msgstr ""
+
+#: djangocms_link/fields.py:194
+msgid "#anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
+msgstr ""
+
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
+msgstr ""
+
+#: djangocms_link/fields.py:215
+msgid "Select site"
+msgstr ""
+
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
+msgstr ""
+
+#: djangocms_link/models.py:24
 msgid "Default"
 msgstr "Défaut"
 
-#: models.py:44
+#: djangocms_link/models.py:41
 msgid "Open in new window"
 msgstr "Ouvrir dans une nouvelle fenêtre"
 
-#: models.py:45
+#: djangocms_link/models.py:42
 msgid "Open in same window"
 msgstr "Ouvrir dans la même fenêtre"
 
-#: models.py:46
+#: djangocms_link/models.py:43
 msgid "Delegate to parent"
 msgstr "Déléguer au parent"
 
-#: models.py:47
+#: djangocms_link/models.py:44
 msgid "Delegate to top"
 msgstr "Délégué au sommet"
 
-#: models.py:65
+#: djangocms_link/models.py:61
 msgid "Template"
 msgstr "Modèle"
 
-#: models.py:71
+#: djangocms_link/models.py:67
 msgid "Display name"
 msgstr "Afficher un nom"
 
-#: models.py:77
-msgid "External link"
-msgstr "Lien externe"
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr "Si fourni, remplace le lien externe."
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr "Ancre"
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-"Ajoute la valeur uniquement après le lien interne ou externe. N'incluez "
-"<em>pas</em> le symbole \"#\" précédent."
-
-#: models.py:109
-msgid "Email address"
-msgstr "Adresse électronique"
-
-#: models.py:114
-msgid "Phone"
-msgstr "Téléphone"
-
-#: models.py:120
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr "Cible"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr "Les attributs"
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr "<link is missing>"
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr "Un seul des {0} ou {1} peut être donné."
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr "S'il vous plaît fournir un lien."
+#: djangocms_link/models.py:118
+msgid "Link is required."
+msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr "%(anchor_field_verbose_name)sn'est pas autorisé avec%(field_name)s"
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
+msgstr ""
 
-#~ msgid "At least one link is required."
-#~ msgstr "Au moins un lien est requis."
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
+msgstr ""
diff --git a/djangocms_link/locale/fr_CA/LC_MESSAGES/django.mo b/djangocms_link/locale/fr_CA/LC_MESSAGES/django.mo
deleted file mode 100644
index f43668c6..00000000
Binary files a/djangocms_link/locale/fr_CA/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/fr_CA/LC_MESSAGES/django.po b/djangocms_link/locale/fr_CA/LC_MESSAGES/django.po
deleted file mode 100644
index 9d034577..00000000
--- a/djangocms_link/locale/fr_CA/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: French (Canada) (https://www.transifex.com/divio/teams/58664/fr_CA/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: fr_CA\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/fr_FR/LC_MESSAGES/django.mo b/djangocms_link/locale/fr_FR/LC_MESSAGES/django.mo
deleted file mode 100644
index 8da5bc0e..00000000
Binary files a/djangocms_link/locale/fr_FR/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/fr_FR/LC_MESSAGES/django.po b/djangocms_link/locale/fr_FR/LC_MESSAGES/django.po
deleted file mode 100644
index 39d3756b..00000000
--- a/djangocms_link/locale/fr_FR/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,135 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Assma Buifruri <assma.buifruri@hotmail.com>, 2017
-# Adrien Delhorme, 2017
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Adrien Delhorme, 2017\n"
-"Language-Team: French (France) (https://www.transifex.com/divio/teams/58664/fr_FR/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: fr_FR\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "Lien"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "Paramètres du lien"
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr "Paramètres avancés"
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr "Lien interne"
-
-#: models.py:27
-msgid "Default"
-msgstr "Par défaut"
-
-#: models.py:44
-msgid "Open in new window"
-msgstr "Ouvrir dans une nouvelle fenêtre"
-
-#: models.py:45
-msgid "Open in same window"
-msgstr "Ouvrir dans la même fenêtre"
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr "Charger dans le cadre parent"
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr "Charger dans le corps entier de la fenêtre"
-
-#: models.py:65
-msgid "Template"
-msgstr "Modèle"
-
-#: models.py:71
-msgid "Display name"
-msgstr "Nom affiché"
-
-#: models.py:77
-msgid "External link"
-msgstr "Lien externe"
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr "Si renseigné, sera utilisé à la place du lien externe"
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr "Ancre"
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-"Ajouter seulement l'ancre qui suit le lien interne ou externe, <em>sans</em>"
-" le signe # au début."
-
-#: models.py:109
-msgid "Email address"
-msgstr "Adresse e-mail"
-
-#: models.py:114
-msgid "Phone"
-msgstr "Téléphone"
-
-#: models.py:120
-msgid "Target"
-msgstr "Cible"
-
-#: models.py:126
-msgid "Attributes"
-msgstr "Attributs"
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr "<lien manquant>"
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr "Seulement un des deux champs {0} ou {1} doit être rempli."
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr "Veuillez indiquer un lien."
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-"%(anchor_field_verbose_name)s ne peut être utilisé en même temps que "
-"%(field_name)s"
-
-#~ msgid "At least one link is required."
-#~ msgstr "Au moins un lien est requis"
diff --git a/djangocms_link/locale/ga/LC_MESSAGES/django.mo b/djangocms_link/locale/ga/LC_MESSAGES/django.mo
index 38daeb91..41898af1 100644
Binary files a/djangocms_link/locale/ga/LC_MESSAGES/django.mo and b/djangocms_link/locale/ga/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ga/LC_MESSAGES/django.po b/djangocms_link/locale/ga/LC_MESSAGES/django.po
index 8b60fa1a..5f49f66a 100644
--- a/djangocms_link/locale/ga/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ga/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Irish (https://www.transifex.com/divio/teams/58664/ga/)\n"
+"Language-Team: Irish (https://app.transifex.com/divio/teams/58664/ga/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ga\n"
 "Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/gl/LC_MESSAGES/django.mo b/djangocms_link/locale/gl/LC_MESSAGES/django.mo
index c60be34f..3e910eaa 100644
Binary files a/djangocms_link/locale/gl/LC_MESSAGES/django.mo and b/djangocms_link/locale/gl/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/gl/LC_MESSAGES/django.po b/djangocms_link/locale/gl/LC_MESSAGES/django.po
index f55e1266..bda88f5b 100644
--- a/djangocms_link/locale/gl/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/gl/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Galician (https://www.transifex.com/divio/teams/58664/gl/)\n"
+"Language-Team: Galician (https://app.transifex.com/divio/teams/58664/gl/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: gl\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "Ligazón"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/gu/LC_MESSAGES/django.mo b/djangocms_link/locale/gu/LC_MESSAGES/django.mo
index e5c560bd..fbd9472c 100644
Binary files a/djangocms_link/locale/gu/LC_MESSAGES/django.mo and b/djangocms_link/locale/gu/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/gu/LC_MESSAGES/django.po b/djangocms_link/locale/gu/LC_MESSAGES/django.po
index b4045a2d..cf7abf38 100644
--- a/djangocms_link/locale/gu/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/gu/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Gujarati (https://www.transifex.com/divio/teams/58664/gu/)\n"
+"Language-Team: Gujarati (https://app.transifex.com/divio/teams/58664/gu/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: gu\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/he/LC_MESSAGES/django.mo b/djangocms_link/locale/he/LC_MESSAGES/django.mo
index d70e9a85..6d5c6856 100644
Binary files a/djangocms_link/locale/he/LC_MESSAGES/django.mo and b/djangocms_link/locale/he/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/he/LC_MESSAGES/django.po b/djangocms_link/locale/he/LC_MESSAGES/django.po
index c4aec7b8..22b89884 100644
--- a/djangocms_link/locale/he/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/he/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Hebrew (https://www.transifex.com/divio/teams/58664/he/)\n"
+"Language-Team: Hebrew (https://app.transifex.com/divio/teams/58664/he/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: he\n"
-"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n"
+"Plural-Forms: nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "לינק"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/hi/LC_MESSAGES/django.mo b/djangocms_link/locale/hi/LC_MESSAGES/django.mo
index 80cc5d4f..9649925e 100644
Binary files a/djangocms_link/locale/hi/LC_MESSAGES/django.mo and b/djangocms_link/locale/hi/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/hi/LC_MESSAGES/django.po b/djangocms_link/locale/hi/LC_MESSAGES/django.po
index b15fcf5d..209d9aea 100644
--- a/djangocms_link/locale/hi/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/hi/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Hindi (https://www.transifex.com/divio/teams/58664/hi/)\n"
+"Language-Team: Hindi (https://app.transifex.com/divio/teams/58664/hi/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: hi\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr " लिंक"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/hr/LC_MESSAGES/django.mo b/djangocms_link/locale/hr/LC_MESSAGES/django.mo
index 88f3b8dd..42d3290b 100644
Binary files a/djangocms_link/locale/hr/LC_MESSAGES/django.mo and b/djangocms_link/locale/hr/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/hr/LC_MESSAGES/django.po b/djangocms_link/locale/hr/LC_MESSAGES/django.po
index f03a0af6..b4545f4c 100644
--- a/djangocms_link/locale/hr/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/hr/LC_MESSAGES/django.po
@@ -4,127 +4,140 @@
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 # 
 # Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
+# Aleks Acimovic, 2022
 # 
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Croatian (https://www.transifex.com/divio/teams/58664/hr/)\n"
+"Last-Translator: Aleks Acimovic, 2022\n"
+"Language-Team: Croatian (https://app.transifex.com/divio/teams/58664/hr/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: hr\n"
 "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "Link"
-
-#: cms_plugins.py:26
-msgid "Link settings"
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
+msgid "Link"
+msgstr "Poveznica"
+
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
-msgstr ""
+msgstr "Napredne postavke"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
-msgstr ""
+msgstr "Interna poveznica"
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr "Poveznica na datoteku"
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
+#: djangocms_link/models.py:24
+msgid "Default"
+msgstr "Zadano"
 
-#: models.py:109
-msgid "Email address"
-msgstr ""
+#: djangocms_link/models.py:41
+msgid "Open in new window"
+msgstr "Otvori u novom prozoru"
+
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr "Otvori u istom prozoru"
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr "Delegiraj roditelju"
 
-#: models.py:114
-msgid "Phone"
-msgstr "Telefon"
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr "Delegiraj na vrh"
+
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr "Predložak"
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr "Naziv za prikaz"
 
-#: models.py:120
+#: djangocms_link/models.py:77
 msgid "Target"
-msgstr ""
+msgstr "Odredište"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
-msgstr ""
+msgstr "Atributi"
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr "Potrebna je barem jedna poveznica"
diff --git a/djangocms_link/locale/hu/LC_MESSAGES/django.mo b/djangocms_link/locale/hu/LC_MESSAGES/django.mo
index 68e98210..adfe7fd4 100644
Binary files a/djangocms_link/locale/hu/LC_MESSAGES/django.mo and b/djangocms_link/locale/hu/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/hu/LC_MESSAGES/django.po b/djangocms_link/locale/hu/LC_MESSAGES/django.po
index 6d29258c..4d964dca 100644
--- a/djangocms_link/locale/hu/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/hu/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Hungarian (https://www.transifex.com/divio/teams/58664/hu/)\n"
+"Language-Team: Hungarian (https://app.transifex.com/divio/teams/58664/hu/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: hu\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Hivatkozás"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Telefon"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/id/LC_MESSAGES/django.mo b/djangocms_link/locale/id/LC_MESSAGES/django.mo
index f013e930..c80fe01f 100644
Binary files a/djangocms_link/locale/id/LC_MESSAGES/django.mo and b/djangocms_link/locale/id/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/id/LC_MESSAGES/django.po b/djangocms_link/locale/id/LC_MESSAGES/django.po
index 1d6aece3..931f12c5 100644
--- a/djangocms_link/locale/id/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/id/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Indonesian (https://www.transifex.com/divio/teams/58664/id/)\n"
+"Language-Team: Indonesian (https://app.transifex.com/divio/teams/58664/id/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: id\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/is/LC_MESSAGES/django.mo b/djangocms_link/locale/is/LC_MESSAGES/django.mo
index 6cb95d1b..504f0fcd 100644
Binary files a/djangocms_link/locale/is/LC_MESSAGES/django.mo and b/djangocms_link/locale/is/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/is/LC_MESSAGES/django.po b/djangocms_link/locale/is/LC_MESSAGES/django.po
index c318b03b..db8aacc1 100644
--- a/djangocms_link/locale/is/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/is/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Icelandic (https://www.transifex.com/divio/teams/58664/is/)\n"
+"Language-Team: Icelandic (https://app.transifex.com/divio/teams/58664/is/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: is\n"
 "Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "Hlekkur"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/is_IS/LC_MESSAGES/django.mo b/djangocms_link/locale/is_IS/LC_MESSAGES/django.mo
deleted file mode 100644
index 143f29b4..00000000
Binary files a/djangocms_link/locale/is_IS/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/is_IS/LC_MESSAGES/django.po b/djangocms_link/locale/is_IS/LC_MESSAGES/django.po
deleted file mode 100644
index af5bc981..00000000
--- a/djangocms_link/locale/is_IS/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Icelandic (Iceland) (https://www.transifex.com/divio/teams/58664/is_IS/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: is_IS\n"
-"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/it/LC_MESSAGES/django.mo b/djangocms_link/locale/it/LC_MESSAGES/django.mo
index 6077b52c..c01f9528 100644
Binary files a/djangocms_link/locale/it/LC_MESSAGES/django.mo and b/djangocms_link/locale/it/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/it/LC_MESSAGES/django.po b/djangocms_link/locale/it/LC_MESSAGES/django.po
index ad03dbe4..ea3d6515 100644
--- a/djangocms_link/locale/it/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/it/LC_MESSAGES/django.po
@@ -3,124 +3,141 @@
 # This file is distributed under the same license as the PACKAGE package.
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 # 
+# Translators:
+# yakky <i.spalletti@nephila.it>, 2019
+# 
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Italian (https://www.transifex.com/divio/teams/58664/it/)\n"
+"Last-Translator: yakky <i.spalletti@nephila.it>, 2019\n"
+"Language-Team: Italian (https://app.transifex.com/divio/teams/58664/it/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: it\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
+msgid "Link"
+msgstr "Collegamento"
 
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
-msgstr ""
+msgstr "Impostazioni avanzate"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
-msgstr ""
+msgstr "Collegamento interno"
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr "Collegamento a file"
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
+#: djangocms_link/models.py:24
+msgid "Default"
+msgstr "Default"
 
-#: models.py:109
-msgid "Email address"
-msgstr ""
+#: djangocms_link/models.py:41
+msgid "Open in new window"
+msgstr "Apri in una nuova finestra"
 
-#: models.py:114
-msgid "Phone"
-msgstr ""
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr "Apri nella stessa finestra"
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr "Apri nella finestra superiore"
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr "Apri nella finestra principale"
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr "Template"
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr "Testo mostrato"
+
+#: djangocms_link/models.py:77
 msgid "Target"
-msgstr ""
+msgstr "Apertura"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
-msgstr ""
+msgstr "Attributi"
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
-msgstr ""
+msgstr "<link is missing>"
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/ja/LC_MESSAGES/django.mo b/djangocms_link/locale/ja/LC_MESSAGES/django.mo
index 63af4740..dffce96f 100644
Binary files a/djangocms_link/locale/ja/LC_MESSAGES/django.mo and b/djangocms_link/locale/ja/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ja/LC_MESSAGES/django.po b/djangocms_link/locale/ja/LC_MESSAGES/django.po
index 17a018ad..a79eb04f 100644
--- a/djangocms_link/locale/ja/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ja/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Japanese (https://www.transifex.com/divio/teams/58664/ja/)\n"
+"Language-Team: Japanese (https://app.transifex.com/divio/teams/58664/ja/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ja\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "リンク"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "電話番号"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr "少なくとも1つのリンクが必要"
diff --git a/djangocms_link/locale/ka/LC_MESSAGES/django.mo b/djangocms_link/locale/ka/LC_MESSAGES/django.mo
index 99671cd6..13807bf7 100644
Binary files a/djangocms_link/locale/ka/LC_MESSAGES/django.mo and b/djangocms_link/locale/ka/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ka/LC_MESSAGES/django.po b/djangocms_link/locale/ka/LC_MESSAGES/django.po
index 20fc1f8b..ba695437 100644
--- a/djangocms_link/locale/ka/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ka/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Georgian (https://www.transifex.com/divio/teams/58664/ka/)\n"
+"Language-Team: Georgian (https://app.transifex.com/divio/teams/58664/ka/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ka\n"
 "Plural-Forms: nplurals=2; plural=(n!=1);\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "ბმული"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/kk/LC_MESSAGES/django.mo b/djangocms_link/locale/kk/LC_MESSAGES/django.mo
index 671b1e9b..455aea14 100644
Binary files a/djangocms_link/locale/kk/LC_MESSAGES/django.mo and b/djangocms_link/locale/kk/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/kk/LC_MESSAGES/django.po b/djangocms_link/locale/kk/LC_MESSAGES/django.po
index f17815a5..f979c424 100644
--- a/djangocms_link/locale/kk/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/kk/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Kazakh (https://www.transifex.com/divio/teams/58664/kk/)\n"
+"Language-Team: Kazakh (https://app.transifex.com/divio/teams/58664/kk/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: kk\n"
 "Plural-Forms: nplurals=2; plural=(n!=1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/km/LC_MESSAGES/django.mo b/djangocms_link/locale/km/LC_MESSAGES/django.mo
index 242bf9a3..c327d55c 100644
Binary files a/djangocms_link/locale/km/LC_MESSAGES/django.mo and b/djangocms_link/locale/km/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/km/LC_MESSAGES/django.po b/djangocms_link/locale/km/LC_MESSAGES/django.po
index 7c84823e..df543461 100644
--- a/djangocms_link/locale/km/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/km/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Khmer (https://www.transifex.com/divio/teams/58664/km/)\n"
+"Language-Team: Khmer (https://app.transifex.com/divio/teams/58664/km/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: km\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "ឈ្នាប់"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/ko/LC_MESSAGES/django.mo b/djangocms_link/locale/ko/LC_MESSAGES/django.mo
index e0427013..3cb7f944 100644
Binary files a/djangocms_link/locale/ko/LC_MESSAGES/django.mo and b/djangocms_link/locale/ko/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ko/LC_MESSAGES/django.po b/djangocms_link/locale/ko/LC_MESSAGES/django.po
index a4c3e127..a0351e3b 100644
--- a/djangocms_link/locale/ko/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ko/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Korean (https://www.transifex.com/divio/teams/58664/ko/)\n"
+"Language-Team: Korean (https://app.transifex.com/divio/teams/58664/ko/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ko\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/ko_KR/LC_MESSAGES/django.mo b/djangocms_link/locale/ko_KR/LC_MESSAGES/django.mo
deleted file mode 100644
index 89f61d2b..00000000
Binary files a/djangocms_link/locale/ko_KR/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/ko_KR/LC_MESSAGES/django.po b/djangocms_link/locale/ko_KR/LC_MESSAGES/django.po
deleted file mode 100644
index 69d9245b..00000000
--- a/djangocms_link/locale/ko_KR/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,130 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Korean (Korea) (https://www.transifex.com/divio/teams/58664/ko_KR/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ko_KR\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "연결"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr "전화"
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr "최소 하나의 링크가 필요합니다."
diff --git a/djangocms_link/locale/ku_IQ/LC_MESSAGES/django.mo b/djangocms_link/locale/ku_IQ/LC_MESSAGES/django.mo
deleted file mode 100644
index 3dc647c6..00000000
Binary files a/djangocms_link/locale/ku_IQ/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/ku_IQ/LC_MESSAGES/django.po b/djangocms_link/locale/ku_IQ/LC_MESSAGES/django.po
deleted file mode 100644
index 4e99643c..00000000
--- a/djangocms_link/locale/ku_IQ/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,130 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Kurdish (Iraq) (https://www.transifex.com/divio/teams/58664/ku_IQ/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ku_IQ\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "لینک"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/lt/LC_MESSAGES/django.mo b/djangocms_link/locale/lt/LC_MESSAGES/django.mo
index e27ae197..e641f117 100644
Binary files a/djangocms_link/locale/lt/LC_MESSAGES/django.mo and b/djangocms_link/locale/lt/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/lt/LC_MESSAGES/django.po b/djangocms_link/locale/lt/LC_MESSAGES/django.po
index ba3c1a30..70c60ed6 100644
--- a/djangocms_link/locale/lt/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/lt/LC_MESSAGES/django.po
@@ -12,122 +12,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Matas Dailyda <matas@dailyda.com>, 2017\n"
-"Language-Team: Lithuanian (https://www.transifex.com/divio/teams/58664/lt/)\n"
+"Language-Team: Lithuanian (https://app.transifex.com/divio/teams/58664/lt/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: lt\n"
 "Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Nuoroda"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "Nuorodos nustatymai"
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr "Išplėstiniai nustatymai"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr "Vidinė nuoroda"
 
-#: models.py:27
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr ""
+
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
+msgstr ""
+
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:177
+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."
+msgstr ""
+
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
+msgstr ""
+
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
+msgstr ""
+
+#: djangocms_link/fields.py:194
+msgid "#anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
+msgstr ""
+
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
+msgstr ""
+
+#: djangocms_link/fields.py:215
+msgid "Select site"
+msgstr ""
+
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
+msgstr ""
+
+#: djangocms_link/models.py:24
 msgid "Default"
 msgstr "Numatytasis"
 
-#: models.py:44
+#: djangocms_link/models.py:41
 msgid "Open in new window"
 msgstr "Atidaryti naujame lange"
 
-#: models.py:45
+#: djangocms_link/models.py:42
 msgid "Open in same window"
 msgstr "Atidaryti tame pačiame lange"
 
-#: models.py:46
+#: djangocms_link/models.py:43
 msgid "Delegate to parent"
 msgstr "Nukreipti į tėvinį elementą"
 
-#: models.py:47
+#: djangocms_link/models.py:44
 msgid "Delegate to top"
 msgstr "Nukreipti į viršų"
 
-#: models.py:65
+#: djangocms_link/models.py:61
 msgid "Template"
 msgstr "Šablonas"
 
-#: models.py:71
+#: djangocms_link/models.py:67
 msgid "Display name"
 msgstr "Atvaizduojamas pavadinimas"
 
-#: models.py:77
-msgid "External link"
-msgstr "Išorinė nuoroda"
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr "Jei pateikta, perrašo išorinę nuorodą."
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr "Ankeris"
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-"Prideda reikšmė po vidinės ar išorinės nuorodos.  <em>Nepridėkite</em>\"#\" "
-"simbolio pradžioje."
-
-#: models.py:109
-msgid "Email address"
-msgstr "Elektroninio pašto adresas"
-
-#: models.py:114
-msgid "Phone"
-msgstr "Telefono numeris"
-
-#: models.py:120
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr "Tikslas"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr "Atributai"
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr "<nuoroda nerasta>"
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr "Tik vienas iš {0} arba {1} gali būti pateiktas."
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr "Pateikite nuorodą."
+#: djangocms_link/models.py:118
+msgid "Link is required."
+msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr "%(anchor_field_verbose_name)s negalimas kartu su %(field_name)s"
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
+msgstr ""
 
-#~ msgid "At least one link is required."
-#~ msgstr "Reikalinga bent viena nuoroda."
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
+msgstr ""
diff --git a/djangocms_link/locale/lt_LT/LC_MESSAGES/django.mo b/djangocms_link/locale/lt_LT/LC_MESSAGES/django.mo
deleted file mode 100644
index 9043ab23..00000000
Binary files a/djangocms_link/locale/lt_LT/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/lt_LT/LC_MESSAGES/django.po b/djangocms_link/locale/lt_LT/LC_MESSAGES/django.po
deleted file mode 100644
index f23d3604..00000000
--- a/djangocms_link/locale/lt_LT/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Lithuanian (Lithuania) (https://www.transifex.com/divio/teams/58664/lt_LT/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: lt_LT\n"
-"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/lv/LC_MESSAGES/django.mo b/djangocms_link/locale/lv/LC_MESSAGES/django.mo
index 361b015c..ddad4d68 100644
Binary files a/djangocms_link/locale/lv/LC_MESSAGES/django.mo and b/djangocms_link/locale/lv/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/lv/LC_MESSAGES/django.po b/djangocms_link/locale/lv/LC_MESSAGES/django.po
index c6d49a90..90517862 100644
--- a/djangocms_link/locale/lv/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/lv/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Latvian (https://www.transifex.com/divio/teams/58664/lv/)\n"
+"Language-Team: Latvian (https://app.transifex.com/divio/teams/58664/lv/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: lv\n"
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/mn/LC_MESSAGES/django.mo b/djangocms_link/locale/mn/LC_MESSAGES/django.mo
index c3018305..9e8a3a51 100644
Binary files a/djangocms_link/locale/mn/LC_MESSAGES/django.mo and b/djangocms_link/locale/mn/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/mn/LC_MESSAGES/django.po b/djangocms_link/locale/mn/LC_MESSAGES/django.po
index 0585a3a1..4b424cba 100644
--- a/djangocms_link/locale/mn/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/mn/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Mongolian (https://www.transifex.com/divio/teams/58664/mn/)\n"
+"Language-Team: Mongolian (https://app.transifex.com/divio/teams/58664/mn/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: mn\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/mn_MN/LC_MESSAGES/django.mo b/djangocms_link/locale/mn_MN/LC_MESSAGES/django.mo
deleted file mode 100644
index 4cf06b39..00000000
Binary files a/djangocms_link/locale/mn_MN/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/mn_MN/LC_MESSAGES/django.po b/djangocms_link/locale/mn_MN/LC_MESSAGES/django.po
deleted file mode 100644
index 502ffa9e..00000000
--- a/djangocms_link/locale/mn_MN/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Mongolian (Mongolia) (https://www.transifex.com/divio/teams/58664/mn_MN/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: mn_MN\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/ms/LC_MESSAGES/django.mo b/djangocms_link/locale/ms/LC_MESSAGES/django.mo
index a6431fca..11584e94 100644
Binary files a/djangocms_link/locale/ms/LC_MESSAGES/django.mo and b/djangocms_link/locale/ms/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ms/LC_MESSAGES/django.po b/djangocms_link/locale/ms/LC_MESSAGES/django.po
index 43c166ec..2c2d8483 100644
--- a/djangocms_link/locale/ms/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ms/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Malay (https://www.transifex.com/divio/teams/58664/ms/)\n"
+"Language-Team: Malay (https://app.transifex.com/divio/teams/58664/ms/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ms\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/mt/LC_MESSAGES/django.mo b/djangocms_link/locale/mt/LC_MESSAGES/django.mo
index a0bdd7f3..8fefb5d1 100644
Binary files a/djangocms_link/locale/mt/LC_MESSAGES/django.mo and b/djangocms_link/locale/mt/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/mt/LC_MESSAGES/django.po b/djangocms_link/locale/mt/LC_MESSAGES/django.po
index 7d929df0..31f0c39d 100644
--- a/djangocms_link/locale/mt/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/mt/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Maltese (https://www.transifex.com/divio/teams/58664/mt/)\n"
+"Language-Team: Maltese (https://app.transifex.com/divio/teams/58664/mt/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: mt\n"
 "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/nb/LC_MESSAGES/django.mo b/djangocms_link/locale/nb/LC_MESSAGES/django.mo
index 2214c8ef..847e2f3f 100644
Binary files a/djangocms_link/locale/nb/LC_MESSAGES/django.mo and b/djangocms_link/locale/nb/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/nb/LC_MESSAGES/django.po b/djangocms_link/locale/nb/LC_MESSAGES/django.po
index aa99c46a..36a28a2a 100644
--- a/djangocms_link/locale/nb/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/nb/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Norwegian Bokmål (https://www.transifex.com/divio/teams/58664/nb/)\n"
+"Language-Team: Norwegian Bokmål (https://app.transifex.com/divio/teams/58664/nb/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: nb\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/nl/LC_MESSAGES/django.mo b/djangocms_link/locale/nl/LC_MESSAGES/django.mo
index fa86461d..8b272cd3 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 e574efad..4b6116f6 100644
--- a/djangocms_link/locale/nl/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/nl/LC_MESSAGES/django.po
@@ -6,131 +6,140 @@
 # Translators:
 # Angelo Dini <angelo.dini@divio.ch>, 2016
 # Evelijn Saaltink <evelijnsaaltink@gmail.com>, 2016
-# Heimen Stoffels <vistausss@outlook.com>, 2019
+# Heimen Stoffels <vistausss@fastmail.com>, 2019
 # 
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Heimen Stoffels <vistausss@outlook.com>, 2019\n"
-"Language-Team: Dutch (https://www.transifex.com/divio/teams/58664/nl/)\n"
+"Last-Translator: Heimen Stoffels <vistausss@fastmail.com>, 2019\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"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: nl\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Link"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "Linkinstellingen"
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr "Geavanceerde instellingen"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr "Interne link"
 
-#: models.py:27
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr "Bestandslink"
+
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
+msgstr ""
+
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:177
+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."
+msgstr ""
+
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
+msgstr ""
+
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
+msgstr ""
+
+#: djangocms_link/fields.py:194
+msgid "#anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
+msgstr ""
+
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
+msgstr ""
+
+#: djangocms_link/fields.py:215
+msgid "Select site"
+msgstr ""
+
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
+msgstr ""
+
+#: djangocms_link/models.py:24
 msgid "Default"
 msgstr "Standaard"
 
-#: models.py:44
+#: djangocms_link/models.py:41
 msgid "Open in new window"
 msgstr "Openen in nieuw venster"
 
-#: models.py:45
+#: djangocms_link/models.py:42
 msgid "Open in same window"
 msgstr "Openen in hetzelfde venster"
 
-#: models.py:46
+#: djangocms_link/models.py:43
 msgid "Delegate to parent"
 msgstr "Naar ouder delegeren"
 
-#: models.py:47
+#: djangocms_link/models.py:44
 msgid "Delegate to top"
 msgstr "Naar bovenkant delegeren"
 
-#: models.py:65
+#: djangocms_link/models.py:61
 msgid "Template"
 msgstr "Sjabloon"
 
-#: models.py:71
+#: djangocms_link/models.py:67
 msgid "Display name"
 msgstr "Getoonde naam"
 
-#: models.py:77
-msgid "External link"
-msgstr "Externe link"
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr "Als je dit opgeeft, dan overschrijft het de externe link."
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr "Anker"
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-"Voegt alleen een waarde toe na een interne of externe link. Voeg "
-"<em>geen</em> \"#\"-teken toe aan het begin."
-
-#: models.py:109
-msgid "Email address"
-msgstr "E-mailadres"
-
-#: models.py:114
-msgid "Phone"
-msgstr "Telefoonnummer"
-
-#: models.py:120
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr "Doel"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr "Eigenschappen"
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr "<link is missing>"
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr "Er mag slechts één van {0} of {1} worden gegeven."
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr "Voer een link in."
+#: djangocms_link/models.py:118
+msgid "Link is required."
+msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
-"%(anchor_field_verbose_name)s is niet toegestaan in combinatie met "
-"%(field_name)s"
 
-#~ msgid "At least one link is required."
-#~ msgstr "Minimaal één link nodig."
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
+msgstr ""
diff --git a/djangocms_link/locale/no/LC_MESSAGES/django.mo b/djangocms_link/locale/no/LC_MESSAGES/django.mo
index 5dba54b1..8e946b16 100644
Binary files a/djangocms_link/locale/no/LC_MESSAGES/django.mo and b/djangocms_link/locale/no/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/no/LC_MESSAGES/django.po b/djangocms_link/locale/no/LC_MESSAGES/django.po
index aa052e44..e9e37424 100644
--- a/djangocms_link/locale/no/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/no/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Norwegian (https://www.transifex.com/divio/teams/58664/no/)\n"
+"Language-Team: Norwegian (https://app.transifex.com/divio/teams/58664/no/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: no\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "Lenke"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/pap/LC_MESSAGES/django.mo b/djangocms_link/locale/pap/LC_MESSAGES/django.mo
deleted file mode 100644
index 70be8981..00000000
Binary files a/djangocms_link/locale/pap/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/pap/LC_MESSAGES/django.po b/djangocms_link/locale/pap/LC_MESSAGES/django.po
deleted file mode 100644
index de1f0d5f..00000000
--- a/djangocms_link/locale/pap/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Papiamento (https://www.transifex.com/divio/teams/58664/pap/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: pap\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/pl/LC_MESSAGES/django.mo b/djangocms_link/locale/pl/LC_MESSAGES/django.mo
index 58fefa8a..a90c2564 100644
Binary files a/djangocms_link/locale/pl/LC_MESSAGES/django.mo and b/djangocms_link/locale/pl/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/pl/LC_MESSAGES/django.po b/djangocms_link/locale/pl/LC_MESSAGES/django.po
index 852635b2..88b66036 100644
--- a/djangocms_link/locale/pl/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/pl/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Polish (https://www.transifex.com/divio/teams/58664/pl/)\n"
+"Language-Team: Polish (https://app.transifex.com/divio/teams/58664/pl/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: pl\n"
 "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Odnośnik"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Telefon"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr "Wymagany jest co najmniej 1 odnośnik."
diff --git a/djangocms_link/locale/pt/LC_MESSAGES/django.mo b/djangocms_link/locale/pt/LC_MESSAGES/django.mo
index 72d367a7..a3641606 100644
Binary files a/djangocms_link/locale/pt/LC_MESSAGES/django.mo and b/djangocms_link/locale/pt/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/pt/LC_MESSAGES/django.po b/djangocms_link/locale/pt/LC_MESSAGES/django.po
index 1465e41f..a75494b4 100644
--- a/djangocms_link/locale/pt/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/pt/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Portuguese (https://www.transifex.com/divio/teams/58664/pt/)\n"
+"Language-Team: Portuguese (https://app.transifex.com/divio/teams/58664/pt/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: pt\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Link"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Telefone"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr "É necessária no mínimo uma ligação."
diff --git a/djangocms_link/locale/pt_BR/LC_MESSAGES/django.mo b/djangocms_link/locale/pt_BR/LC_MESSAGES/django.mo
deleted file mode 100644
index 5834f98e..00000000
Binary files a/djangocms_link/locale/pt_BR/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/pt_BR/LC_MESSAGES/django.po b/djangocms_link/locale/pt_BR/LC_MESSAGES/django.po
deleted file mode 100644
index ba68a308..00000000
--- a/djangocms_link/locale/pt_BR/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,134 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
-# Diego Ponci <dgo.ponciano@gmail.com>, 2017
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Diego Ponci <dgo.ponciano@gmail.com>, 2017\n"
-"Language-Team: Portuguese (Brazil) (https://www.transifex.com/divio/teams/58664/pt_BR/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: pt_BR\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "Link"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "Configurações do link"
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr "Configurações avançadas"
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr "Link interno"
-
-#: models.py:27
-msgid "Default"
-msgstr "Padrão"
-
-#: models.py:44
-msgid "Open in new window"
-msgstr "Abrir em nova janela"
-
-#: models.py:45
-msgid "Open in same window"
-msgstr "Abrir na mesma janela"
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr "Abrir no frame superior"
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr "Abrir na página principal"
-
-#: models.py:65
-msgid "Template"
-msgstr "Template"
-
-#: models.py:71
-msgid "Display name"
-msgstr "Nome exibido"
-
-#: models.py:77
-msgid "External link"
-msgstr "Link externo"
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr "Se fornecido, substitui o link externo."
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr "Âncora"
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-"Acrescenta o valor somente após o link interno ou externo. <em>Não</em> "
-"inclui o prefixo \"#\"."
-
-#: models.py:109
-msgid "Email address"
-msgstr "Endereço de e-mail"
-
-#: models.py:114
-msgid "Phone"
-msgstr "Telefone"
-
-#: models.py:120
-msgid "Target"
-msgstr "Target"
-
-#: models.py:126
-msgid "Attributes"
-msgstr "Atributos"
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr "<link faltando>"
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr "Apenas um de {0} ou {1} deve ser informado."
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr "Por favor forneça um link."
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-"%(anchor_field_verbose_name)s não é permitido junto com %(field_name)s"
-
-#~ msgid "At least one link is required."
-#~ msgstr "Pelo menos um link é necessário."
diff --git a/djangocms_link/locale/pt_PT/LC_MESSAGES/django.mo b/djangocms_link/locale/pt_PT/LC_MESSAGES/django.mo
deleted file mode 100644
index 02be7f6f..00000000
Binary files a/djangocms_link/locale/pt_PT/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/pt_PT/LC_MESSAGES/django.po b/djangocms_link/locale/pt_PT/LC_MESSAGES/django.po
deleted file mode 100644
index cd2e508a..00000000
--- a/djangocms_link/locale/pt_PT/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,130 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Portuguese (Portugal) (https://www.transifex.com/divio/teams/58664/pt_PT/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: pt_PT\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "Endereço Web"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr "Telefone"
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/ro/LC_MESSAGES/django.mo b/djangocms_link/locale/ro/LC_MESSAGES/django.mo
index c530f29b..078e6e3a 100644
Binary files a/djangocms_link/locale/ro/LC_MESSAGES/django.mo and b/djangocms_link/locale/ro/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ro/LC_MESSAGES/django.po b/djangocms_link/locale/ro/LC_MESSAGES/django.po
index 447adfcf..fbb03534 100644
--- a/djangocms_link/locale/ro/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ro/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Romanian (https://www.transifex.com/divio/teams/58664/ro/)\n"
+"Language-Team: Romanian (https://app.transifex.com/divio/teams/58664/ro/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ro\n"
 "Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "Link"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/ro_RO/LC_MESSAGES/django.mo b/djangocms_link/locale/ro_RO/LC_MESSAGES/django.mo
deleted file mode 100644
index 7bdf42b9..00000000
Binary files a/djangocms_link/locale/ro_RO/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/ro_RO/LC_MESSAGES/django.po b/djangocms_link/locale/ro_RO/LC_MESSAGES/django.po
deleted file mode 100644
index f3c4f99a..00000000
--- a/djangocms_link/locale/ro_RO/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Romanian (Romania) (https://www.transifex.com/divio/teams/58664/ro_RO/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ro_RO\n"
-"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/ru/LC_MESSAGES/django.mo b/djangocms_link/locale/ru/LC_MESSAGES/django.mo
index 1a25782c..5e43e807 100644
Binary files a/djangocms_link/locale/ru/LC_MESSAGES/django.mo and b/djangocms_link/locale/ru/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ru/LC_MESSAGES/django.po b/djangocms_link/locale/ru/LC_MESSAGES/django.po
index b4ceb114..9a3b8a11 100644
--- a/djangocms_link/locale/ru/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ru/LC_MESSAGES/django.po
@@ -12,122 +12,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Oleg Fish <okfish@yandex.ru>, 2017\n"
-"Language-Team: Russian (https://www.transifex.com/divio/teams/58664/ru/)\n"
+"Language-Team: Russian (https://app.transifex.com/divio/teams/58664/ru/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ru\n"
 "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Ссылка"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr "Настройки ссылки"
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr "Дополнительные настройки"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr "Внутренняя ссылка"
 
-#: models.py:27
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr ""
+
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
+msgstr ""
+
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:177
+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."
+msgstr ""
+
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
+msgstr ""
+
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
+msgstr ""
+
+#: djangocms_link/fields.py:194
+msgid "#anchor"
+msgstr ""
+
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
+msgstr ""
+
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
+msgstr ""
+
+#: djangocms_link/fields.py:215
+msgid "Select site"
+msgstr ""
+
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
+msgstr ""
+
+#: djangocms_link/models.py:24
 msgid "Default"
 msgstr "По умолчанию"
 
-#: models.py:44
+#: djangocms_link/models.py:41
 msgid "Open in new window"
 msgstr "Открыть в новом окне"
 
-#: models.py:45
+#: djangocms_link/models.py:42
 msgid "Open in same window"
 msgstr "Открыть в том же окне"
 
-#: models.py:46
+#: djangocms_link/models.py:43
 msgid "Delegate to parent"
 msgstr "Передать в родительский фрейм"
 
-#: models.py:47
+#: djangocms_link/models.py:44
 msgid "Delegate to top"
 msgstr "Передать в окно верхнего уровня"
 
-#: models.py:65
+#: djangocms_link/models.py:61
 msgid "Template"
 msgstr "Шаблон"
 
-#: models.py:71
+#: djangocms_link/models.py:67
 msgid "Display name"
 msgstr "Название для отображения"
 
-#: models.py:77
-msgid "External link"
-msgstr "Внешняя ссылка"
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr "Если указана, замещает внешнюю ссылку."
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr "Якорь"
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-"Якорь добавляется только после внешней или внутренней ссылки. <em>Не "
-"надо</em> добавлять  символ \"#\" в начале."
-
-#: models.py:109
-msgid "Email address"
-msgstr "Адрес эл. почты"
-
-#: models.py:114
-msgid "Phone"
-msgstr "Телефон"
-
-#: models.py:120
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr "Цель"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr "Атрибуты"
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr "<ссылка отсутствует>"
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr "Только {0} или {1} можно задать."
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr "Пожалуйста, укажите ссылку."
+#: djangocms_link/models.py:118
+msgid "Link is required."
+msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr "%(anchor_field_verbose_name)s не допускается вместе с %(field_name)s"
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
+msgstr ""
 
-#~ msgid "At least one link is required."
-#~ msgstr "Как минимум одна ссылка необходима."
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
+msgstr ""
diff --git a/djangocms_link/locale/sk/LC_MESSAGES/django.mo b/djangocms_link/locale/sk/LC_MESSAGES/django.mo
index 583e7b3b..a890c0a0 100644
Binary files a/djangocms_link/locale/sk/LC_MESSAGES/django.mo and b/djangocms_link/locale/sk/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/sk/LC_MESSAGES/django.po b/djangocms_link/locale/sk/LC_MESSAGES/django.po
index 86cc890f..a356b992 100644
--- a/djangocms_link/locale/sk/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/sk/LC_MESSAGES/django.po
@@ -11,120 +11,160 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Slovak (https://www.transifex.com/divio/teams/58664/sk/)\n"
+"Language-Team: Slovak (https://app.transifex.com/divio/teams/58664/sk/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: sk\n"
 "Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n"
 
-#: cms_plugins.py:15
+#: apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: cms_plugins.py:15 models.py:73
 msgid "Link"
 msgstr "Odkaz"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/sk_SK/LC_MESSAGES/django.mo b/djangocms_link/locale/sk_SK/LC_MESSAGES/django.mo
deleted file mode 100644
index 5d185daf..00000000
Binary files a/djangocms_link/locale/sk_SK/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/sk_SK/LC_MESSAGES/django.po b/djangocms_link/locale/sk_SK/LC_MESSAGES/django.po
deleted file mode 100644
index b534aec0..00000000
--- a/djangocms_link/locale/sk_SK/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Slovak (Slovakia) (https://www.transifex.com/divio/teams/58664/sk_SK/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: sk_SK\n"
-"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/sl/LC_MESSAGES/django.mo b/djangocms_link/locale/sl/LC_MESSAGES/django.mo
index 4afa8c9c..05e3aaeb 100644
Binary files a/djangocms_link/locale/sl/LC_MESSAGES/django.mo and b/djangocms_link/locale/sl/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/sl/LC_MESSAGES/django.po b/djangocms_link/locale/sl/LC_MESSAGES/django.po
index 583d1000..11727207 100644
--- a/djangocms_link/locale/sl/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/sl/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Slovenian (https://www.transifex.com/divio/teams/58664/sl/)\n"
+"Language-Team: Slovenian (https://app.transifex.com/divio/teams/58664/sl/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: sl\n"
 "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/sl_SI/LC_MESSAGES/django.mo b/djangocms_link/locale/sl_SI/LC_MESSAGES/django.mo
deleted file mode 100644
index b43cb2d7..00000000
Binary files a/djangocms_link/locale/sl_SI/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/sl_SI/LC_MESSAGES/django.po b/djangocms_link/locale/sl_SI/LC_MESSAGES/django.po
deleted file mode 100644
index 214814a0..00000000
--- a/djangocms_link/locale/sl_SI/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,130 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Slovenian (Slovenia) (https://www.transifex.com/divio/teams/58664/sl_SI/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: sl_SI\n"
-"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "Povezava"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/sq/LC_MESSAGES/django.mo b/djangocms_link/locale/sq/LC_MESSAGES/django.mo
index f1d290a6..29af7511 100644
Binary files a/djangocms_link/locale/sq/LC_MESSAGES/django.mo and b/djangocms_link/locale/sq/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/sq/LC_MESSAGES/django.po b/djangocms_link/locale/sq/LC_MESSAGES/django.po
index e9726508..8ee722bb 100644
--- a/djangocms_link/locale/sq/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/sq/LC_MESSAGES/django.po
@@ -3,124 +3,141 @@
 # This file is distributed under the same license as the PACKAGE package.
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 # 
+# Translators:
+# Besnik Bleta <besnik@programeshqip.org>, 2020
+# 
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Albanian (https://www.transifex.com/divio/teams/58664/sq/)\n"
+"Last-Translator: Besnik Bleta <besnik@programeshqip.org>, 2020\n"
+"Language-Team: Albanian (https://app.transifex.com/divio/teams/58664/sq/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: sq\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
+msgid "Link"
+msgstr "Lidhje"
 
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
-msgstr ""
+msgstr "Rregullime të mëtejshme"
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
-msgstr ""
+msgstr "Lidhje e brendshme"
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
+#: djangocms_link/fields.py:30
+msgid "File link"
+msgstr "Lidhje kartele"
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
+#: djangocms_link/models.py:24
+msgid "Default"
+msgstr "Parazgjedhje"
+
+#: djangocms_link/models.py:41
+msgid "Open in new window"
+msgstr "Hape në dritare të re"
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr "Hape në të njëjtën dritare"
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr "Gjedhe"
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr "Emër në ekran"
+
+#: djangocms_link/models.py:77
 msgid "Target"
-msgstr ""
+msgstr "Objektiv"
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
-msgstr ""
+msgstr "Atribute"
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
-msgstr ""
+msgstr "<lidhja mungon>"
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/sq_AL/LC_MESSAGES/django.mo b/djangocms_link/locale/sq_AL/LC_MESSAGES/django.mo
deleted file mode 100644
index dde71438..00000000
Binary files a/djangocms_link/locale/sq_AL/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/sq_AL/LC_MESSAGES/django.po b/djangocms_link/locale/sq_AL/LC_MESSAGES/django.po
deleted file mode 100644
index 224ee71d..00000000
--- a/djangocms_link/locale/sq_AL/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Albanian (Albania) (https://www.transifex.com/divio/teams/58664/sq_AL/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: sq_AL\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/sr/LC_MESSAGES/django.mo b/djangocms_link/locale/sr/LC_MESSAGES/django.mo
index 6c0bc8db..0503856a 100644
Binary files a/djangocms_link/locale/sr/LC_MESSAGES/django.mo and b/djangocms_link/locale/sr/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/sr/LC_MESSAGES/django.po b/djangocms_link/locale/sr/LC_MESSAGES/django.po
index ee5d884d..de923596 100644
--- a/djangocms_link/locale/sr/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/sr/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Serbian (https://www.transifex.com/divio/teams/58664/sr/)\n"
+"Language-Team: Serbian (https://app.transifex.com/divio/teams/58664/sr/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: sr\n"
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/sr@latin/LC_MESSAGES/django.mo b/djangocms_link/locale/sr@latin/LC_MESSAGES/django.mo
deleted file mode 100644
index fde40783..00000000
Binary files a/djangocms_link/locale/sr@latin/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/sr@latin/LC_MESSAGES/django.po b/djangocms_link/locale/sr@latin/LC_MESSAGES/django.po
deleted file mode 100644
index dc9c7ed9..00000000
--- a/djangocms_link/locale/sr@latin/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,130 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Serbian (Latin) (https://www.transifex.com/divio/teams/58664/sr@latin/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: sr@latin\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "Link"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/sv/LC_MESSAGES/django.mo b/djangocms_link/locale/sv/LC_MESSAGES/django.mo
index 14a54320..eae17268 100644
Binary files a/djangocms_link/locale/sv/LC_MESSAGES/django.mo and b/djangocms_link/locale/sv/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/sv/LC_MESSAGES/django.po b/djangocms_link/locale/sv/LC_MESSAGES/django.po
index 490e1a52..6b478a6e 100644
--- a/djangocms_link/locale/sv/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/sv/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Swedish (https://www.transifex.com/divio/teams/58664/sv/)\n"
+"Language-Team: Swedish (https://app.transifex.com/divio/teams/58664/sv/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: sv\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Länk"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Telefon"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/ta/LC_MESSAGES/django.mo b/djangocms_link/locale/ta/LC_MESSAGES/django.mo
index 8f357dfb..06ce80fa 100644
Binary files a/djangocms_link/locale/ta/LC_MESSAGES/django.mo and b/djangocms_link/locale/ta/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ta/LC_MESSAGES/django.po b/djangocms_link/locale/ta/LC_MESSAGES/django.po
index f8147656..b696c723 100644
--- a/djangocms_link/locale/ta/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ta/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Tamil (https://www.transifex.com/divio/teams/58664/ta/)\n"
+"Language-Team: Tamil (https://app.transifex.com/divio/teams/58664/ta/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ta\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "தொடுப்பு"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "தொலைபேசி"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/th/LC_MESSAGES/django.mo b/djangocms_link/locale/th/LC_MESSAGES/django.mo
index 0482c7be..927e5d88 100644
Binary files a/djangocms_link/locale/th/LC_MESSAGES/django.mo and b/djangocms_link/locale/th/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/th/LC_MESSAGES/django.po b/djangocms_link/locale/th/LC_MESSAGES/django.po
index f7d74459..3a57d263 100644
--- a/djangocms_link/locale/th/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/th/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Thai (https://www.transifex.com/divio/teams/58664/th/)\n"
+"Language-Team: Thai (https://app.transifex.com/divio/teams/58664/th/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: th\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/th_TH/LC_MESSAGES/django.mo b/djangocms_link/locale/th_TH/LC_MESSAGES/django.mo
deleted file mode 100644
index d98aefc3..00000000
Binary files a/djangocms_link/locale/th_TH/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/th_TH/LC_MESSAGES/django.po b/djangocms_link/locale/th_TH/LC_MESSAGES/django.po
deleted file mode 100644
index 78a8fe31..00000000
--- a/djangocms_link/locale/th_TH/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Thai (Thailand) (https://www.transifex.com/divio/teams/58664/th_TH/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: th_TH\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/tlh/LC_MESSAGES/django.mo b/djangocms_link/locale/tlh/LC_MESSAGES/django.mo
deleted file mode 100644
index a9d40605..00000000
Binary files a/djangocms_link/locale/tlh/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/tlh/LC_MESSAGES/django.po b/djangocms_link/locale/tlh/LC_MESSAGES/django.po
deleted file mode 100644
index 52f43376..00000000
--- a/djangocms_link/locale/tlh/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Klingon (https://www.transifex.com/divio/teams/58664/tlh/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: tlh\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/tr/LC_MESSAGES/django.mo b/djangocms_link/locale/tr/LC_MESSAGES/django.mo
index 2fa7b117..8e35fe6e 100644
Binary files a/djangocms_link/locale/tr/LC_MESSAGES/django.mo and b/djangocms_link/locale/tr/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/tr/LC_MESSAGES/django.po b/djangocms_link/locale/tr/LC_MESSAGES/django.po
index 1383afa9..d18d4605 100644
--- a/djangocms_link/locale/tr/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/tr/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Turkish (https://www.transifex.com/divio/teams/58664/tr/)\n"
+"Language-Team: Turkish (https://app.transifex.com/divio/teams/58664/tr/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: tr\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Bağlantı"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Telefon"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/tr_TR/LC_MESSAGES/django.mo b/djangocms_link/locale/tr_TR/LC_MESSAGES/django.mo
deleted file mode 100644
index 33d3af81..00000000
Binary files a/djangocms_link/locale/tr_TR/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/tr_TR/LC_MESSAGES/django.po b/djangocms_link/locale/tr_TR/LC_MESSAGES/django.po
deleted file mode 100644
index 3bf61281..00000000
--- a/djangocms_link/locale/tr_TR/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Turkish (Turkey) (https://www.transifex.com/divio/teams/58664/tr_TR/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: tr_TR\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/ug/LC_MESSAGES/django.mo b/djangocms_link/locale/ug/LC_MESSAGES/django.mo
index 130e8797..d8e56508 100644
Binary files a/djangocms_link/locale/ug/LC_MESSAGES/django.mo and b/djangocms_link/locale/ug/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ug/LC_MESSAGES/django.po b/djangocms_link/locale/ug/LC_MESSAGES/django.po
index 45096550..52a38c7e 100644
--- a/djangocms_link/locale/ug/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ug/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Uighur (https://www.transifex.com/divio/teams/58664/ug/)\n"
+"Language-Team: Uyghur (https://app.transifex.com/divio/teams/58664/ug/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ug\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/uk/LC_MESSAGES/django.mo b/djangocms_link/locale/uk/LC_MESSAGES/django.mo
index 2f8c51df..07019e3a 100644
Binary files a/djangocms_link/locale/uk/LC_MESSAGES/django.mo and b/djangocms_link/locale/uk/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/uk/LC_MESSAGES/django.po b/djangocms_link/locale/uk/LC_MESSAGES/django.po
index 7d90a08a..8f1ddc2a 100644
--- a/djangocms_link/locale/uk/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/uk/LC_MESSAGES/django.po
@@ -11,120 +11,133 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 14:11+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
 "Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Ukrainian (https://www.transifex.com/divio/teams/58664/uk/)\n"
+"Language-Team: Ukrainian (https://app.transifex.com/divio/teams/58664/uk/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: uk\n"
 "Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n"
 
-#: cms_plugins.py:15
+#: djangocms_link/apps.py:7
+msgid "django CMS Link"
+msgstr ""
+
+#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73
 msgid "Link"
 msgstr "Посилання"
 
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
+#: djangocms_link/cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: djangocms_link/fields.py:26 djangocms_link/forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: djangocms_link/fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: djangocms_link/fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: djangocms_link/fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: djangocms_link/fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: djangocms_link/fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: djangocms_link/fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: djangocms_link/fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: djangocms_link/fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: djangocms_link/fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: djangocms_link/fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: djangocms_link/fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: djangocms_link/fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: djangocms_link/models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: djangocms_link/models.py:41
+msgid "Open in new window"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
-msgstr "Телефон"
+#: djangocms_link/models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: djangocms_link/models.py:43
+msgid "Delegate to parent"
+msgstr ""
+
+#: djangocms_link/models.py:44
+msgid "Delegate to top"
+msgstr ""
 
-#: models.py:120
+#: djangocms_link/models.py:61
+msgid "Template"
+msgstr ""
+
+#: djangocms_link/models.py:67
+msgid "Display name"
+msgstr ""
+
+#: djangocms_link/models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: djangocms_link/models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: djangocms_link/models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: djangocms_link/models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: djangocms_link/validators.py:50
+msgid "Enter a valid anchor"
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: djangocms_link/validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr "Принаймні, одне посилання не потрібно."
diff --git a/djangocms_link/locale/ur/LC_MESSAGES/django.mo b/djangocms_link/locale/ur/LC_MESSAGES/django.mo
index da1d3da2..49e0e851 100644
Binary files a/djangocms_link/locale/ur/LC_MESSAGES/django.mo and b/djangocms_link/locale/ur/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/ur/LC_MESSAGES/django.po b/djangocms_link/locale/ur/LC_MESSAGES/django.po
index 6c988c25..4cdbaa7d 100644
--- a/djangocms_link/locale/ur/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/ur/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Urdu (https://www.transifex.com/divio/teams/58664/ur/)\n"
+"Language-Team: Urdu (https://app.transifex.com/divio/teams/58664/ur/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ur\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/vi/LC_MESSAGES/django.mo b/djangocms_link/locale/vi/LC_MESSAGES/django.mo
index 28cbcb66..6becf383 100644
Binary files a/djangocms_link/locale/vi/LC_MESSAGES/django.mo and b/djangocms_link/locale/vi/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/vi/LC_MESSAGES/django.po b/djangocms_link/locale/vi/LC_MESSAGES/django.po
index 257dd48c..0363bc5f 100644
--- a/djangocms_link/locale/vi/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/vi/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Vietnamese (https://www.transifex.com/divio/teams/58664/vi/)\n"
+"Language-Team: Vietnamese (https://app.transifex.com/divio/teams/58664/vi/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: vi\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/vi_VN/LC_MESSAGES/django.mo b/djangocms_link/locale/vi_VN/LC_MESSAGES/django.mo
deleted file mode 100644
index 9d12dc03..00000000
Binary files a/djangocms_link/locale/vi_VN/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/vi_VN/LC_MESSAGES/django.po b/djangocms_link/locale/vi_VN/LC_MESSAGES/django.po
deleted file mode 100644
index 1f352519..00000000
--- a/djangocms_link/locale/vi_VN/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Vietnamese (Viet Nam) (https://www.transifex.com/divio/teams/58664/vi_VN/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: vi_VN\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/zh-Hans/LC_MESSAGES/django.mo b/djangocms_link/locale/zh-Hans/LC_MESSAGES/django.mo
index b545cdf8..8893fb66 100644
Binary files a/djangocms_link/locale/zh-Hans/LC_MESSAGES/django.mo and b/djangocms_link/locale/zh-Hans/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/zh-Hans/LC_MESSAGES/django.po b/djangocms_link/locale/zh-Hans/LC_MESSAGES/django.po
index 380df8a5..93fd0ecc 100644
--- a/djangocms_link/locale/zh-Hans/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/zh-Hans/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Chinese Simplified (https://www.transifex.com/divio/teams/58664/zh-Hans/)\n"
+"Language-Team: Chinese Simplified (https://app.transifex.com/divio/teams/58664/zh-Hans/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: zh-Hans\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/zh/LC_MESSAGES/django.mo b/djangocms_link/locale/zh/LC_MESSAGES/django.mo
index 7dc5a128..099e54a9 100644
Binary files a/djangocms_link/locale/zh/LC_MESSAGES/django.mo and b/djangocms_link/locale/zh/LC_MESSAGES/django.mo differ
diff --git a/djangocms_link/locale/zh/LC_MESSAGES/django.po b/djangocms_link/locale/zh/LC_MESSAGES/django.po
index d427bca9..f8c5ea69 100644
--- a/djangocms_link/locale/zh/LC_MESSAGES/django.po
+++ b/djangocms_link/locale/zh/LC_MESSAGES/django.po
@@ -8,119 +8,159 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
+"POT-Creation-Date: 2024-10-27 13:38+0100\n"
 "PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Chinese (https://www.transifex.com/divio/teams/58664/zh/)\n"
+"Language-Team: Chinese (https://app.transifex.com/divio/teams/58664/zh/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: zh\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: cms_plugins.py:15
-msgid "Link"
+#: apps.py:7
+msgid "django CMS Link"
 msgstr ""
 
-#: cms_plugins.py:26
-msgid "Link settings"
+#: cms_plugins.py:15 models.py:73
+msgid "Link"
 msgstr ""
 
-#: cms_plugins.py:34
+#: cms_plugins.py:27
 msgid "Advanced settings"
 msgstr ""
 
-#: forms.py:15 models.py:85
+#: fields.py:26 forms.py:15
 msgid "Internal link"
 msgstr ""
 
-#: models.py:27
-msgid "Default"
+#: fields.py:27
+msgid "External link/anchor"
 msgstr ""
 
-#: models.py:44
-msgid "Open in new window"
+#: fields.py:30
+msgid "File link"
 msgstr ""
 
-#: models.py:45
-msgid "Open in same window"
+#: fields.py:169
+msgid "No destination selected. Use the dropdown to select a destination."
 msgstr ""
 
-#: models.py:46
-msgid "Delegate to parent"
+#: fields.py:175
+msgid "https://example.com or #anchor"
 msgstr ""
 
-#: models.py:47
-msgid "Delegate to top"
+#: fields.py:177
+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."
 msgstr ""
 
-#: models.py:65
-msgid "Template"
+#: fields.py:186
+msgid ""
+"Select from available internal destinations. Optionally, add an anchor to "
+"scroll to."
 msgstr ""
 
-#: models.py:71
-msgid "Display name"
+#: fields.py:188
+msgid "Select internal destination"
 msgstr ""
 
-#: models.py:77
-msgid "External link"
+#: fields.py:194
+msgid "#anchor"
 msgstr ""
 
-#: models.py:89
-msgid "If provided, overrides the external link."
+#: fields.py:195
+msgid "Provide an anchor to scroll to."
 msgstr ""
 
-#: models.py:93
-msgid "File link"
+#: fields.py:206
+msgid "Select a file as destination."
 msgstr ""
 
-#: models.py:97
-msgid "If provided links a file from the filer app."
+#: fields.py:215
+msgid "Select site"
 msgstr ""
 
-#: models.py:102
-msgid "Anchor"
+#: fields.py:249
+msgid "Select a link type and provide a link."
 msgstr ""
 
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
+#: models.py:24
+msgid "Default"
 msgstr ""
 
-#: models.py:109
-msgid "Email address"
+#: models.py:41
+msgid "Open in new window"
+msgstr ""
+
+#: models.py:42
+msgid "Open in same window"
+msgstr ""
+
+#: models.py:43
+msgid "Delegate to parent"
 msgstr ""
 
-#: models.py:114
-msgid "Phone"
+#: models.py:44
+msgid "Delegate to top"
 msgstr ""
 
-#: models.py:120
+#: models.py:61
+msgid "Template"
+msgstr ""
+
+#: models.py:67
+msgid "Display name"
+msgstr ""
+
+#: models.py:77
 msgid "Target"
 msgstr ""
 
-#: models.py:126
+#: models.py:83
 msgid "Attributes"
 msgstr ""
 
-#: models.py:151
+#: models.py:109
 msgid "<link is missing>"
 msgstr ""
 
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
+#: models.py:118
+msgid "Link is required."
 msgstr ""
 
-#: models.py:258
-msgid "Please provide a link."
+#: validators.py:50
+msgid "Enter a valid anchor."
 msgstr ""
 
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
+#: validators.py:84
+msgid "Enter a valid phone number"
 msgstr ""
 
-#~ msgid "At least one link is required."
+#~ msgid "Link settings"
+#~ msgstr ""
+
+#~ msgid "If provided, overrides the external link."
+#~ msgstr ""
+
+#~ msgid "If provided links a file from the filer app."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "Appends the value only after the internal or external link. Do <em>not</em> "
+#~ "include a preceding \"#\" symbol."
+#~ msgstr ""
+
+#~ msgid "Email address"
+#~ msgstr ""
+
+#~ msgid "Phone"
+#~ msgstr ""
+
+#~ msgid "Only one of {0} or {1} may be given."
+#~ msgstr ""
+
+#~ msgid ""
+#~ "%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
 #~ msgstr ""
diff --git a/djangocms_link/locale/zh_CN.GB2312/LC_MESSAGES/django.mo b/djangocms_link/locale/zh_CN.GB2312/LC_MESSAGES/django.mo
deleted file mode 100644
index bc68c877..00000000
Binary files a/djangocms_link/locale/zh_CN.GB2312/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/zh_CN.GB2312/LC_MESSAGES/django.po b/djangocms_link/locale/zh_CN.GB2312/LC_MESSAGES/django.po
deleted file mode 100644
index 490bfe65..00000000
--- a/djangocms_link/locale/zh_CN.GB2312/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,126 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Language-Team: Chinese (China) (GB2312) (https://www.transifex.com/divio/teams/58664/zh_CN.GB2312/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: zh_CN.GB2312\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr ""
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/locale/zh_CN/LC_MESSAGES/django.mo b/djangocms_link/locale/zh_CN/LC_MESSAGES/django.mo
deleted file mode 100644
index 7310df3e..00000000
Binary files a/djangocms_link/locale/zh_CN/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/zh_CN/LC_MESSAGES/django.po b/djangocms_link/locale/zh_CN/LC_MESSAGES/django.po
deleted file mode 100644
index b382e55c..00000000
--- a/djangocms_link/locale/zh_CN/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,130 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Chinese (China) (https://www.transifex.com/divio/teams/58664/zh_CN/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: zh_CN\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "链接"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr "电话号码"
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr "请提供最少一个链接"
diff --git a/djangocms_link/locale/zh_TW/LC_MESSAGES/django.mo b/djangocms_link/locale/zh_TW/LC_MESSAGES/django.mo
deleted file mode 100644
index a201854a..00000000
Binary files a/djangocms_link/locale/zh_TW/LC_MESSAGES/django.mo and /dev/null differ
diff --git a/djangocms_link/locale/zh_TW/LC_MESSAGES/django.po b/djangocms_link/locale/zh_TW/LC_MESSAGES/django.po
deleted file mode 100644
index af15a9c4..00000000
--- a/djangocms_link/locale/zh_TW/LC_MESSAGES/django.po
+++ /dev/null
@@ -1,130 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-# 
-# Translators:
-# Angelo Dini <angelo.dini@divio.ch>, 2016
-# 
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-07-03 10:56+0200\n"
-"PO-Revision-Date: 2016-09-15 09:08+0000\n"
-"Last-Translator: Angelo Dini <angelo.dini@divio.ch>, 2016\n"
-"Language-Team: Chinese (Taiwan) (https://www.transifex.com/divio/teams/58664/zh_TW/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: zh_TW\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#: cms_plugins.py:15
-msgid "Link"
-msgstr "連結"
-
-#: cms_plugins.py:26
-msgid "Link settings"
-msgstr ""
-
-#: cms_plugins.py:34
-msgid "Advanced settings"
-msgstr ""
-
-#: forms.py:15 models.py:85
-msgid "Internal link"
-msgstr ""
-
-#: models.py:27
-msgid "Default"
-msgstr ""
-
-#: models.py:44
-msgid "Open in new window"
-msgstr ""
-
-#: models.py:45
-msgid "Open in same window"
-msgstr ""
-
-#: models.py:46
-msgid "Delegate to parent"
-msgstr ""
-
-#: models.py:47
-msgid "Delegate to top"
-msgstr ""
-
-#: models.py:65
-msgid "Template"
-msgstr ""
-
-#: models.py:71
-msgid "Display name"
-msgstr ""
-
-#: models.py:77
-msgid "External link"
-msgstr ""
-
-#: models.py:89
-msgid "If provided, overrides the external link."
-msgstr ""
-
-#: models.py:93
-msgid "File link"
-msgstr ""
-
-#: models.py:97
-msgid "If provided links a file from the filer app."
-msgstr ""
-
-#: models.py:102
-msgid "Anchor"
-msgstr ""
-
-#: models.py:105
-msgid ""
-"Appends the value only after the internal or external link. Do <em>not</em> "
-"include a preceding \"#\" symbol."
-msgstr ""
-
-#: models.py:109
-msgid "Email address"
-msgstr ""
-
-#: models.py:114
-msgid "Phone"
-msgstr ""
-
-#: models.py:120
-msgid "Target"
-msgstr ""
-
-#: models.py:126
-msgid "Attributes"
-msgstr ""
-
-#: models.py:151
-msgid "<link is missing>"
-msgstr ""
-
-#: models.py:246
-#, python-brace-format
-msgid "Only one of {0} or {1} may be given."
-msgstr ""
-
-#: models.py:258
-msgid "Please provide a link."
-msgstr ""
-
-#: models.py:264
-#, python-format
-msgid ""
-"%(anchor_field_verbose_name)s is not allowed together with %(field_name)s"
-msgstr ""
-
-#~ msgid "At least one link is required."
-#~ msgstr ""
diff --git a/djangocms_link/migrations/0017_link_link.py b/djangocms_link/migrations/0017_link_link.py
new file mode 100644
index 00000000..cd8f9505
--- /dev/null
+++ b/djangocms_link/migrations/0017_link_link.py
@@ -0,0 +1,47 @@
+# Generated by Django 4.2.16 on 2024-10-24 19:46
+
+from django.db import migrations
+
+import djangocms_link.fields
+
+
+def forward(apps, schema_editor):
+    Link = apps.get_model("djangocms_link", "Link")
+    links = Link.objects.all()
+    for link in links:
+        if link.external_link:
+            anchor = "#" + link.anchor if link.anchor else ""
+            link.link = {"external_link": link.external_link + anchor}
+        elif link.internal_link:
+            opt = link.internal_link._meta
+            link.link = {"internal_link": f"{opt.app_label}.{opt.model_name}:{link.internal_link.pk}"}
+            if link.anchor:
+                link.link["anchor"] = "#" + link.anchor
+        elif link.file_link:
+            link.link = {"file_link": str(link.file_link.pk)}
+        elif link.phone:
+            link.link = {"external_link": f"tel:{link.phone}"}
+        elif link.mailto:
+            link.link = {"external_link": f"mailto:{link.mailto}"}
+        elif link.anchor:
+            link.link = {"external_link": "#" + link.anchor}
+    Link.objects.bulk_update(links, ["link"])
+
+
+def backward(apps, schema_editor):
+    raise NotImplementedError("Cannot reverse this migration.")
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("djangocms_link", "0016_alter_link_cmsplugin_ptr"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="link",
+            name="link",
+            field=djangocms_link.fields.LinkField(default={}, verbose_name="Link"),
+        ),
+        migrations.RunPython(forward, backward, elidable=True),
+    ]
diff --git a/djangocms_link/migrations/0018_remove_link_anchor_remove_link_external_link_and_more.py b/djangocms_link/migrations/0018_remove_link_anchor_remove_link_external_link_and_more.py
new file mode 100644
index 00000000..ce847aa6
--- /dev/null
+++ b/djangocms_link/migrations/0018_remove_link_anchor_remove_link_external_link_and_more.py
@@ -0,0 +1,36 @@
+# Generated by Django 4.2.16 on 2024-10-24 19:59
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("djangocms_link", "0017_link_link"),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name="link",
+            name="anchor",
+        ),
+        migrations.RemoveField(
+            model_name="link",
+            name="external_link",
+        ),
+        migrations.RemoveField(
+            model_name="link",
+            name="file_link",
+        ),
+        migrations.RemoveField(
+            model_name="link",
+            name="internal_link",
+        ),
+        migrations.RemoveField(
+            model_name="link",
+            name="mailto",
+        ),
+        migrations.RemoveField(
+            model_name="link",
+            name="phone",
+        ),
+    ]
diff --git a/djangocms_link/models.py b/djangocms_link/models.py
index fab94772..61635211 100644
--- a/djangocms_link/models.py
+++ b/djangocms_link/models.py
@@ -2,52 +2,49 @@
 Enables the user to add a "Link" plugin that displays a link
 using the HTML <a> tag.
 """
+
 from django.conf import settings
-from django.contrib.sites.models import Site
 from django.core.exceptions import ValidationError
 from django.db import models
 from django.utils.encoding import force_str
 from django.utils.translation import gettext
 from django.utils.translation import gettext_lazy as _
 
-from cms.models import CMSPlugin, Page
+from cms.models import CMSPlugin
 
 from djangocms_attributes_field.fields import AttributesField
-from filer.fields.file import FilerFileField
 
+from .fields import LinkField
+from .helpers import get_link
 from .validators import IntranetURLValidator
 
 
 # Add additional choices through the ``settings.py``.
 def get_templates():
     choices = [
-        ('default', _('Default')),
+        ("default", _("Default")),
     ]
     choices += getattr(
         settings,
-        'DJANGOCMS_LINK_TEMPLATES',
+        "DJANGOCMS_LINK_TEMPLATES",
         [],
     )
     return choices
 
 
-HOSTNAME = getattr(
-    settings,
-    'DJANGOCMS_LINK_INTRANET_HOSTNAME_PATTERN',
-    None
-)
+HOSTNAME = getattr(settings, "DJANGOCMS_LINK_INTRANET_HOSTNAME_PATTERN", None)
 
 TARGET_CHOICES = (
-    ('_blank', _('Open in new window')),
-    ('_self', _('Open in same window')),
-    ('_parent', _('Delegate to parent')),
-    ('_top', _('Delegate to top')),
+    ("_blank", _("Open in new window")),
+    ("_self", _("Open in same window")),
+    ("_parent", _("Delegate to parent")),
+    ("_top", _("Delegate to top")),
 )
 
 
 class AbstractLink(CMSPlugin):
     # used by django CMS search
-    search_fields = ('name', )
+    search_fields = ("name",)
 
     # allows link requirement to be changed when another
     # CMS plugin inherits from AbstractLink
@@ -58,68 +55,31 @@ class AbstractLink(CMSPlugin):
     ]
 
     template = models.CharField(
-        verbose_name=_('Template'),
+        verbose_name=_("Template"),
         choices=get_templates(),
         default=get_templates()[0][0],
         max_length=255,
     )
     name = models.CharField(
-        verbose_name=_('Display name'),
-        blank=True,
-        max_length=255,
-    )
-    # re: max_length, see: http://stackoverflow.com/questions/417142/
-    external_link = models.CharField(
-        verbose_name=_('External link'),
-        blank=True,
-        max_length=2040,
-        validators=url_validators,
-        help_text=_('Provide a link to an external source.'),
-    )
-    internal_link = models.ForeignKey(
-        Page,
-        verbose_name=_('Internal link'),
-        blank=True,
-        null=True,
-        on_delete=models.SET_NULL,
-        help_text=_('If provided, overrides the external link.'),
-    )
-    file_link = FilerFileField(
-        verbose_name=_('File link'),
-        blank=True,
-        null=True,
-        on_delete=models.SET_NULL,
-        help_text=_('If provided links a file from the filer app.'),
-    )
-    # other link types
-    anchor = models.CharField(
-        verbose_name=_('Anchor'),
-        blank=True,
-        max_length=255,
-        help_text=_('Appends the value only after the internal or external link. '
-                    'Do <em>not</em> include a preceding "#" symbol.'),
-    )
-    mailto = models.EmailField(
-        verbose_name=_('Email address'),
+        verbose_name=_("Display name"),
         blank=True,
         max_length=255,
     )
-    phone = models.CharField(
-        verbose_name=_('Phone'),
-        blank=True,
-        max_length=255,
+
+    link = LinkField(
+        verbose_name=_("Link"),
     )
     # advanced options
     target = models.CharField(
-        verbose_name=_('Target'),
+        verbose_name=_("Target"),
         choices=TARGET_CHOICES,
         blank=True,
         max_length=255,
     )
     attributes = AttributesField(
-        verbose_name=_('Attributes'),
+        verbose_name=_("Attributes"),
         blank=True,
-        excluded_keys=['href', 'target'],
+        excluded_keys=["href", "target"],
     )
 
     # Add an app namespace to related_name to avoid field name clashes
@@ -128,7 +88,7 @@ class AbstractLink(CMSPlugin):
     # https://github.com/divio/django-cms/issues/5030
     cmsplugin_ptr = models.OneToOneField(
         CMSPlugin,
-        related_name='%(app_label)s_%(class)s',
+        related_name="%(app_label)s_%(class)s",
         parent_link=True,
         on_delete=models.CASCADE,
     )
@@ -140,132 +100,27 @@ def __str__(self):
         return self.name or str(self.pk)
 
     def get_short_description(self):
-        if self.name and self.get_link():
-            return f'{self.name} ({self.get_link()})'
-        return self.name or self.get_link() or gettext('<link is missing>')
-
-    def get_link(self):
-        if self.internal_link:
-            ref_page = self.internal_link
-            link = ref_page.get_absolute_url()
+        link = self.get_link()
+        if self.name and link:
+            return f"{self.name} ({link})"
+        return self.name or link or gettext("<link is missing>")
 
-            # simulate the call to the unauthorized CMSPlugin.page property
-            cms_page = self.placeholder.page if self.placeholder_id else None
-
-            # first, we check if the placeholder the plugin is attached to
-            # has a page. Thus the check "is not None":
-            if cms_page is not None:
-                if getattr(cms_page, 'node', None):
-                    cms_page_site_id = getattr(cms_page.node, 'site_id', None)
-                else:
-                    cms_page_site_id = getattr(cms_page, 'site_id', None)
-            # a plugin might not be attached to a page and thus has no site
-            # associated with it. This also applies to plugins inside
-            # static placeholders
-            else:
-                cms_page_site_id = None
-
-            # now we do the same for the reference page the plugin links to
-            # in order to compare them later
-            if cms_page is not None:
-                if getattr(cms_page, 'node', None):
-                    ref_page_site_id = ref_page.node.site_id
-                else:
-                    ref_page_site_id = ref_page.site_id
-            # if no external reference is found the plugin links to the
-            # current page
-            else:
-                ref_page_site_id = Site.objects.get_current().pk
-
-            if ref_page_site_id != cms_page_site_id:
-                ref_site = Site.objects._get_site_by_id(ref_page_site_id).domain
-                link = f'//{ref_site}{link}'
-
-        elif self.file_link:
-            link = self.file_link.url
-
-        elif self.external_link:
-            link = self.external_link
-
-        elif self.phone:
-            link = 'tel:{}'.format(self.phone.replace(' ', ''))
-
-        elif self.mailto:
-            link = f'mailto:{self.mailto}'
-
-        else:
-            link = ''
-
-        if (not self.phone and not self.mailto) and self.anchor:
-            link += f'#{self.anchor}'
-
-        return link
+    def get_link(self, site_id=None):
+        return get_link(self.link, site_id)
 
     def clean(self):
         super().clean()
-        field_names = (
-            'external_link',
-            'internal_link',
-            'mailto',
-            'phone',
-            'file_link',
-        )
-        anchor_field_name = 'anchor'
-        field_names_allowed_with_anchor = (
-            'external_link',
-            'internal_link',
-        )
-
-        anchor_field_verbose_name = force_str(
-           self._meta.get_field(anchor_field_name).verbose_name)
-        anchor_field_value = getattr(self, anchor_field_name)
-
-        link_fields = {
-            key: getattr(self, key)
-            for key in field_names
-        }
-        link_field_verbose_names = {
-            key: force_str(self._meta.get_field(key).verbose_name)
-            for key in link_fields.keys()
-        }
-        provided_link_fields = {
-            key: value
-            for key, value in link_fields.items()
-            if value
-        }
-
-        if len(provided_link_fields) > 1:
-            # Too many fields have a value.
-            verbose_names = sorted(link_field_verbose_names.values())
-            error_msg = _('Only one of {0} or {1} may be given.').format(
-                ', '.join(verbose_names[:-1]),
-                verbose_names[-1],
-            )
-            errors = {}.fromkeys(provided_link_fields.keys(), error_msg)
-            raise ValidationError(errors)
-
-        if (len(provided_link_fields) == 0
-                and not self.anchor
-                and not self.link_is_optional):
-
+        if not self.link_is_optional and not self.link:
             raise ValidationError(
-                _('Please provide a link.')
+                force_str(_("Link is required.")),
+                code="required",
             )
 
-        if anchor_field_value:
-            for field_name in provided_link_fields.keys():
-                if field_name not in field_names_allowed_with_anchor:
-                    error_msg = _('%(anchor_field_verbose_name)s is not allowed together with %(field_name)s') % {
-                        'anchor_field_verbose_name': anchor_field_verbose_name,
-                        'field_name': link_field_verbose_names.get(field_name)
-                    }
-                    raise ValidationError({
-                        anchor_field_name: error_msg,
-                        field_name: error_msg,
-                    })
+    def __init__(self, *args, **wkargs):
+        super().__init__(*args, **wkargs)
+        self._meta.get_field("link").blank = self.link_is_optional
 
 
 class Link(AbstractLink):
-
     class Meta:
         abstract = False
diff --git a/djangocms_link/static/djangocms_link/link-widget.css b/djangocms_link/static/djangocms_link/link-widget.css
new file mode 100644
index 00000000..9a70b123
--- /dev/null
+++ b/djangocms_link/static/djangocms_link/link-widget.css
@@ -0,0 +1,76 @@
+.link-widget {
+    width: 100%;
+    display: block;
+    margin-bottom: 0.5em;
+    .link-type-selector {
+        margin-inline-end: 1em;
+        display: inline-block;
+        width: calc(25% - 1em);
+        flex-shrink: 2;
+        select {
+            width: 100%;
+            min-width: unset;
+        }
+    }
+    .external_link, .internal_link, .file_link, .anchor, .site {
+        display: none;
+        padding: 0;
+        select, input {
+            width: 100%;
+        }
+        span.select2 {
+            display: inline-block;
+            width: 100% !important;
+        }
+    }
+    .external_link {
+        width: 75%;
+    }
+    .internal_link {
+        width: calc(60% - 1em);
+        margin-inline-end: 1em;
+    }
+    .anchor {
+        width: 15%;  /* end of line, no 1em margin to remove */
+    }
+    .file_link {
+        margin-top: 0.5em;
+    }
+    &[data-type="external_link"] .external_link,
+    &[data-type="internal_link"] .internal_link,
+    &[data-type="internal_link"] .site,
+    &[data-type="internal_link"] .anchor
+    {
+        display: inline-block;
+    }
+    &[data-type="file_link"] .file_link {
+        display: block;
+        width: 100%;
+    }
+    &[data-type="file_link"] .link-type-selector,
+    &[data-type="empty"] .link-type-selector{
+        margin-inline-end: 0;
+    }
+
+    &:has(.site) {
+        /* if site subwidget is present, arrange widgets in two lines */
+        .site {
+            width: 75%;
+            margin-inline-end: 0;
+            margin-bottom: 0.5em;
+        }
+        .internal_link {
+            width: calc(60% - 1em);
+            margin-inline-start: 25%;
+            margin-inline-end: 1em;
+        }
+        .anchor (
+            margin-top: -3em;
+        )
+    )
+    }
+
+    .select2-container .select2-selection--single {
+        height: 2.55em;
+    }
+}
diff --git a/djangocms_link/static/djangocms_link/link-widget.js b/djangocms_link/static/djangocms_link/link-widget.js
new file mode 100644
index 00000000..47e737fa
--- /dev/null
+++ b/djangocms_link/static/djangocms_link/link-widget.js
@@ -0,0 +1,42 @@
+/* eslint-env es11 */
+/* jshint esversion: 11 */
+/* global document django */
+
+document.addEventListener('DOMContentLoaded' , () => {
+    'use strict';
+
+    const updateSelection = (el) => {
+        const widget = el.closest('.link-widget');
+        const help = widget.closest('.form-row')?.querySelector('div.help');
+        widget.dataset.type = el.value;
+
+        if (help) {
+            if (el.value === 'empty') {
+                help.textContent = el.dataset.help || '';
+            } else {
+                help.textContent = widget.querySelector(`[widget="${el.value}"]`)?.dataset.help || '';
+            }
+        }
+    };
+    for (let item of document.querySelectorAll('.js-link-widget-selector')) {
+        updateSelection(item);
+        item.addEventListener("change", (e) => {
+            updateSelection(e.target);
+            e.target.closest('.link-widget').querySelector('input[widget="anchor"]').value = '';
+        });
+    }
+
+    // If site widget changes, clear internal link widget
+    for (let item of document.querySelectorAll('.js-link-site-widget')) {
+        console.warn(item);
+        django.jQuery(item).on('change', e => {
+            const site_select2 = django.jQuery(e.target);
+            const internal_link_select2 = site_select2.closest('.link-widget').find('[widget="internal_link"]');
+            internal_link_select2.attr('data-app-label', site_select2.val());
+            internal_link_select2.val(null).trigger('change');
+        });
+        item.addEventListener("change", (e) => {
+            console.warn(e.target.closest('.link-widget').querySelector('[widget="internal_link"]'));
+        });
+    }
+});
diff --git a/djangocms_link/templates/djangocms_link/admin/link_widget.html b/djangocms_link/templates/djangocms_link/admin/link_widget.html
new file mode 100644
index 00000000..7480e7c5
--- /dev/null
+++ b/djangocms_link/templates/djangocms_link/admin/link_widget.html
@@ -0,0 +1,6 @@
+{% spaceless %}<div name="{{ widget.name }}" class="link-widget widget"{% include "django/forms/widgets/attrs.html" %}>
+    {% for name, widget in widget.subwidgets.items %}
+        <div class="{{ name }}">{% include widget.template_name %}</div>
+    {% endfor %}
+    {% if filer_widget %}<div class="file_link">{{ filer_widget }}</div>{% endif %}
+</div>{% endspaceless %}
diff --git a/djangocms_link/templates/djangocms_link/default/link.html b/djangocms_link/templates/djangocms_link/default/link.html
index fb7f277b..27815549 100644
--- a/djangocms_link/templates/djangocms_link/default/link.html
+++ b/djangocms_link/templates/djangocms_link/default/link.html
@@ -1,17 +1,3 @@
 {% load cms_tags %}{% spaceless %}
-
 {# this needs to be in one line for rendering purpose #}
-{% endspaceless %}<a href="{{ link }}"{% if instance.target %} target="{{ instance.target }}"{% endif %}{% if instance.attributes %} {{ instance.attributes_str }}{% endif %}>{% for plugin in instance.child_plugin_instances %}{% render_plugin plugin %}{% empty %}{{ instance.name }}{% endfor %}</a>{% spaceless %}
-
-{% endspaceless %}{% comment %}
-# https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a
-    {{ instance.name }}
-    {{ link }} or {{ instance.get_link }} summarizes:
-        {{ instance.external_link }}
-        {{ instance.internal_link }}
-        {{ instance.anchor }}
-        {{ instance.mailto }}
-        {{ instance.phone }}
-    {{ instance.target }}
-    {{ instance.attributes_str }}
-{% endcomment %}
\ No newline at end of file
+{% endspaceless %}{% if link %}<a href="{{ link }}"{% if instance.target %} target="{{ instance.target }}"{% endif %}{% if instance.attributes %} {{ instance.attributes_str }}{% endif %}>{% for plugin in instance.child_plugin_instances %}{% render_plugin plugin %}{% empty %}{{ instance.name }}{% endfor %}</a>{% else %}<span{% if instance.attributes %} {{ instance.attributes_str }}{% endif %}>{% for plugin in instance.child_plugin_instances %}{% render_plugin plugin %}{% empty %}{{ instance.name }}{% endfor %}</span>{% endif %}
\ No newline at end of file
diff --git a/djangocms_link/templatetags/__init__.py b/djangocms_link/templatetags/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/djangocms_link/templatetags/djangocms_link_tags.py b/djangocms_link/templatetags/djangocms_link_tags.py
new file mode 100644
index 00000000..764fdd3d
--- /dev/null
+++ b/djangocms_link/templatetags/djangocms_link_tags.py
@@ -0,0 +1,24 @@
+from django import template
+
+from djangocms_link.helpers import LinkDict, get_link
+
+
+try:
+    from filer.models import File
+except (ImportError, ModuleNotFoundError):  # pragma: no cover
+
+    class File:
+        pass
+
+
+register = template.Library()
+
+
+@register.filter
+def to_url(value):
+    return get_link(value) or ""
+
+
+@register.filter
+def to_link(value):
+    return LinkDict(value)
diff --git a/djangocms_link/validators.py b/djangocms_link/validators.py
index c456d694..4fed5ff9 100644
--- a/djangocms_link/validators.py
+++ b/djangocms_link/validators.py
@@ -1,6 +1,9 @@
 import re
 
-from django.core.validators import URLValidator
+from django.core.exceptions import ValidationError
+from django.core.validators import EmailValidator, URLValidator
+from django.utils.deconstruct import deconstructible
+from django.utils.translation import gettext as _
 
 
 class IntranetURLValidator(URLValidator):
@@ -14,29 +17,96 @@ class IntranetURLValidator(URLValidator):
         DJANGOCMS_LINK_INTRANET_HOSTNAME_PATTERN = r'[a-z,0-9,-]{1,15}'
     """
 
-    ul = '\u00a1-\uffff'  # unicode letters range (must be a unicode string, not a raw string)
+    ul = "\u00a1-\uffff"  # unicode letters range (must be a unicode string, not a raw string)
 
     # IP patterns
-    ipv4_re = r'(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'
-    ipv6_re = r'\[[0-9a-f:\.]+\]'  # (simple regex, validated later)
+    ipv4_re = (
+        r"(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}"
+    )
+    ipv6_re = r"\[[0-9a-f:\.]+\]"  # (simple regex, validated later)
 
     # Host patterns
-    hostname_re = r'[a-z' + ul + r'0-9](?:[a-z' + ul + r'0-9-]*[a-z' + ul + r'0-9])?'
-    domain_re = r'(?:\.[a-z' + ul + r'0-9]+(?:[a-z' + ul + r'0-9-]*[a-z' + ul + r'0-9]+)*)*'
-    tld_re = r'\.[a-z' + ul + r']{2,}\.?'
-    host_re = '(' + hostname_re + domain_re + tld_re + '|localhost)'
+    hostname_re = r"[a-z" + ul + r"0-9](?:[a-z" + ul + r"0-9-]*[a-z" + ul + r"0-9])?"
+    domain_re = (
+        r"(?:\.[a-z" + ul + r"0-9]+(?:[a-z" + ul + r"0-9-]*[a-z" + ul + r"0-9]+)*)*"
+    )
+    tld_re = r"\.[a-z" + ul + r"]{2,}\.?"
+    host_re = "(" + hostname_re + domain_re + tld_re + "|localhost)"
 
     def __init__(self, intranet_host_re=None, **kwargs):
         super().__init__(**kwargs)
         if intranet_host_re:
             self.host_re = (
-                '(' + self.hostname_re + self.domain_re + self.tld_re +
-                '|' + intranet_host_re + '|localhost)'
+                "("
+                + self.hostname_re
+                + self.domain_re
+                + self.tld_re
+                + "|"
+                + intranet_host_re
+                + "|localhost)"
             )
             self.regex = re.compile(
-                r'^(?:[a-z0-9\.\-]*)://'
-                r'(?:\S+(?::\S*)?@)?'
-                r'(?:' + self.ipv4_re + '|' + self.ipv6_re + '|' + self.host_re + ')'
-                r'(?::\d{2,5})?'
-                r'(?:[/?#][^\s]*)?'
-                r'$', re.IGNORECASE)
+                r"^(?:[a-z0-9\.\-]*)://"
+                r"(?:\S+(?::\S*)?@)?"
+                r"(?:" + self.ipv4_re + "|" + self.ipv6_re + "|" + self.host_re + ")"
+                r"(?::\d{2,5})?"
+                r"(?:[/?#][^\s]*)?"
+                r"$",
+                re.IGNORECASE,
+            )
+
+
+@deconstructible
+class AnchorValidator:
+    message = _("Enter a valid anchor")
+    code = "invalid"
+
+    def __call__(self, value: str):
+        value = value.lstrip("#")
+        if not value:
+            return value
+        if not isinstance(value, str) or len(value) > 100:
+            raise ValidationError(self.message, code=self.code, params={"value": value})
+
+        if not re.match(r"^[a-zA-Z0-9_\-]+$", value):
+            raise ValidationError(self.message, code=self.code, params={"value": value})
+        return value
+
+
+class ExtendedURLValidator(IntranetURLValidator):
+    # Phone numbers don't match the host regex in Django's validator,
+    # so we test for a simple alternative.
+    tel_re = r"^tel\:[0-9 \#\*\-\.\(\)\+]+$"
+
+    def __init__(self, allowed_link_types: list = None, **kwargs):
+        self.allowed_link_types = allowed_link_types
+        super().__init__(**kwargs)
+
+    def __call__(self, value: str):
+        if not isinstance(value, str) or len(value) > self.max_length:
+            raise ValidationError(self.message, code=self.code, params={"value": value})
+        if self.unsafe_chars.intersection(value):
+            raise ValidationError(self.message, code=self.code, params={"value": value})
+        # Check if just an anchor
+        if value.startswith("#") and (
+            self.allowed_link_types is None or "anchor" in self.allowed_link_types
+        ):
+            return AnchorValidator()(value)
+        # Check if the scheme is valid.
+        scheme = value.split(":")[0].lower()
+        if scheme == "tel" and (
+            self.allowed_link_types is None or "tel" in self.allowed_link_types
+        ):
+            if re.match(self.tel_re, value):
+                return
+            else:
+                raise ValidationError(
+                    _("Enter a valid phone number"),
+                    code=self.code,
+                    params={"value": value},
+                )
+        if scheme == "mailto" and (
+            self.allowed_link_types is None or "mailto" in self.allowed_link_types
+        ):
+            return EmailValidator()(value[7:])
+        return super().__call__(value)
diff --git a/preview.gif b/preview.gif
index c49da778..969c224f 100644
Binary files a/preview.gif and b/preview.gif differ
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 00000000..6457245c
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,124 @@
+[build-system]
+build-backend = "setuptools.build_meta"
+
+requires = [ "setuptools", "setuptools-scm" ]
+
+[project]
+name = "djangocms-link"
+description = "Adds a link plugin to django CMS"
+readme = "README.rst"
+license = { text = "BSD-3-Clause" }
+maintainers = [
+  { name = "Django CMS Association and contributors", email = "info@django-cms.org" },
+]
+authors = [
+  { name = "Divio AG", email = "info@divio.ch" },
+]
+requires-python = ">=3.9"
+
+classifiers = [
+  "Development Status :: 5 - Production/Stable",
+  "Environment :: Web Environment",
+  "Framework :: Django",
+  "Framework :: Django :: 4.2",
+  "Framework :: Django :: 5.0",
+  "Framework :: Django :: 5.1",
+  "Framework :: Django CMS",
+  "Framework :: Django CMS :: 3.11",
+  "Framework :: Django CMS :: 4.0",
+  "Framework :: Django CMS :: 4.1",
+  "Intended Audience :: Developers",
+  "License :: OSI Approved :: BSD License",
+  "Operating System :: OS Independent",
+  "Programming Language :: Python",
+  "Programming Language :: Python :: 3 :: Only",
+  "Programming Language :: Python :: 3.9",
+  "Programming Language :: Python :: 3.10",
+  "Programming Language :: Python :: 3.11",
+  "Programming Language :: Python :: 3.12",
+  "Programming Language :: Python :: 3.13",
+  "Topic :: Internet :: WWW/HTTP",
+  "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
+  "Topic :: Software Development",
+  "Topic :: Software Development :: Libraries",
+]
+dynamic = [ "version" ]
+dependencies = [
+  "django-cms>=3.7,!=4.1,!=4.1.1,!=4.1.2",
+  "djangocms-attributes-field>=1",
+]
+urls.Homepage = "https://github.com/django-cms/djangocms-link"
+
+[tool.setuptools]
+packages = [ "djangocms_link" ]
+
+[tool.setuptools.dynamic]
+version = { attr = "djangocms_link.__version__" }
+
+[tool.isort]
+line_length = 119
+skip = [
+  "manage.py",
+  "*migrations*",
+  ".tox",
+  ".eggs",
+  ".env",
+  ".venv",
+  "data",
+]
+include_trailing_comma = true
+multi_line_output = 5
+lines_after_imports = 2
+default_section = "THIRDPARTY"
+sections = [
+  "FUTURE",
+  "STDLIB",
+  "DJANGO",
+  "CMS",
+  "THIRDPARTY",
+  "FIRSTPARTY",
+  "LOCALFOLDER",
+]
+known_first_party = "djangocms_link"
+known_cms = [ "cms", "menus" ]
+known_django = "django"
+
+[tool.flake8]
+max-line-length = 119
+exclude = [
+  "*.egg-info",
+  ".eggs",
+  ".env",
+  ".git",
+  ".settings",
+  ".tox",
+  ".venv",
+  "build",
+  "data",
+  "dist",
+  "docs",
+  "*migrations*",
+  "requirements",
+  "tmp",
+]
+
+[tool.coverage.run]
+branch = true
+source = [ "djangocms_link" ]
+omit = [
+  "migrations/*",
+  "tests/*",
+]
+
+[tool.coverage.report]
+exclude_lines = [
+  "pragma: no cover",
+  "def __repr__",
+  "if self.debug:",
+  "if settings.DEBUG",
+  "raise AssertionError",
+  "raise NotImplementedError",
+  "if 0:",
+  "if __name__ == .__main__.:",
+]
+ignore_errors = true
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 6b26cc22..00000000
--- a/setup.cfg
+++ /dev/null
@@ -1,29 +0,0 @@
-[flake8]
-max-line-length = 119
-exclude =
-    *.egg-info,
-    .eggs,
-    .env,
-    .git,
-    .settings,
-    .tox,
-    .venv,
-    build,
-    data,
-    dist,
-    docs,
-    *migrations*,
-    requirements,
-    tmp
-
-[isort]
-line_length = 119
-skip = manage.py, *migrations*, .tox, .eggs, .env, .venv, data
-include_trailing_comma = true
-multi_line_output = 5
-lines_after_imports = 2
-default_section = THIRDPARTY
-sections = FUTURE, STDLIB, DJANGO, CMS, THIRDPARTY, FIRSTPARTY, LOCALFOLDER
-known_first_party = djangocms_link
-known_cms = cms, menus
-known_django = django
diff --git a/setup.py b/setup.py
index 4deb3e46..25980616 100644
--- a/setup.py
+++ b/setup.py
@@ -1,56 +1,5 @@
 #!/usr/bin/env python
-from setuptools import find_packages, setup
+from setuptools import setup
 
-from djangocms_link import __version__
 
-
-REQUIREMENTS = [
-    'django-cms>=3.7',
-    'django-filer>=1.7',
-    'djangocms-attributes-field>=1',
-]
-
-
-CLASSIFIERS = [
-    'Development Status :: 5 - Production/Stable',
-    'Environment :: Web Environment',
-    'Intended Audience :: Developers',
-    'License :: OSI Approved :: BSD License',
-    'Operating System :: OS Independent',
-    'Programming Language :: Python',
-    'Programming Language :: Python :: 3',
-    'Programming Language :: Python :: 3.8',
-    'Programming Language :: Python :: 3.9',
-    'Programming Language :: Python :: 3.10',
-    'Framework :: Django',
-    'Framework :: Django :: 3.2',
-    'Framework :: Django :: 4.0',
-    'Framework :: Django CMS',
-    'Framework :: Django CMS :: 3.9',
-    'Framework :: Django CMS :: 3.10',
-    'Framework :: Django CMS :: 3.11',
-    'Topic :: Internet :: WWW/HTTP',
-    'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
-    'Topic :: Software Development',
-    'Topic :: Software Development :: Libraries',
-]
-
-
-setup(
-    name='djangocms-link',
-    version=__version__,
-    author='Divio AG',
-    author_email='info@divio.ch',
-    maintainer='Django CMS Association and contributors',
-    maintainer_email='info@django-cms.org',
-    url='https://github.com/django-cms/djangocms-link',
-    license='BSD-3-Clause',
-    description='Adds a link plugin to django CMS',
-    long_description=open('README.rst').read(),
-    packages=find_packages(),
-    include_package_data=True,
-    zip_safe=False,
-    install_requires=REQUIREMENTS,
-    classifiers=CLASSIFIERS,
-    test_suite='tests.settings.run',
-)
+setup()
diff --git a/tox.ini b/tox.ini
index 838fcd7b..8f5ab358 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,33 +1,20 @@
 [tox]
 envlist =
-    flake8
-    isort
-    py{38,39,310}-dj{32}-cms{310,311}
-    py{38,39,310}-dj{40}-cms{311}
-    py{39,310}-dj{40,42}-cms{41}
+    py{39,310,311}-dj{42}-cms{311}
+    py{310,311,312}-dj{42,50,51}-cms{41}
 
 skip_missing_interpreters=True
 
 [testenv]
 deps =
     -r{toxinidir}/tests/requirements/base.txt
-    dj32: Django>=3.2,<4.0
-    dj40: Django>=4.0,<4.1
     dj42: Django>=4.2,<5.0
-    cms310: django-cms>=3.10,<3.11
-    cms311: django-cms>=3.11,<3.12
+    dj50: Django>=5.0,<5.1
+    dj51: Django>=5.1,<5.2
+    cms311: django-cms>=3.11,<4
     cms41: django-cms>=4.1,<4.2
 commands =
     {envpython} --version
     {env:COMMAND:coverage} erase
-    {env:COMMAND:coverage} run setup.py test
+    {env:COMMAND:coverage} run -m pytest
     {env:COMMAND:coverage} report
-
-[testenv:flake8]
-deps = flake8
-commands = flake8
-
-[testenv:isort]
-deps = isort
-commands = isort --check --diff djangocms_link
-skip_install = true


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 96f8208d..a7db4aa3 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -8,32 +8,45 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        python-version: [ "3.10", "3.11", "3.12"]  # latest release minus two
+        python-version: [ "3.9", "3.10", "3.11", "3.12"]
         requirements-file: [
           dj42_cms311.txt,
           dj42_cms41.txt,
           dj50_cms311.txt,
           dj50_cms41.txt,
+          dj51_cms41.txt,
         ]
         os: [
           ubuntu-20.04,
         ]
+        exclude:
+          - requirements-file: dj50_cms311.txt
+            python-version: 3.9
+          - requirements-file: dj50_cms41.txt
+            python-version: 3.9
+          - requirements-file: dj51_cms311.txt
+            python-version: 3.9
+          - requirements-file: dj51_cms41.txt
+            python-version: 3.9
 
     steps:
-    - uses: actions/checkout@v1
+    - uses: actions/checkout@v4
     - name: Set up Python ${{ matrix.python-version }}
 
-      uses: actions/setup-python@v2
+      uses: actions/setup-python@v5
       with:
         python-version: ${{ matrix.python-version }}
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
+        pip install -U setuptools
         pip install -r tests/requirements/${{ matrix.requirements-file }}
         python setup.py install
 
-    - name: Run coverage
-      run: coverage run setup.py test
+    - name: Run test coverage
+      run: coverage run -m pytest
 
     - name: Upload Coverage to Codecov
-      uses: codecov/codecov-action@v1
+      uses: codecov/codecov-action@v4
+      with:
+        token: ${{ secrets.CODECOV_TOKEN }} # required
diff --git a/conftest.py b/conftest.py
new file mode 100755
index 00000000..a7663e4e
--- /dev/null
+++ b/conftest.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+import os
+import sys
+
+import django
+from django.conf import global_settings, settings
+from django.test.utils import get_runner
+
+from tests.settings import HELPER_SETTINGS
+
+
+CMS_APP = [
+    "cms",
+    "menus",
+    "easy_thumbnails",
+    "treebeard",
+    "sekizai",
+    "djangocms_link",
+]
+CMS_APP_STYLE = []
+CMS_PROCESSORS = []
+CMS_MIDDLEWARE = [
+    "cms.middleware.user.CurrentUserMiddleware",
+    "cms.middleware.page.CurrentPageMiddleware",
+    "cms.middleware.toolbar.ToolbarMiddleware",
+    "cms.middleware.language.LanguageCookieMiddleware",
+]
+
+INSTALLED_APPS = (
+    [
+        "django.contrib.contenttypes",
+        "django.contrib.auth",
+        "django.contrib.sessions",
+        "django.contrib.sites",
+        "django.contrib.staticfiles",
+    ]
+    + CMS_APP_STYLE
+    + ["django.contrib.admin", "django.contrib.messages"]
+    + CMS_APP
+)
+DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}}
+TEMPLATE_CONTEXT_PROCESSORS = [
+    "django.template.context_processors.debug",
+    "django.template.context_processors.request",
+    "django.contrib.auth.context_processors.auth",
+    "django.contrib.messages.context_processors.messages",
+] + CMS_PROCESSORS
+TEMPLATES = [
+    {
+        "BACKEND": "django.template.backends.django.DjangoTemplates",
+        "DIRS": [
+            os.path.join(os.path.dirname(__file__), "templates"),
+            # insert your TEMPLATE_DIRS here
+        ],
+        "APP_DIRS": True,
+        "OPTIONS": {
+            "context_processors": TEMPLATE_CONTEXT_PROCESSORS,
+        },
+    },
+]
+MIDDLEWARE = [
+    "django.middleware.http.ConditionalGetMiddleware",
+    "django.contrib.sessions.middleware.SessionMiddleware",
+    "django.contrib.auth.middleware.AuthenticationMiddleware",
+    "django.contrib.messages.middleware.MessageMiddleware",
+    "django.middleware.csrf.CsrfViewMiddleware",
+    "django.middleware.locale.LocaleMiddleware",
+    "django.middleware.common.CommonMiddleware",
+] + CMS_MIDDLEWARE
+SITE_ID = 1
+LANGUAGE_CODE = "en"
+LANGUAGES = (("en", "English"),)
+STATIC_URL = "/static/"
+MEDIA_URL = "/media/"
+MIGRATION_MODULES = {}
+URL_CONF = "tests.utils.urls"
+
+
+def pytest_configure():
+    INSTALLED_APPS.extend(HELPER_SETTINGS.pop("INSTALLED_APPS"))
+
+    settings.configure(
+        default_settings=global_settings,
+        **{
+            **dict(
+                INSTALLED_APPS=INSTALLED_APPS,
+                TEMPLATES=TEMPLATES,
+                DATABASES=DATABASES,
+                SITE_ID=SITE_ID,
+                LANGUAGE_CODE=LANGUAGE_CODE,
+                LANGUAGES=LANGUAGES,
+                MIGRATION_MODULES=MIGRATION_MODULES,
+                ROOT_URLCONF=URL_CONF,
+                STATIC_URL=STATIC_URL,
+                MEDIA_URL=MEDIA_URL,
+                SECRET_KEY="Secret!",
+                MIDDLEWARE=MIDDLEWARE,
+            ),
+            **HELPER_SETTINGS,
+        }
+    )
+    django.setup()
+
+
+if __name__ == "__main__":
+    pytest_configure()
+
+    argv = ["tests"] if sys.argv is None else sys.argv
+    tests = argv[1:] if len(argv) > 1 else ["tests"]
+    TestRunner = get_runner(settings)
+    test_runner = TestRunner()
+    failures = test_runner.run_tests(tests)
+    sys.exit(bool(failures))
diff --git a/tests/requirements/base.txt b/tests/requirements/base.txt
index b8239246..44d1718f 100644
--- a/tests/requirements/base.txt
+++ b/tests/requirements/base.txt
@@ -1,9 +1,11 @@
-django-select2>=5.11,<7 # 7 works in Django 2+
 django-filer>=1.5.0
 html5lib>=1
-django-app-helper
 tox
 coverage
 isort
 flake8
+flake8-pyproject
 pyflakes>=2.1
+django-test-migrations
+pytest
+pytest-django
diff --git a/tests/requirements/dj51_cms41.txt b/tests/requirements/dj51_cms41.txt
new file mode 100644
index 00000000..3e2807c1
--- /dev/null
+++ b/tests/requirements/dj51_cms41.txt
@@ -0,0 +1,4 @@
+-r base.txt
+
+Django>=5.1,<5.2
+django-cms>=4.1,<4.2
diff --git a/tests/settings.py b/tests/settings.py
index 0914f9b6..52de5244 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -3,39 +3,41 @@
 
 
 HELPER_SETTINGS = {
-    'INSTALLED_APPS': [
-        'filer',
-        'django_select2',
-        'tests.utils',
+    "INSTALLED_APPS": [
+        "filer",
+        "tests.utils",
     ],
-    'CMS_LANGUAGES': {
-        1: [{
-            'code': 'en',
-            'name': 'English',
-        }]
+    "CMS_LANGUAGES": {
+        1: [
+            {
+                "code": "en",
+                "name": "English",
+            }
+        ]
     },
-    'LANGUAGE_CODE': 'en',
-    'THUMBNAIL_PROCESSORS': (
-        'easy_thumbnails.processors.colorspace',
-        'easy_thumbnails.processors.autocrop',
-        'filer.thumbnail_processors.scale_and_crop_with_subject_location',
-        'easy_thumbnails.processors.filters',
+    "LANGUAGE_CODE": "en",
+    "THUMBNAIL_PROCESSORS": (
+        "easy_thumbnails.processors.colorspace",
+        "easy_thumbnails.processors.autocrop",
+        "filer.thumbnail_processors.scale_and_crop_with_subject_location",
+        "easy_thumbnails.processors.filters",
     ),
-    'ALLOWED_HOSTS': ['localhost'],
-    'DJANGOCMS_LINK_USE_SELECT2': True,
-    'CMS_TEMPLATES': (
-        ('page.html', 'Normal page'),
-        ('static_placeholder.html', 'Page with static placeholder'),
+    "ALLOWED_HOSTS": ["localhost"],
+    "CMS_TEMPLATES": (
+        ("page.html", "Normal page"),
+        ("static_placeholder.html", "Page with static placeholder"),
     ),
-    'FILE_UPLOAD_TEMP_DIR': mkdtemp(),
-    'CMS_CONFIRM_VERSION4': True
+    "FILE_UPLOAD_TEMP_DIR": mkdtemp(),
+    "CMS_CONFIRM_VERSION4": True,
+    "DJANGOCMS_LINKABLE_MODELS": ["utils.thirdpartymodel"],
 }
 
 
 def run():
     from app_helper import runner
-    runner.cms('djangocms_link')
 
+    runner.cms("djangocms_link")
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     run()
diff --git a/tests/test_endpoint.py b/tests/test_endpoint.py
new file mode 100644
index 00000000..57084e30
--- /dev/null
+++ b/tests/test_endpoint.py
@@ -0,0 +1,302 @@
+from django.contrib import admin
+from django.contrib.sites.models import Site
+
+from cms.api import create_page
+from cms.models import Page
+from cms.test_utils.testcases import CMSTestCase
+from cms.utils.urlutils import admin_reverse
+
+from djangocms_link.models import Link
+from tests.utils.models import ThirdPartyModel
+
+
+class LinkEndpointTestCase(CMSTestCase):
+    def setUp(self):
+        self.root_page = create_page(
+            title="root",
+            template="page.html",
+            language="en",
+        )
+        create_page(
+            title="child 1",
+            template="page.html",
+            language="en",
+            parent=self.root_page,
+        )
+        create_page(
+            title="child 2",
+            template="page.html",
+            language="en",
+            parent=self.root_page,
+        )
+        self.subling = create_page(
+            title="sibling",
+            template="page.html",
+            language="en",
+        )
+        from django.contrib.admin import site
+
+        LinkAdmin = site._registry[Link]
+        self.endpoint = admin_reverse(LinkAdmin.global_link_url_name)
+
+    def tearDown(self):
+        self.root_page.delete()
+        self.subling.delete()
+
+    def test_api_endpoint(self):
+        from djangocms_link import admin
+
+        registered = admin.REGISTERED_ADMIN
+        admin.REGISTERED_ADMIN = []
+        for query_params in ("", "?app_label=1"):
+            with self.subTest(query_params=query_params):
+                with self.login_user_context(self.get_superuser()):
+                    response = self.client.get(self.endpoint + query_params)
+                    self.assertEqual(response.status_code, 200)
+                    data = response.json()
+
+                self.assertIn("results", data)
+                self.assertEqual(len(data["results"]), 1)
+                self.assertIn("pagination", data)
+                self.assertEqual(data["pagination"]["more"], False)
+
+                pages = data["results"][0]
+                self.assertEqual(pages["text"], "Pages")
+                for page in pages["children"]:
+                    self.assertIn("id", page)
+                    self.assertIn("text", page)
+                    self.assertIn("url", page)
+                    _, pk = page["id"].split(":")
+                    db_page = Page.objects.get(pk=pk)
+                    self.assertEqual(page["text"], str(db_page))
+        admin.REGISTERED_ADMIN = registered
+
+    def test_filter(self):
+        with self.login_user_context(self.get_superuser()):
+            response = self.client.get(self.endpoint + "?term=child")
+            self.assertEqual(response.status_code, 200)
+            data = response.json()
+
+        self.assertIn("results", data)
+        self.assertEqual(len(data["results"]), 1)
+        self.assertIn("pagination", data)
+        self.assertEqual(data["pagination"]["more"], False)
+
+        pages = data["results"][0]
+        self.assertEqual(len(pages["children"]), 2)
+
+    def test_filter_with_empty_result(self):
+        with self.login_user_context(self.get_superuser()):
+            response = self.client.get(self.endpoint + "?term=DJANGOCMS")
+            self.assertEqual(response.status_code, 200)
+            data = response.json()
+
+        self.assertIn("results", data)
+        self.assertEqual(len(data["results"]), 0)
+        self.assertIn("pagination", data)
+        self.assertEqual(data["pagination"]["more"], False)
+
+    def test_site_selector(self):
+        with self.login_user_context(self.get_superuser()):
+            response = self.client.get(self.endpoint + "?app_label=2")
+            self.assertEqual(response.status_code, 200)
+            data = response.json()
+
+        self.assertIn("results", data)
+        self.assertEqual(len(data["results"]), 0)
+        self.assertIn("pagination", data)
+        self.assertEqual(data["pagination"]["more"], False)
+
+    def test_get_reference(self):
+        with self.login_user_context(self.get_superuser()):
+            response = self.client.get(self.endpoint + "?g=cms.page:1")
+            self.assertEqual(response.status_code, 200)
+            data = response.json()
+
+        self.assertIn("id", data)
+        self.assertIn("text", data)
+        self.assertIn("url", data)
+        self.assertEqual(data["id"], "cms.page:1")
+        self.assertEqual(data["text"], "root")
+        self.assertEqual(data["url"], self.root_page.get_absolute_url())
+
+    def test_outdated_reference(self):
+        with self.login_user_context(self.get_superuser()):
+            response = self.client.get(self.endpoint + "?g=cms.page:0")
+            self.assertEqual(response.status_code, 200)
+            data = response.json()
+
+        self.assertIn("error", data)
+        self.assertEqual(data["error"], "Page matching query does not exist.")
+
+
+class LinkEndpointThirdPartyTestCase(CMSTestCase):
+    def setUp(self):
+        LinkAdmin = admin.site._registry[Link]
+        self.endpoint = admin_reverse(LinkAdmin.global_link_url_name)
+
+        self.second_site = Site.objects.create(
+            domain="second",
+            name="second",
+        )
+
+        self.items = (
+            ThirdPartyModel.objects.create(name="First", path="/first", site_id=1),
+            ThirdPartyModel.objects.create(
+                name="Second", path="/second", site=self.second_site
+            ),
+            ThirdPartyModel.objects.create(name="django CMS", path="/django-cms"),
+            ThirdPartyModel.objects.create(
+                name="django CMS rocks", path="/django-cms-2"
+            ),
+        )
+
+    def test_auto_config(self):
+        from djangocms_link.admin import REGISTERED_ADMIN
+        from tests.utils.admin import ThirdPartyAdmin
+
+        for registered_admin in REGISTERED_ADMIN:
+            if isinstance(registered_admin, ThirdPartyAdmin):
+                break
+        else:
+            self.asserFail("ThirdPartyAdmin not found in REGISTERED_ADMIN")
+
+    def test_api_endpoint(self):
+        for query_params in ("", "?app_label=1"):
+            with self.subTest(query_params=query_params):
+                with self.login_user_context(self.get_superuser()):
+                    response = self.client.get(self.endpoint + query_params)
+                    self.assertEqual(response.status_code, 200)
+                    data = response.json()
+
+                self.assertIn("results", data)
+                self.assertEqual(len(data["results"]), 1)
+                self.assertIn("pagination", data)
+                self.assertEqual(data["pagination"]["more"], False)
+                destinations = data["results"][0]
+                self.assertEqual(destinations["text"], "Third party models")
+                for destination in destinations["children"]:
+                    self.assertIn("id", destination)
+                    self.assertIn("text", destination)
+                    self.assertIn("url", destination)
+                    _, pk = destination["id"].split(":")
+                    db_obj = ThirdPartyModel.objects.get(pk=pk)
+                    self.assertEqual(destination["text"], str(db_obj))
+
+    def test_filter(self):
+        with self.login_user_context(self.get_superuser()):
+            response = self.client.get(self.endpoint + "?term=CMS")
+            self.assertEqual(response.status_code, 200)
+            data = response.json()
+
+        self.assertIn("results", data)
+        self.assertEqual(len(data["results"]), 1)
+        self.assertIn("pagination", data)
+        self.assertEqual(data["pagination"]["more"], False)
+
+        pages = data["results"][0]
+        self.assertEqual(len(pages["children"]), 2)
+
+    def test_site_selector(self):
+        for site_id in (1, 2):
+            with self.subTest(site_id=site_id):
+                with self.login_user_context(self.get_superuser()):
+                    response = self.client.get(self.endpoint + f"?app_label={site_id}")
+                    self.assertEqual(response.status_code, 200)
+                    data = response.json()
+
+                self.assertIn("results", data)
+                self.assertEqual(len(data["results"]), 1)
+                self.assertIn("pagination", data)
+                self.assertEqual(data["pagination"]["more"], False)
+                destinations = data["results"][0]
+                self.assertEqual(destinations["text"], "Third party models")
+                # One site-specific item, two all-sites items
+                self.assertEqual(len(destinations["children"]), 3)
+
+                # Specific site item
+                if site_id == 1:
+                    self.assertIn(
+                        {
+                            "id": "utils.thirdpartymodel:1",
+                            "text": "First",
+                            "url": "/first",
+                            "verbose_name": ThirdPartyModel._meta.verbose_name.capitalize(),
+                        },
+                        destinations["children"],
+                    )
+                else:
+                    self.assertIn(
+                        {
+                            "id": "utils.thirdpartymodel:2",
+                            "text": "Second",
+                            "url": "/second",
+                            "verbose_name": ThirdPartyModel._meta.verbose_name.capitalize(),
+                        },
+                        destinations["children"],
+                    )
+                # All-sites items
+                self.assertIn(
+                    {
+                        "id": "utils.thirdpartymodel:3",
+                        "text": "django CMS",
+                        "url": "/django-cms",
+                        "verbose_name": ThirdPartyModel._meta.verbose_name.capitalize(),
+                    },
+                    destinations["children"],
+                )
+                self.assertIn(
+                    {
+                        "id": "utils.thirdpartymodel:4",
+                        "text": "django CMS rocks",
+                        "url": "/django-cms-2",
+                        "verbose_name": ThirdPartyModel._meta.verbose_name.capitalize(),
+                    },
+                    destinations["children"],
+                )
+
+    def test_get_reference(self):
+        with self.login_user_context(self.get_superuser()):
+            response = self.client.get(self.endpoint + "?g=utils.thirdpartymodel:1")
+            self.assertEqual(response.status_code, 200)
+            data = response.json()
+
+        self.assertIn("id", data)
+        self.assertIn("text", data)
+        self.assertIn("url", data)
+        self.assertEqual(data["id"], "utils.thirdpartymodel:1")
+        self.assertEqual(data["text"], "First")
+        self.assertEqual(data["url"], self.items[0].get_absolute_url())
+
+
+class LinkEndpointMultiModelTestCase(CMSTestCase):
+    def setUp(self):
+        LinkAdmin = admin.site._registry[Link]
+
+        self.endpoint = admin_reverse(LinkAdmin.global_link_url_name)
+        self.root_page = create_page(
+            title="root",
+            template="page.html",
+            language="en",
+        )
+        self.items = (
+            ThirdPartyModel.objects.create(name="First", path="/first"),
+            ThirdPartyModel.objects.create(name="Second", path="/second"),
+        )
+
+    def test_api_endpoint(self):
+        with self.login_user_context(self.get_superuser()):
+            response = self.client.get(self.endpoint)
+            self.assertEqual(response.status_code, 200)
+            data = response.json()
+
+        self.assertIn("results", data)
+        self.assertIn("pagination", data)
+        self.assertEqual(data["pagination"]["more"], False)
+
+        # Two optgroups:
+        # 1. Pages (always first)
+        # 2. Third party models
+        self.assertEqual(len(data["results"]), 2)
+        self.assertEqual(data["results"][0]["text"], "Pages")
+        self.assertEqual(data["results"][1]["text"], "Third party models")
diff --git a/tests/test_fields.py b/tests/test_fields.py
index ec91981e..15b0f81a 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -1,15 +1,132 @@
-from django.conf import settings
+from django import forms
 from django.test import TestCase
 
-from djangocms_link.fields import PageSearchField, is_select2_enabled
-from djangocms_link.fields_select2 import Select2PageSearchField
+from cms.api import create_page
+
+from djangocms_link.fields import LinkFormField, LinkWidget
+from tests.helpers import get_filer_file
 
 
 class LinkFieldTestCase(TestCase):
+    def setUp(self):
+        self.page = create_page(
+            title="django CMS is fun",
+            template="page.html",
+            language="en",
+        )
+        self.file = get_filer_file()
+
+    def test_form_field_rendering(self):
+        class LinkForm(forms.Form):
+            link_field = LinkFormField(required=True)
+
+        form = LinkForm()
+        form_html = str(form)
+
+        # Render widget
+        self.assertIn(
+            '<div name="link_field" class="link-widget widget" required id="id_link_field">',
+            form_html,
+        )
+        # Render selector
+        self.assertIn(
+            '<select name="link_field_0" class="js-link-widget-selector" data-help="No destination selected. '
+            'Use the dropdown to select a destination." required id="id_link_field_0">'
+            '<option value="internal_link">Internal link</option>'
+            '<option value="external_link">External link/anchor</option>'
+            '<option value="file_link">File link</option></select>',
+            form_html,
+        )
+        # Render internal URL field
+        self.assertIn(
+            '<select name="link_field_2" widget="internal_link" '
+            'data-help="Select from available internal destinations. Optionally, add an anchor to scroll to." '
+            'data-placeholder="" required id="id_link_field_2" class="admin-autocomplete" data-ajax--cache="true" '
+            'data-ajax--delay="250" data-ajax--type="GET" data-ajax--url="/en/admin/djangocms_link/link/urls" '
+            'data-theme="admin-autocomplete" data-allow-clear="true" '
+            'data-minimum-input-length="0" lang="en">'
+            '<option value=""></option><option value="" selected>None</option>'
+            "</select>",
+            form_html,
+        )
+        # Render external URL field
+        self.assertIn(
+            '<input type="url" name="link_field_1" widget="external_link" '
+            'placeholder="https://example.com or #anchor" '
+            'data-help="Provide a link to an external URL, including the schema such as &#x27;https://&#x27;, '
+            '&#x27;tel:&#x27;, or &#x27;mailto:&#x27;. Optionally, add an #anchor (including the #) to scroll to." '
+            'required id="id_link_field_1">',
+            form_html,
+        )
+
+        class LinkNotRequiredForm(forms.Form):
+            link_field = LinkFormField(required=False)
+
+        # Render selector with empty option
+        self.assertIn(
+            '<select name="link_field_0" class="js-link-widget-selector" data-help="No destination selected. '
+            'Use the dropdown to select a destination." id="id_link_field_0">'
+            '<option value="empty">---------</option>'
+            '<option value="internal_link">Internal link</option>'
+            '<option value="external_link">External link/anchor</option>'
+            '<option value="file_link">File link</option></select>',
+            str(LinkNotRequiredForm()),
+        )
+
+    def prepare_value(self, form, value):
+        return form.fields["link_field"].prepare_value(value)
+
+    def test_form_field_transparency(self):
+        class LinkForm(forms.Form):
+            link_field = LinkFormField(required=False)
+
+        def check_value(value):
+            # Creates submission data for value and checks if the form returns the submitted value
+            data = {
+                f"link_field_{i}": item
+                for i, item in enumerate(self.prepare_value(LinkForm(), value))
+            }
+            form = LinkForm(data=data)
+            self.assertTrue(form.is_valid(), form.errors)
+            self.assertEqual(form.cleaned_data["link_field"], value)
+
+        check_value({"internal_link": f"cms.page:{self.page.id}", "anchor": "#anchor"})
+        check_value({"external_link": "https://example.com"})
+        check_value({"external_link": "#anchor"})
+        check_value({"file_link": str(self.file.id)})
+        check_value({})
+
+    def test_widget_renders_selection(self):
+        widget = LinkWidget()
+        pre_select_page = len(widget.widgets) * [None]
+        pre_select_page[0] = "internal_link"
+        pre_select_page[2] = f"cms.page:{self.page.id}"
+        rendered_widget = widget.render(
+            "link_field", pre_select_page, attrs={"id": "id_link_field"}
+        )
+
+        self.assertIn(
+            '<option value="cms.page:1" selected>django CMS is fun</option>',
+            rendered_widget,
+        )
+
+    def test_widget_renders_site_selector(self):
+        widget = LinkWidget(site_selector=True)
+        pre_select_page = len(widget.widgets) * [None]
+        pre_select_page[0] = "internal_link"
+        pre_select_page[2] = f"cms.page:{self.page.id}"
+        rendered_widget = widget.render(
+            "link_field", pre_select_page, attrs={"id": "id_link_field"}
+        )
 
-    def test_field_with_django_select2_extension(self):
-        self.assertTrue('django_select2' in settings.INSTALLED_APPS)
-        self.assertTrue(is_select2_enabled())
-        settings.INSTALLED_APPS.remove("django_select2")
-        self.assertFalse(is_select2_enabled())
-        self.assertEqual(PageSearchField, Select2PageSearchField)
+        # Subwidget is present
+        self.assertIn(
+            '<select name="link_field_2" class="js-link-site-widget admin-autocomplete" widget="site"',
+            rendered_widget,
+        )
+        # Current site is pre-selected
+        self.assertIn(
+            '<option value="1" selected>example.com</option>', rendered_widget
+        )
+        # Site selector uses django admin autocomplete
+        self.assertIn('data-ajax--url="/en/admin/autocomplete/"', rendered_widget)
diff --git a/tests/test_link_dict.py b/tests/test_link_dict.py
new file mode 100644
index 00000000..07a79dbf
--- /dev/null
+++ b/tests/test_link_dict.py
@@ -0,0 +1,99 @@
+from django.test import TestCase
+from django.utils.crypto import get_random_string
+
+from filer.models import File
+
+from djangocms_link.helpers import LinkDict
+from djangocms_link.models import Link
+from tests.utils.models import ThirdPartyModel
+
+
+class LinkDictTestCase(TestCase):
+    def test_link_dict_is_a_dict(self):
+        some_dict = {get_random_string(5): get_random_string(5) for _ in range(5)}
+
+        self.assertEqual(LinkDict(some_dict), some_dict)
+        self.assertEqual(LinkDict(some_dict).url, "")
+        self.assertEqual(LinkDict(), dict())
+        self.assertEqual(LinkDict().url, "")
+        self.assertEqual(LinkDict().type, "")
+        self.assertEqual(LinkDict(1), dict())
+
+    def test_external_link(self):
+        link1 = LinkDict({"external_link": "https://www.example.com"})
+        link2 = LinkDict("https://www.django-cms.org")
+
+        self.assertEqual(link1.url, "https://www.example.com")
+        self.assertEqual(link2.url, "https://www.django-cms.org")
+        self.assertEqual(str(link1), "https://www.example.com")
+        self.assertEqual(str(link2), "https://www.django-cms.org")
+        self.assertEqual(link1.type, "external_link")
+        self.assertEqual(link2.type, "external_link")
+
+    def test_file_link(self):
+        file = File.objects.create(file=get_random_string(5))
+        link1 = LinkDict({"file_link": file.pk})
+        link2 = LinkDict(file)
+
+        self.assertEqual(link1, link2)
+        self.assertEqual(link1.url, file.url)
+        self.assertEqual(link2.url, file.url)
+        self.assertEqual(str(link1), file.url)
+        self.assertEqual(str(link2), file.url)
+        self.assertEqual(link1.type, "file_link")
+        self.assertEqual(link2.type, "file_link")
+
+    def test_internal_link(self):
+        obj = ThirdPartyModel.objects.create(
+            name=get_random_string(5), path=get_random_string(5)
+        )
+        link1 = LinkDict(
+            {"internal_link": f"{obj._meta.app_label}.{obj._meta.model_name}:{obj.pk}"}
+        )
+        link2 = LinkDict(obj)
+        link3 = LinkDict(obj, anchor="#test")
+
+        self.assertEqual(link1.url, obj.get_absolute_url())
+        self.assertEqual(link2.url, obj.get_absolute_url())
+        self.assertEqual(link3.url, f"{obj.get_absolute_url()}#test")
+        self.assertEqual(str(link1), obj.get_absolute_url())
+        self.assertEqual(str(link2), obj.get_absolute_url())
+        self.assertEqual(str(link3), f"{obj.get_absolute_url()}#test")
+        self.assertEqual(link1.type, "internal_link")
+        self.assertEqual(link2.type, "internal_link")
+        self.assertEqual(link3.type, "internal_link")
+
+    def test_link_types(self):
+        anchor = LinkDict("#test")
+        external = LinkDict("https://www.example.com")
+        phone = LinkDict("tel:+1234567890")
+        mail = LinkDict("mailto:info@django-cms.org")
+
+        self.assertEqual(anchor.type, "anchor")
+        self.assertEqual(external.type, "external_link")
+        self.assertEqual(phone.type, "tel")
+        self.assertEqual(mail.type, "mailto")
+
+    def test_db_queries(self):
+        obj = ThirdPartyModel.objects.create(
+            name=get_random_string(5), path=get_random_string(5)
+        )
+        link = LinkDict(obj)
+        with self.assertNumQueries(0):
+            self.assertEqual(link.url, obj.get_absolute_url())
+            self.assertEqual(str(link), obj.get_absolute_url())
+
+    def test_cache_no_written_to_db(self):
+        obj = ThirdPartyModel.objects.create(
+            name=get_random_string(5), path=get_random_string(5)
+        )
+        link = Link.objects.create(
+            link=LinkDict(obj)
+        )
+        self.assertEqual(link.link.url, link.link["__cache__"])  # populates cache
+        link.save()
+
+        link = Link.objects.get(pk=link.pk)  # load from db
+
+        # Cache not saved to db
+        self.assertNotIn("__cache__", link.link)
diff --git a/tests/test_migrations.py b/tests/test_migrations.py
index 50d7bc96..5749ca7c 100644
--- a/tests/test_migrations.py
+++ b/tests/test_migrations.py
@@ -1,30 +1,137 @@
 # original from
 # http://tech.octopus.energy/news/2016/01/21/testing-for-missing-migrations-in-django.html
 from io import StringIO
+from unittest import skipIf
 
 from django.core.management import call_command
 from django.test import TestCase, override_settings
 
+from cms import __version__ as cms_version
+
+from django_test_migrations.contrib.unittest_case import MigratorTestCase
+
+from djangocms_link import __version__
+from djangocms_link.helpers import get_link
 
-class MigrationTestCase(TestCase):
 
+class MigrationTestCase(TestCase):
     @override_settings(MIGRATION_MODULES={})
     def test_for_missing_migrations(self):
         output = StringIO()
         options = {
-            'interactive': False,
-            'dry_run': True,
-            'stdout': output,
-            'check_changes': True,
+            "interactive": False,
+            "dry_run": True,
+            "stdout": output,
+            "check_changes": True,
         }
 
         try:
-            call_command('makemigrations', **options)
+            call_command("makemigrations", **options)
         except SystemExit as e:
             status_code = str(e)
         else:
             # the "no changes" exit code is 0
-            status_code = '0'
+            status_code = "0"
+
+        if status_code == "1" and "djangocms_link" in output:
+            self.fail(f"There are missing migrations:\n {output.getvalue()}")
+
+
+@skipIf(
+    __version__[0] > "5" or cms_version < "4",
+    "Migration has already been tested before releasing version 5",
+)
+class MigrationToVersion5(MigratorTestCase):
+    migrate_from = ("djangocms_link", "0016_alter_link_cmsplugin_ptr")
+    migrate_to = (
+        "djangocms_link",
+        "0018_remove_link_anchor_remove_link_external_link_and_more",
+    )
+
+    def prepare(self):
+        # Can't use the cms.api here, since these are "historic" versions of the models
+        Link = self.old_state.apps.get_model("djangocms_link", "Link")
+        Page = self.old_state.apps.get_model("cms", "Page")
+        PageContent = self.old_state.apps.get_model("cms", "PageContent")
+        PageUrl = self.old_state.apps.get_model("cms", "PageUrl")
+        TreeNode = self.old_state.apps.get_model("cms", "TreeNode")
+        Site = self.old_state.apps.get_model("sites", "Site")
+
+        # First create a Site at this stage in migration
+        site = Site.objects.create(
+            domain="example.com",
+            name="example.com",
+        )
+        # ... then a node
+        node = TreeNode.objects.create(
+            path="0001",
+            depth=1,
+            numchild=0,
+            parent=None,
+            site=site,
+        )
+        # ... a page
+        self.page = Page.objects.create(
+            node=node,
+        )
+        # ... and finally a page content object
+        PageContent.objects.create(
+            title="My Page",
+            page=self.page,
+            language="en",
+        )
+        PageUrl.objects.create(
+            page=self.page,
+            language="en",
+            path="my-page",
+        )
+        self.links = [
+            Link.objects.create(
+                template="default",
+                name="My Link",
+                internal_link=self.page,
+                anchor="some_id",
+            ),
+            Link.objects.create(
+                template="default",
+                name="My Link",
+                external_link="https://www.django-cms.com",
+            ),
+            Link.objects.create(
+                template="default",
+                name="My Link",
+                external_link="https://www.django-cms.com/",
+                anchor="some_id",
+            ),
+            Link.objects.create(
+                template="default",
+                name="My Link",
+                mailto="test@email.com",
+            ),
+            Link.objects.create(
+                template="default",
+                name="My Link",
+                phone="+01 234 567 89",
+            ),
+            Link.objects.create(
+                template="default",
+                name="My Link",
+                anchor="anchor",
+            ),
+        ]
+        self.urls = [
+            "/en/my-page/#some_id",
+            "https://www.django-cms.com",
+            "https://www.django-cms.com/#some_id",
+            "mailto:test@email.com",
+            "tel:+0123456789",
+            "#anchor",
+        ]
+
+    def test_plugins_migrated(self):
+        Link = self.new_state.apps.get_model("djangocms_link", "Link")
+        links = Link.objects.all()
 
-        if status_code == '1' and "djangocms_link" in output:
-            self.fail(f'There are missing migrations:\n {output.getvalue()}')
+        for link, url in zip(links, self.urls):
+            with self.subTest(link=link, url=url):
+                self.assertEqual(get_link(link.link, site_id=1), url)
diff --git a/tests/test_models.py b/tests/test_models.py
index 97cf5226..e11d16e1 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -9,23 +9,52 @@
 
 
 class LinkModelTestCase(TestCase):
-
     def setUp(self):
         self.page = create_page(
-            title='help',
-            template='page.html',
-            language='en',
+            title="help",
+            template="page.html",
+            language="en",
         )
         self.file = get_filer_file()
-        self.link = Link.objects.create(
+        self.internal_link = Link.objects.create(
+            template="default",
+            name="My Link",
+            link={"internal_link": f"cms.page:{self.page.pk}", "anchor": "#some_id"},
+            target=TARGET_CHOICES[0][0],
+            attributes="{'data-type', 'link'}",
+        )
+        self.external_link = Link.objects.create(
+            template="default",
+            name="My Link",
+            link={"external_link": "https://www.django-cms.org/#some_id"},
+            target=TARGET_CHOICES[0][0],
+            attributes="{'data-type', 'link'}",
+        )
+        self.phone_link = Link.objects.create(
+            template="default",
+            name="My Link",
+            link={"external_link": "tel:+01 234 567 89"},
+            target=TARGET_CHOICES[0][0],
+            attributes="{'data-type', 'link'}",
+        )
+        self.mail_link = Link.objects.create(
+            template="default",
+            name="My Link",
+            link={"external_link": "mailto:test@email.com"},
+            target=TARGET_CHOICES[0][0],
+            attributes="{'data-type', 'link'}",
+        )
+        self.anchor_link = Link.objects.create(
             template="default",
             name="My Link",
-            internal_link=self.page,
-            external_link="http://www.divio.com",
-            file_link=self.file,
-            anchor="some_id",
-            mailto="test@email.com",
-            phone="+01 234 567 89",
+            link={"external_link": "#some_id"},
+            target=TARGET_CHOICES[0][0],
+            attributes="{'data-type', 'link'}",
+        )
+        self.file_link = Link.objects.create(
+            template="default",
+            name="My Link",
+            link={"file_link": self.file.pk},
             target=TARGET_CHOICES[0][0],
             attributes="{'data-type', 'link'}",
         )
@@ -35,72 +64,85 @@ def tearDown(self):
         self.page.delete()
 
     def test_link_instance(self):
-        instance = self.link
-        instance = Link.objects.all()
-        self.assertEqual(instance.count(), 1)
+        instances = Link.objects.all()
+        self.assertEqual(instances.count(), 6)  # 4 instances created in setUp
+
         instance = Link.objects.first()
         self.assertEqual(instance.template, "default")
         self.assertEqual(instance.name, "My Link")
-        self.assertEqual(instance.external_link, "http://www.divio.com")
-        self.assertEqual(instance.anchor, "some_id")
-        self.assertEqual(instance.mailto, "test@email.com")
-        self.assertEqual(instance.phone, "+01 234 567 89")
         self.assertEqual(instance.target, "_blank")
         self.assertEqual(instance.attributes, "{'data-type', 'link'}")
+
         # test strings
         self.assertEqual(str(instance), "My Link")
-        # we test these later in get_link
-        instance.internal_link = None
-        instance.file_link = None
+
+    def test_get_short_description(self):
+        """"""
+        instance = self.external_link
         self.assertEqual(
             instance.get_short_description(),
-            "My Link (http://www.divio.com)",
+            "My Link (https://www.django-cms.org/#some_id)",
         )
         instance.name = None
-        self.assertEqual(str(instance), "1")
-        self.assertEqual(instance.get_short_description(), "http://www.divio.com")
-        instance.external_link = None
-        instance.internal_link = None
-        instance.file_link = None
-        instance.phone = None
-        instance.mailto = None
-        instance.anchor = None
+        self.assertEqual(str(instance), str(instance.pk))
+        self.assertEqual(
+            instance.get_short_description(), "https://www.django-cms.org/#some_id"
+        )
+
+        instance.link = {}
         self.assertEqual(instance.get_short_description(), "<link is missing>")
 
     def test_get_link(self):
-        instance = self.link
-        with self.assertRaises(ValidationError):
-            # should throw an error as too many values are provided
-            instance.clean()
-        self.assertEqual(instance.get_link(), "//example.com" + self.page.get_absolute_url())
-        instance.internal_link = None
-        self.assertEqual(instance.get_link(), self.file.url)
-        instance.file_link = None
-        self.assertEqual(instance.get_link(), "http://www.divio.com")
-        instance.external_link = None
-        self.assertEqual(instance.get_link(), "tel:+0123456789")
-        instance.phone = None
-        self.assertEqual(instance.get_link(), "mailto:test@email.com")
-        instance.mailto = None
-        self.assertEqual(instance.get_link(), "#some_id")
+        self.assertEqual(
+            self.internal_link.get_link(), self.page.get_absolute_url() + "#some_id"
+        )
+        self.assertEqual(self.file_link.get_link(), self.file.url)
+        self.assertEqual(
+            self.external_link.get_link(), "https://www.django-cms.org/#some_id"
+        )
+        self.assertEqual(self.phone_link.get_link(), "tel:+0123456789")
+        self.assertEqual(self.mail_link.get_link(), "mailto:test@email.com")
+        self.assertEqual(self.anchor_link.get_link(), "#some_id")
+
+    def test_get_url_template_tag(self):
+        from djangocms_link.templatetags.djangocms_link_tags import to_url
+
+        self.assertEqual(
+            to_url(self.internal_link.link), self.page.get_absolute_url() + "#some_id"
+        )
+        self.assertEqual(to_url(self.file_link.link), self.file.url)
+        self.assertEqual(
+            to_url(self.external_link.link), "https://www.django-cms.org/#some_id"
+        )
+        self.assertEqual(to_url(self.phone_link.link), "tel:+0123456789")
+        self.assertEqual(to_url(self.mail_link.link), "mailto:test@email.com")
+        self.assertEqual(to_url(self.anchor_link.link), "#some_id")
+        self.assertEqual(to_url(None), "")
+        self.assertEqual(to_url({}), "")
+
+    def test_to_link_template_tag(self):
+        from djangocms_link.templatetags.djangocms_link_tags import to_link
+
+        self.assertEqual(to_link(self.file), {"file_link": self.file.pk})
+        self.assertEqual(
+            to_link(self.page), {
+                "internal_link": f"cms.page:{self.page.pk}",
+                "__cache__": self.page.get_absolute_url(),
+            }
+        )
+        self.assertEqual(
+            to_link("https://www.django-cms.org/#some_id"),
+            {"external_link": "https://www.django-cms.org/#some_id"},
+        )
+
+    def test_respect_link_is_optional(self):
         # by now the configuration is good again
+        instance = self.internal_link
         instance.clean()
-        instance.anchor = None
+        instance.link = {}
         with self.assertRaises(ValidationError):
             # this should error again as no link is defined
             instance.clean()
         # now we allow the link to be empty
         instance.link_is_optional = True
         instance.clean()
-
-    def test_not_allowed_attributes(self):
-        instance = self.link
-        instance.internal_link = None
-        instance.external_link = None
-        instance.phone = None
-        instance.file_link = None
-        with self.assertRaises(ValidationError):
-            # anchor is not compatible with all fields (e.g. phone, mailto)
-            instance.clean()
-        instance.mailto = None
-        instance.clean()
diff --git a/tests/test_plugins.py b/tests/test_plugins.py
index b2c5302c..8a07136d 100644
--- a/tests/test_plugins.py
+++ b/tests/test_plugins.py
@@ -14,7 +14,6 @@
 
 
 class LinkPluginsTestCase(TestFixture, CMSTestCase):
-
     def setUp(self):
         self.file = get_filer_file()
         self.language = "en"
@@ -31,11 +30,13 @@ def setUp(self):
         )
         self.publish(self.page, self.language)
         self.static_page = create_page(
-            title='static-content',
-            template='static_placeholder.html',
-            language='en',
+            title="static-content",
+            template="static_placeholder.html",
+            language="en",
+        )
+        self.placeholder = self.get_placeholders(self.page, self.language).get(
+            slot="content"
         )
-        self.placeholder = self.get_placeholders(self.page, self.language).get(slot="content")
         self.superuser = self.get_superuser()
 
     def tearDown(self):
@@ -50,7 +51,7 @@ def test_link_plugin(self):
             placeholder=self.placeholder,
             plugin_type=LinkPlugin.__name__,
             language=self.language,
-            internal_link=self.page,
+            link={"internal_link": f"cms.page:{self.page.pk}"},
         )
         plugin.full_clean()
         self.assertEqual(plugin.plugin_type, "LinkPlugin")
@@ -62,7 +63,7 @@ def test_plugin_structure(self):
             placeholder=self.placeholder,
             plugin_type=LinkPlugin.__name__,
             language=self.language,
-            internal_link=self.page,
+            link={"internal_link": f"cms.page:{self.page.pk}"},
             name="Page link",
         )
         self.publish(self.page, self.language)
@@ -79,10 +80,15 @@ def test_full_plugin_render(self):
             plugin_type=LinkPlugin.__name__,
             language=self.language,
         )
+        from djangocms_link.fields import LinkWidget
+
+        pos = LinkWidget().data_pos["external_link"]
+
         data = {
             "template": "default",
-            "external_link": "https://www.google.com",
-            "name": "External link"
+            "link_0": "external_link",
+            f"link_{pos}": "https://www.google.com",
+            "name": "External link",
         }
 
         with self.login_user_context(self.superuser), warnings.catch_warnings():
@@ -98,9 +104,9 @@ def test_optional_link(self):
         AbstractLink.link_is_optional = True
 
         plugin = add_plugin(
-            self.get_placeholders(self.page, self.language).get(slot='content'),
-            'LinkPlugin',
-            'en',
+            self.get_placeholders(self.page, self.language).get(slot="content"),
+            "LinkPlugin",
+            "en",
         )
         self.assertIsNone(plugin.full_clean())
 
@@ -109,9 +115,9 @@ def test_optional_link(self):
         self.assertEqual(AbstractLink.link_is_optional, False)
 
         plugin = add_plugin(
-            self.get_placeholders(self.page, self.language).get(slot='content'),
-            'LinkPlugin',
-            'en',
+            self.get_placeholders(self.page, self.language).get(slot="content"),
+            "LinkPlugin",
+            "en",
         )
 
         # should throw "Please provide a link." error
@@ -119,56 +125,85 @@ def test_optional_link(self):
             plugin.clean()
 
     def test_in_placeholders(self):
+        from djangocms_link.helpers import get_link
+
         plugin = add_plugin(
-            self.get_placeholders(self.page, self.language).get(slot='content'),
-            'LinkPlugin',
-            'en',
-            internal_link=self.page,
+            self.get_placeholders(self.page, self.language).get(slot="content"),
+            "LinkPlugin",
+            "en",
+            link={"internal_link": f"cms.page:{self.page.pk}"},
         )
-        self.assertEqual(plugin.get_link(), '/en/content/')
+        site = getattr(self.page, "site", self.page.node.site)
+        self.assertEqual(get_link(plugin.link, site.id), "/en/content/")
 
         placeholder = Placeholder(slot="generated_placeholder")
         placeholder.save()
 
         plugin = add_plugin(
             placeholder,
-            'LinkPlugin',
-            'en',
-            internal_link=self.static_page,
+            "LinkPlugin",
+            "en",
+            link={"internal_link": f"cms.page:{self.static_page.pk}"},
         )
         # the generated placeholder has no page attached to it, thus:
-        self.assertEqual(plugin.get_link(), '//example.com/en/static-content/')
+        self.assertEqual(plugin.get_link(), "/en/static-content/")
 
         static_placeholder = StaticPlaceholder.objects.create(
-            name='content_static',
-            code='content_static',
+            name="content_static",
+            code="content_static",
             site_id=1,
         )
         static_placeholder.save()
 
         plugin_a = add_plugin(
             static_placeholder.draft,
-            'LinkPlugin',
-            'en',
-            internal_link=self.page,
+            "LinkPlugin",
+            "en",
+            link={"internal_link": f"cms.page:{self.page.pk}"},
         )
 
         plugin_b = add_plugin(
             static_placeholder.public,
-            'LinkPlugin',
-            'en',
-            internal_link=self.static_page,
+            "LinkPlugin",
+            "en",
+            link={"internal_link": f"cms.page:{self.static_page.pk}"},
         )
-        # static placeholders will always return the full path
-        self.assertEqual(plugin_a.get_link(), '//example.com/en/content/')
-        self.assertEqual(plugin_b.get_link(), '//example.com/en/static-content/')
+        # static placeholders will not return the full path
+        self.assertEqual(plugin_a.get_link(0), "//example.com/en/content/")
+        self.assertEqual(plugin_b.get_link(), "/en/static-content/")
 
     def test_file(self):
         plugin = add_plugin(
             self.get_placeholders(self.page, self.language).get(slot="content"),
             "LinkPlugin",
             "en",
-            file_link=self.file,
+            link={"file_link": str(self.file.pk)},
         )
         self.assertIn("test_file.pdf", plugin.get_link())
         self.assertIn("/media/filer_public/", plugin.get_link())
+
+    def test_rendering(self):
+        add_plugin(
+            self.get_placeholders(self.page, self.language).get(slot="content"),
+            "LinkPlugin",
+            "en",
+            name="Link",
+            link={"internal_link": f"cms.page:{self.page.pk}"},
+        )
+        self.publish(self.page, self.language)
+
+        response = self.client.get(self.page.get_absolute_url(self.language))
+        self.assertContains(response, '<a href="/en/content/">Link</a>')
+
+    def test_rendering_fallback(self):
+        add_plugin(
+            self.get_placeholders(self.page, self.language).get(slot="content"),
+            "LinkPlugin",
+            "en",
+            name="Link",
+            link={"internal_link": "cms.page:0"},
+        )
+        self.publish(self.page, self.language)
+
+        response = self.client.get(self.page.get_absolute_url(self.language))
+        self.assertContains(response, "<span>Link</span>")
diff --git a/tests/test_validators.py b/tests/test_validators.py
index 1d278c5b..4c1dbe36 100644
--- a/tests/test_validators.py
+++ b/tests/test_validators.py
@@ -1,21 +1,72 @@
 from django.test import TestCase
 
 from djangocms_link.models import HOSTNAME
-from djangocms_link.validators import IntranetURLValidator
+from djangocms_link.validators import ExtendedURLValidator
 
 
 class LinkValidatorTestCase(TestCase):
+    def assertValidates(self, validator, value):
+        try:
+            validator(value)
+        except Exception as e:
+            self.fail(f"Validation of {value} failed with {e}")
+
+    def assertDoesNotValidate(self, validator, value):
+        try:
+            validator(value)
+            self.fail(f"Validation of {value} unexpectedly did not fail")
+        except Exception:
+            pass
 
     def test_intranet_host_re(self):
-        host = r'[a-z,0-9,-]{1,15}'
+        host = r"[a-z,0-9,-]{1,15}"
         host_re = (
-            '(' + IntranetURLValidator.hostname_re
-            + IntranetURLValidator.domain_re
-            + IntranetURLValidator.tld_re +
-            '|' + host + '|localhost)'
+            "("
+            + ExtendedURLValidator.hostname_re
+            + ExtendedURLValidator.domain_re
+            + ExtendedURLValidator.tld_re
+            + "|"
+            + host
+            + "|localhost)"
         )
-        validator = IntranetURLValidator(
+        validator = ExtendedURLValidator(
             intranet_host_re=host,
         )
         self.assertEqual(validator.host_re, host_re)
         self.assertIsNone(HOSTNAME)
+
+    def test_tel_validation(self):
+        validator = ExtendedURLValidator()
+
+        self.assertValidates(validator, "tel:0123456789")
+        self.assertValidates(validator, "tel:01 234 567 89")
+        self.assertValidates(validator, "tel:+01 234 567 89")
+        self.assertDoesNotValidate(validator, "tel:")
+        self.assertDoesNotValidate(validator, "tel:0800-django-cms")
+        self.assertDoesNotValidate(validator, "tel:info@django-cms.org")
+
+    def test_mailto_validation(self):
+        validator = ExtendedURLValidator()
+
+        self.assertValidates(validator, "mailto:info@django-cms.org")
+        self.assertValidates(validator, "mailto:test@long.subdomain.path.email.com")
+        self.assertDoesNotValidate(validator, "mailto:info@localhost")
+        self.assertDoesNotValidate(validator, "mailto:")
+        self.assertDoesNotValidate(validator, "mailto: info@django-cms.org")
+
+    def test_wrong_type_fails(self):
+        validator = ExtendedURLValidator()
+
+        self.assertDoesNotValidate(validator, "\n")
+        self.assertDoesNotValidate(validator, 42)
+
+    def test_anchor(self):
+        validator = ExtendedURLValidator()
+        self.assertValidates(validator, "#anchor")
+        self.assertValidates(validator, "#anchor-1")
+        self.assertValidates(validator, "#anchor_1")
+        self.assertDoesNotValidate(validator, "#anchor!")
+        self.assertDoesNotValidate(validator, "#anchor with spaces")
+        self.assertValidates(validator, "#" + "a" * (100 - 1))
+        self.assertDoesNotValidate(validator, "#" + "a" * 101)
+        self.assertValidates(validator, "#")
diff --git a/tests/utils/admin.py b/tests/utils/admin.py
new file mode 100644
index 00000000..c47f2252
--- /dev/null
+++ b/tests/utils/admin.py
@@ -0,0 +1,8 @@
+from django.contrib import admin
+
+from tests.utils.models import ThirdPartyModel
+
+
+@admin.register(ThirdPartyModel)
+class ThirdPartyAdmin(admin.ModelAdmin):
+    search_fields = ("name",)
diff --git a/tests/utils/cms_config.py b/tests/utils/cms_config.py
new file mode 100644
index 00000000..7a100aa8
--- /dev/null
+++ b/tests/utils/cms_config.py
@@ -0,0 +1,6 @@
+from cms.app_base import CMSAppConfig
+
+
+class UtilCMSAppConfig(CMSAppConfig):
+    djangocms_link_enabled = True
+    djangocms_link_models = ["utils.thirdpartymodel"]
diff --git a/tests/utils/models.py b/tests/utils/models.py
new file mode 100644
index 00000000..dd64143e
--- /dev/null
+++ b/tests/utils/models.py
@@ -0,0 +1,13 @@
+from django.db import models
+
+
+class ThirdPartyModel(models.Model):
+    name = models.CharField(max_length=255)
+    path = models.CharField(max_length=255)
+    site = models.ForeignKey("sites.Site", on_delete=models.SET_NULL, null=True)
+
+    def get_absolute_url(self):
+        return self.path
+
+    def __str__(self):
+        return self.name
diff --git a/tests/utils/templates/base.html b/tests/utils/templates/base.html
index db9d806d..da3c605e 100755
--- a/tests/utils/templates/base.html
+++ b/tests/utils/templates/base.html
@@ -22,3 +22,12 @@
         {% show_menu 0 100 100 100 %}
     </ul>
     {% block content %}
+    {% endblock content %}
+</div>
+{% render_block "js" %}
+{% with_data "js-script" as jsset %}
+        {% for js in jsset %}<script type="text/javascript" src="{% static js %}"></script>{% endfor %}
+{% end_with_data %}
+{% render_block "js_end" %}
+</body>
+</html>
diff --git a/tests/utils/templates/fullwidth.html b/tests/utils/templates/fullwidth.html
new file mode 100644
index 00000000..e96a8f2f
--- /dev/null
+++ b/tests/utils/templates/fullwidth.html
@@ -0,0 +1,8 @@
+{% extends "base.html" %}
+{% load cms_tags %}
+
+{% block title %}{% page_attribute 'title' %}{% endblock title %}
+
+{% block content %}
+    {% placeholder "content" %}
+{% endblock content %}
diff --git a/tests/utils/templates/page.html b/tests/utils/templates/page.html
new file mode 100644
index 00000000..e96a8f2f
--- /dev/null
+++ b/tests/utils/templates/page.html
@@ -0,0 +1,8 @@
+{% extends "base.html" %}
+{% load cms_tags %}
+
+{% block title %}{% page_attribute 'title' %}{% endblock title %}
+
+{% block content %}
+    {% placeholder "content" %}
+{% endblock content %}
diff --git a/tests/utils/urls.py b/tests/utils/urls.py
new file mode 100644
index 00000000..3ee11096
--- /dev/null
+++ b/tests/utils/urls.py
@@ -0,0 +1,23 @@
+from django.conf import settings
+from django.conf.urls.i18n import i18n_patterns
+from django.contrib import admin
+from django.contrib.staticfiles.urls import staticfiles_urlpatterns
+from django.urls import include, path, re_path
+from django.views.i18n import JavaScriptCatalog
+from django.views.static import serve
+
+
+admin.autodiscover()
+
+urlpatterns = [
+    re_path(r"^media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT, "show_indexes": True}),  # NOQA
+    re_path(r"^jsi18n/(?P<packages>\S+?)/$", JavaScriptCatalog.as_view()),  # NOQA
+]
+i18n_urls = [
+    re_path(r"^admin/", admin.site.urls),
+]
+
+i18n_urls.append(path("", include("cms.urls")))  # NOQA
+
+urlpatterns += i18n_patterns(*i18n_urls)
+urlpatterns += staticfiles_urlpatterns()