{"id":21001455,"url":"https://github.com/divio/aldryn-translation-tools","last_synced_at":"2025-08-24T09:20:52.223Z","repository":{"id":30609898,"uuid":"34165184","full_name":"divio/aldryn-translation-tools","owner":"divio","description":"Collection of translation helpers and mixins","archived":false,"fork":false,"pushed_at":"2020-08-19T13:55:41.000Z","size":61,"stargazers_count":5,"open_issues_count":3,"forks_count":22,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-04-24T22:24:12.097Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/divio.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-04-18T12:32:59.000Z","updated_at":"2021-02-26T11:40:04.000Z","dependencies_parsed_at":"2022-09-08T14:51:15.320Z","dependency_job_id":null,"html_url":"https://github.com/divio/aldryn-translation-tools","commit_stats":null,"previous_names":["aldryn/aldryn-translation-tools"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/divio%2Faldryn-translation-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/divio%2Faldryn-translation-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/divio%2Faldryn-translation-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/divio%2Faldryn-translation-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/divio","download_url":"https://codeload.github.com/divio/aldryn-translation-tools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254248440,"owners_count":22039008,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T08:15:21.628Z","updated_at":"2025-05-14T23:32:33.684Z","avatar_url":"https://github.com/divio.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"**Deprecated**\n\nThis project is no longer supported.\n\nDivio will undertake no further development or maintenance of this project. If you are interested in continuing to develop it, use the fork functionality from GitHub. We are not able to transfer ownership of the repository to another party.\n\nAldryn Translation Tools\n========================\n\n|PyPI Version| |Build Status| |Coverage Status|\n\nA collection of shared helpers and mixins for translated django-CMS projects.\n\nTo use, install it into your project using pip::\n\n    pip install aldryn-translation-tools\n\n\nContributing\n------------\n\nWe're grateful to all contributors who have helped create and maintain this package.\n\nContributors are listed at `contributions page\n\u003chttps://github.com/aldryn/aldryn-translation-tools/graphs/contributors\u003e`_.\n\n\nadmin.AllTranslationsMixin\n--------------------------\n\nAutomatically adds a list of language \"tags\" in the changelist. Tag color\nindicates the state of translation for that object. Grey meaning untranslated,\nblue meaning translated. Darker versions of each are used to indicate the\ncurrent language.\n\nEach tag is linked to the specific language tag on the change form of the\nobject.\n\nA similar capability is in HVAD, and now there is this for Parler-based\nprojects.\n\nPreview:\n\n.. image:: https://cloud.githubusercontent.com/assets/615759/7727430/5889f0e0-ff11-11e4-930a-2bfc80bef426.jpg\n\nTo use this, merely import and add the mixin to your Model Admin class: ::\n\n    from parler.admin import TranslatableAdmin\n    from aldryn_translation_tools.admin import AllTranslationsMixin\n\n    class GroupAdmin(AllTranslationsMixin, TranslatableAdmin):\n       # ....\n\nIf you wish to put the tags into a different column, you can add\n`all_translations` to the list_display list wherever you'd like, otherwise the\n\"Languages\" column will automatically be placed on the far right.\n\n\nadmin.LinkedRelatedInlineMixin\n------------------------------\n\nThis admin inline mixin links the first field to the row object's own admin\nchange form.\n\nIf the first field is editable, results are undefined but probably won't work\nas expected. For best results, consider making all fields readonly (since they\ncan be edited with ease by following the link), and disabling the ability to\nadd new objects by overriding has_add_permission() on the inline to always\nreturn ``False``.\n\n\nmodels.TranslatedAutoSlugMixin\n------------------------------\n\nThis is a TranslatableModel mixin that automatically generates a suitable\nslug for the object on ``save()``.\n\nIf ``slug_globally_unique`` is ``True``, then slugs will be required to be\nunique across all languages.\n\nIf ``slug_globally_unique`` is ``False`` (default), then the strategy used here\nis that it is OK for two objects to use the same slug if the slugs are for\ndifferent languages. So if this were used on a translated Article model, these\nURLs would be valid:\n\n``/en/pain`` - An article in EN about physical discomfort\n\n``/fr/pain`` - An article in FR about bread\n\nOf course, this means that when resolving an object from its URL, care must\nbe taken to factor in the language segment of the URL too.\n\nWhen using this mixin, it is important to also set the\n``slug_source_field_name`` property on the implementing model to the name of\nthe translated field which the slug is to be derived from. If you require more\nslugs to be derived from multiple fields (translated or otherwise), simply\noverride the method ``get_slug_source`` to provide the source string for the\nslug.\n\nConfiguration properties\n************************\n\nslug_default\n~~~~~~~~~~~~\nProvide a lazy translated string to use for the default slug should an object\nnot have a source string to derive a slug from.\n\nslug_field_name\n~~~~~~~~~~~~~~~\nProvide the name of the translated field in which generated slug shall\nbe stored.\n\nslug_globally_unique\n~~~~~~~~~~~~~~~~~~~~\nA boolean flag controlling whether slugs are globally unique, or only unique\nwith each language. Default value is False.\n\nslug_max_length\n~~~~~~~~~~~~~~~\nDeclares the max_length of slugs. This defaults to the ``max_length`` of the\nslug_field and is determined via introspection.\n\nslug_separator\n~~~~~~~~~~~~~~\nThis determines the separator used before any index added to the slug. It does\n**not** determine the separator used in the slug itself, which is always ``-``.\nThis is only provided for compatibility with the slugify()`` method in\naldryn_common, but it is not recommended to be used. Defaults to ``-``.\n\nslug_source_field_name\n~~~~~~~~~~~~~~~~~~~~~~\nProvide the name of the translated field to be used for deriving the slug.\nIf more than one field, or other complex sources are required, override the\nmethod ``get_slug_source()`` instead. Note that if ``get_slug_source()`` is\noverriden, it is recommended to also override ``get_slug_default()``.\n\n\nPublic methods\n**************\n\nget_slug_default\n~~~~~~~~~~~~~~~~\n\nNaively constructs a translated default slug from the object. For better\nresults, just set the `slug_default` property on the class to a lazy\ntranslated string. Alternatively, override this method if you need to more\nprogrammtically determine the default slug.\n\nExample: If your model is \"news article\" and your source field is \"title\" this\nwill return \"news-article-without-title\".\n\n\nget_slug_max_length\n~~~~~~~~~~~~~~~~~~~\nAccepts an optional parameter ``idx_len``.\n\nIntrospects the slug field to determine the maximum length, taking into account\na possible separator and up to a [idx_len]-digit number.\n\n\nget_slug_source\n~~~~~~~~~~~~~~~\nSimply returns the value of the slug source field. Override for more complex\nsituations such as using multiple fields (translated or not) as the source.\n\n\nmodels.TranslationHelperMixin\n-----------------------------\n\nPublic Methods\n**************\n\n\nknown_translation_getter()\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSignature::\n\n    (value, language) = obj.known_translation_getter(field, default=None, language_code=None, any_language=False)\n\nActs like Parler's safe_translation_getter(), but respects the fallback\npreferences as defined in `settings.CMS_LANGUAGES` and provides both the\ntranslated value and the language it represents as a tuple.\n\nThis is especially helpful when resolving an object's absolute url for a given\nlanguage. If a fallback is used (respecting preference), then the returned\nlanguage_code can then be used to set the correct context for a reverse() to get\na URL consistent to the resulting language.\n\nFor example::\n\n    from django.utils.translation import override\n\n    from aldryn_translation_tools.models import TranslationHelperMixin\n    from cms.utils.i18n import get_current_language\n    from parler.models import TranslatableModel, TranslatedFields\n\n    class Fruit(TranslationHelperMixin, TranslatableModel):\n        translations = TranslatableFields(\n            name=models.CharField(...),\n            slug=models.CharField(...)\n        )\n\n        def get_absolute_url(self, language=None):\n            language = language or get_current_language()\n            (slug, language) = self.known_translation_getter('slug',\n                default=None, language_code=language, any_language=False)\n            with override(language):\n                return reverse('fruit-detail', kwargs={'slug': slug})\n\nIn contrast, if we had only done something like this::\n\n    ...\n\n        def get_absolute_url(self, language=None)\n            language = language or get_current_language()\n            slug = self.safe_translation_getter('slug', default=None,\n                language_code=language, any_language=False)\n            with override(language):\n                return reverse('fruit-detail', kwargs={'slug': slug})\n\nThen, if the fruit `apple` has not yet been translated to FR it is possible that\nyou'll end up with the slug in a fallback langauge, and the rest of the URL in\nthe requested language, so instead of getting a language-consistent fallback\nurl::\n\n    /en/apple/\n\nYou might get::\n\n    /fr/apple/\n\nWhich, at best, would be confusing for site visitors but more likely won't exist\nresulting in a NoReverseFound exception or 404 and which clearly is not\nrespecting the fallback preferences set by the developer.\n\n\n.. |PyPI Version| image:: https://badge.fury.io/py/aldryn-translation-tools.svg\n   :target: https://pypi.python.org/pypi/aldryn-translation-tools\n.. |Build Status| image:: https://travis-ci.org/aldryn/aldryn-translation-tools.svg\n   :target: https://travis-ci.org/aldryn/aldryn-translation-tools\n.. |Coverage status| image:: https://coveralls.io/repos/aldryn/aldryn-translation-tools/badge.svg?branch=master\u0026service=github\n   :target: https://coveralls.io/github/aldryn/aldryn-translation-tools?branch=master\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdivio%2Faldryn-translation-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdivio%2Faldryn-translation-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdivio%2Faldryn-translation-tools/lists"}