{ "info": { "author": "Zach Mathew", "author_email": "UNKNOWN", "bugtrack_url": null, "classifiers": [ "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Topic :: Software Development" ], "description": "**Update:** Version 1.4.0 adds support for Django 1.6 and 1.7\nand drops support for Django < 1.4\n\nLinguo\n======\n\nLinguo aims to make model translation easy. It is designed to let you use the\nbuilt-in Django features (Query API, Model Forms, Admin, etc) as intended.\nLinguo integrates relatively easily with your existing code and performs the\ntranslation retrieval logic transparently (similar to ugettext). It does this\nby creating additional columns for each language and using proxy properties to\nmake it transparent to you.\n\n\n\nFeatures\n--------\n\n* Automatically references the correct translation based on the current active\n language.\n* Lets you use the Django ORM normally (no need to worry about which fields are\n translatable, linguo figures it out for you).\n* Support ModelForms by automatically retrieving/saving values based on the\n active language.\n* Supports Django versions 1.4.9 to 1.7.1\n* Comprehensive test coverage\n\n\n\nUsage\n-----\n\nSubclass ``MultilingualModel`` and define the ``translate`` property:\n'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\n\n::\n\n from linguo.models import MultilingualModel\n from linguo.managers import MultilingualManager\n\n class Product(MultilingualModel):\n name = models.CharField(max_length=255, verbose_name=_('name'))\n description = models.TextField(verbose_name=_('description'))\n price = models.FloatField(verbose_name=_('price'))\n\n objects = MultilingualManager()\n\n class Meta:\n # name and description are translatable fields\n translate = ('name', 'description')\n\n``MultilingualManager`` allows you to transparently perform filtering and\nordering on translatable fields (more on this below).\n\n\nAssuming your ``LANGUAGES`` settings looks like this ...\n''''''''''''''''''''''''''''''''''''''''''''''''''''''''\n::\n\n LANGUAGES = (\n ('en', ugettext('English')),\n ('fr', ugettext('French')),\n )\n\n\nThen, you can do this:\n''''''''''''''''''''''\n\n**Create a product:** It automatically sets the values for the current active\nlanguage.\n::\n\n from django.utils import translation # import the translation package\n\n translation.activate('en')\n product = Product.objects.create(\n name='English Name',\n description='English description',\n price=10\n )\n\n\n**Translate the fields** on that product.\n::\n\n product.translate(language='fr',\n name='French Name', description='French description'\n )\n product.save()\n # You don't have to specify price, because it is not a translatable field\n\n\nIf you **switch languages**, it will automatically retrieve the corresponding\ntranslated values.\n::\n\n translation.activate('fr')\n\n product.name\n -> 'French Name'\n\n product.description\n -> 'French description'\n\n\nIf you **modify translatable fields**, it will automatically assign it to\ncurrent active language.\n::\n\n translation.activate('fr')\n\n product.name = 'New French Name'\n product.save()\n\n translation.activate('en')\n\n product.name # This remains untouched in English\n -> 'English Name'\n\n\nNon-translated fields will have the same value regardless of the language\nwe are operating in.\n::\n\n translation.activate('en')\n product.price = 99\n product.save()\n\n translation.activate('fr')\n product.price\n -> 99\n\n\nQuerying the database\n'''''''''''''''''''''\n\n**Filtering and ordering** works as you would expect it to. It will\nfilter/order in the language you are operating in. You need to have\n``MultilingualManager`` on the model in order for this feature to work.\n::\n\n translation.activate('fr')\n Product.objects.filter(name='French Name').order_by('name')\n\n\nModel Forms for Multilingual models\n'''''''''''''''''''''''''''''''''''\n\nModel Forms work transparently in the sense that it automatically saves the form\ndata to the current active language. However, if you want to edit multiple\nlanguages at the same time (eg. ``name``, ``name_fr``, etc.) see section below\non 'Admin Model Forms'. ::\n\n class ProductForm(forms.ModelForm):\n class Meta:\n fields = ('name', 'description', 'price',)\n model = Product\n\nWhen saving the form, it will automatically save the form data to the fields in\nthe **current active language**.\n::\n\n translation.activate('fr') # Activate French\n\n data = {'name': 'French Name', 'description': 'French Description', 'price': 37}\n form = ProductForm(data=data)\n\n new_product = form.save()\n\n new_product.name\n -> 'French Name'\n\n new_product.description\n -> 'French Description'\n\n new_product.price\n -> 37.0\n\n\n # Other languages will not be affected\n\n translation.activate('en')\n\n new_product.name\n -> ''\n\n new_product.description\n -> ''\n\n new_product.price\n -> 37\n # Of course, non-translatable fields will have a consistent value\n\n\nAdmin Model Forms (editing multiple languages at the same time)\n'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\nIn the admin, you most probably want to include fields for each language (eg.\n``name``, ``name_fr``, etc.). In this case you must subclass\n``MultilingualModelForm`` and use it as the admin form.\n::\n\n # Form definition\n from linguo.forms import MultilingualModelForm\n\n class ProductAdminForm(MultilingualModelForm):\n class Meta:\n model = Product\n fields = forms.ALL_FIELDS\n\n # Admin definition\n class ProductAdmin(admin.ModelAdmin):\n form = ProductAdminForm\n\n\n``MultilingualModelForm`` can be used anytime you want to allow editing multiple\nlanguage simultaneously (not just in the admin). Basically, it just **disables\nthe automatic routing** to the current active language.\n\n\nInstallation\n------------\n\n#. Add ``linguo`` to your ``INSTALLED_APPS`` setting.\n#. Ensure the ``LANGUAGES`` setting contains all the languages for your site.\n\n\nAdding new languages\n''''''''''''''''''''\n\n1. Append the new language to the ``LANGUAGES`` setting.\n - You should avoid changing the primary language (ie. the first language in the list). If you do that, you will have to migrate the data in that column.\n2. Generate migrations (since new fields will be added to your models):\n ::\n\n ./manage.py makemigrations \n\n\nRunning the tests\n-----------------\n::\n\n ./manage.py test linguo.tests --settings=linguo.tests.settings\n\n\nTroubleshooting\n---------------\n\nIf you run into this message when generating migrations:\n::\n\n $ ./manage.py schemamigration yourapp --auto\n ? The field 'YourModel.field_text_de' does not have a default specified, yet is NOT NULL.\n ? Since you are adding this field, you MUST specify a default\n ? value to use for existing rows. Would you like to:\n ? 1. Quit now, and add a default to the field in models.py\n ? 2. Specify a one-off value to use for existing columns now\n ? Please select a choice:\n\nIt means you have ``blank=False, default=None`` on one or more of your models.\n\n\nBehind The Scenes (How It Works)\n--------------------------------\nFor each field marked as translatable, ``linguo`` will create additional\ndatabase fields for each additional language.\n\nFor example, if you mark the following field as translatable ...\n::\n\n name = models.CharField(_('name'), max_length=255)\n\n class Meta:\n translate = ('name',)\n\n... and you have three languages (en, fr, de). Your model will have the following db fields:\n::\n\n name = models.CharField(_('name'), max_length=255) # This is for the FIRST language \"en\"\n name_fr = models.CharField(_('name (French)'), max_length=255) # This is for \"fr\"\n name_de = models.CharField(_('name (German)'), max_length=255) # This is for \"de\"\n\nOn the instantiated model, \"name\" becomes a ``property`` that appropriately\ngets/sets the values for the corresponding field that matches the language we\nare working with.\n\nFor example, if the current language is \"fr\" ...\n::\n\n product = Product()\n product.name = \"test\" # --> sets name_fr\n\n... this will set ``product.name_fr`` (not ``product.name``)\n\n\nDatabase filtering works because ``MultingualQueryset`` rewrites the query.\n\nFor example, if the current language is \"fr\", and we run the following query ...\n::\n\n Product.objects.filter(name=\"test\")\n\n... it will be rewritten to be ...\n::\n\n Product.objects.filter(name_fr=\"test\")\n\n\nLicense\n-------\n\nThis app is licensed under the BSD license. See the LICENSE file for details.\nBasically, feel free to do what you want with this code, but I'm not liable if\nyour computer blows up.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/zmathew/django-linguo", "keywords": null, "license": "BSD", "maintainer": null, "maintainer_email": null, "name": "django-linguo", "package_url": "https://pypi.org/project/django-linguo/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/django-linguo/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/zmathew/django-linguo" }, "release_url": "https://pypi.org/project/django-linguo/1.4.0/", "requires_dist": null, "requires_python": null, "summary": "Linguo aims to make model translation easy and is designed to let you use the built-in Django features (Query API, Model Forms, Admin, etc) as intended.", "version": "1.4.0" }, "last_serial": 1368674, "releases": { "1.2.0": [], "1.2.1": [ { "comment_text": "", "digests": { "md5": "68ac93780a8e88b0c8003900a6f322d8", "sha256": "cc55f41777a951d535b78d584a12bf36c96679a93cff562316179a8e2339a1fa" }, "downloads": -1, "filename": "django-linguo-1.2.1.tar.gz", "has_sig": false, "md5_digest": "68ac93780a8e88b0c8003900a6f322d8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9250, "upload_time": "2011-07-04T15:46:35", "url": "https://files.pythonhosted.org/packages/01/1c/03a486fd03e1d38d9ce024878a766d857d49119b02ef11d2020b278019f3/django-linguo-1.2.1.tar.gz" } ], "1.2.2": [ { "comment_text": "", "digests": { "md5": "d630c2766b2bfcad48fcd633ec0a3cee", "sha256": "24e72366cf3a8108fc91cd9bc3e71d39635ba1010908f5161ad925dec4dcb940" }, "downloads": -1, "filename": "django-linguo-1.2.2.tar.gz", "has_sig": false, "md5_digest": "d630c2766b2bfcad48fcd633ec0a3cee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17817, "upload_time": "2011-07-04T18:14:44", "url": "https://files.pythonhosted.org/packages/69/65/0a0b8b8398192ef2c6082b31c9ab29238c16fc919ee5a7c6bc4fb8583567/django-linguo-1.2.2.tar.gz" } ], "1.2.3": [ { "comment_text": "", "digests": { "md5": "668430f8404ef56862cb76b104ef2291", "sha256": "440c8093ebe378fc88dcb7db76bd97e8554a73e584f532d343cc9a54eaa98aec" }, "downloads": -1, "filename": "django-linguo-1.2.3.tar.gz", "has_sig": false, "md5_digest": "668430f8404ef56862cb76b104ef2291", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18052, "upload_time": "2011-08-25T03:54:15", "url": "https://files.pythonhosted.org/packages/b7/63/8a6f41e51a60221aec058e852eb25503364ae5263ba9970340e160516586/django-linguo-1.2.3.tar.gz" } ], "1.2.4": [ { "comment_text": "", "digests": { "md5": "b12f6988aa48e021c250d6771f16bd7a", "sha256": "c62033344cd71b570998b44849556302bd5a1dc7ed31f909118b5e25b5b5fe88" }, "downloads": -1, "filename": "django-linguo-1.2.4.tar.gz", "has_sig": false, "md5_digest": "b12f6988aa48e021c250d6771f16bd7a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18554, "upload_time": "2011-10-31T20:48:40", "url": "https://files.pythonhosted.org/packages/93/a7/164128bc146fb46e88b6438fed744fbfba0ea5cf51173abf3395727e4716/django-linguo-1.2.4.tar.gz" } ], "1.2.5": [ { "comment_text": "", "digests": { "md5": "d742c6cca058d5970e108e4daaeede64", "sha256": "9a9fe2118935e6335661f43fab6ce829ddd794f5c9b471c52aba24d865e6b67c" }, "downloads": -1, "filename": "django-linguo-1.2.5.tar.gz", "has_sig": false, "md5_digest": "d742c6cca058d5970e108e4daaeede64", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18571, "upload_time": "2012-03-18T21:18:25", "url": "https://files.pythonhosted.org/packages/94/2d/29a2fe4b42269372efe7cb9a6425e9b4cf6cf5f6f3f58b1f2dfce1a2ff63/django-linguo-1.2.5.tar.gz" } ], "1.3.0": [ { "comment_text": "", "digests": { "md5": "422fd046d268fb7c141ad5e7c6a20ca5", "sha256": "ad337b226e5ba56cd47dfa9917fa74ff08a6fd7719008e424f5b1075d2765cc2" }, "downloads": -1, "filename": "django-linguo-1.3.0.tar.gz", "has_sig": false, "md5_digest": "422fd046d268fb7c141ad5e7c6a20ca5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16954, "upload_time": "2012-06-06T06:33:40", "url": "https://files.pythonhosted.org/packages/c2/03/31ad0e075d2a00c4a3c89ebfcfa1e1fa430feda96487610af67fce49892b/django-linguo-1.3.0.tar.gz" } ], "1.3.1": [ { "comment_text": "", "digests": { "md5": "a649189bfb125b431fb9fbb7c1557502", "sha256": "4c823915e55aca9cdeba1ce17b085dc1a7076eff1326a8fae81c3bb643f73fa8" }, "downloads": -1, "filename": "django-linguo-1.3.1.tar.gz", "has_sig": false, "md5_digest": "a649189bfb125b431fb9fbb7c1557502", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16808, "upload_time": "2012-08-26T20:28:02", "url": "https://files.pythonhosted.org/packages/92/a0/cd76a17ab82cbbab695d93b8369e798aa4e3cc4e8841d526d4d0717edbe7/django-linguo-1.3.1.tar.gz" } ], "1.3.2": [ { "comment_text": "", "digests": { "md5": "4b59695a1a3a80200a6f5972fbec2cc7", "sha256": "f54398aec86e4fa8a68ce6cc462621e3a25d37375860f34da4ae615088f4e8a8" }, "downloads": -1, "filename": "django-linguo-1.3.2.tar.gz", "has_sig": false, "md5_digest": "4b59695a1a3a80200a6f5972fbec2cc7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17905, "upload_time": "2013-02-01T04:48:29", "url": "https://files.pythonhosted.org/packages/04/c6/8a54181e30ddade26bdc416504ec216288075948bd8892cc3c790d2a9f40/django-linguo-1.3.2.tar.gz" } ], "1.3.3": [ { "comment_text": "", "digests": { "md5": "83626176224f81d9e4f1d3839cf3a615", "sha256": "ebd70f941acd441ad9d8f098be6c5064d1346f1573936436513678db8fe9b401" }, "downloads": -1, "filename": "django-linguo-1.3.3.tar.gz", "has_sig": false, "md5_digest": "83626176224f81d9e4f1d3839cf3a615", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17108, "upload_time": "2013-04-04T18:02:36", "url": "https://files.pythonhosted.org/packages/90/a0/9197efad452b47a2fb0bbd2d098c9b49e9790e344fd01f0253c4f3b6cd13/django-linguo-1.3.3.tar.gz" } ], "1.4.0": [ { "comment_text": "", "digests": { "md5": "617f8ca54c23823bab9a7b058ce25322", "sha256": "e5d2173e124539bc6cf275e2860033d2c1be87a3f5c8fe61817a341473787ecc" }, "downloads": -1, "filename": "django-linguo-1.4.0.tar.gz", "has_sig": false, "md5_digest": "617f8ca54c23823bab9a7b058ce25322", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18079, "upload_time": "2015-01-02T22:30:50", "url": "https://files.pythonhosted.org/packages/43/15/89c869da34d3f5477a5c9244668c69698aa5e7a4362a046fca01f74e4468/django-linguo-1.4.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "617f8ca54c23823bab9a7b058ce25322", "sha256": "e5d2173e124539bc6cf275e2860033d2c1be87a3f5c8fe61817a341473787ecc" }, "downloads": -1, "filename": "django-linguo-1.4.0.tar.gz", "has_sig": false, "md5_digest": "617f8ca54c23823bab9a7b058ce25322", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18079, "upload_time": "2015-01-02T22:30:50", "url": "https://files.pythonhosted.org/packages/43/15/89c869da34d3f5477a5c9244668c69698aa5e7a4362a046fca01f74e4468/django-linguo-1.4.0.tar.gz" } ] }