diff --git a/.gitignore b/.gitignore index cccac58f3..1e9fa8329 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ xadmin/static/xadmin/bower_components/ .idea *~ demo_app/data.db +demo_app/static/ +*.swp diff --git a/.travis.yml b/.travis.yml index 7c6253129..0fd4d162b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: python python: - - "2.7" - - "2.6" -install: "pip install -r requirements.txt --use-mirrors" -script: "cd tests/ && python runtests.py" \ No newline at end of file + - "2.7.11" +install: "pip install -r requirements.txt" +script: "cd tests/ && python runtests.py base view_base" diff --git a/README.rst b/README.rst index f863e6695..4ef644de6 100644 --- a/README.rst +++ b/README.rst @@ -1,11 +1,8 @@ -django-xadmin |Build Status| |Build Status2| +Xadmin |Build Status| ============================================ -.. |Build Status| image:: https://travis-ci.org/sshwsfc/django-xadmin.png?branch=master - :target: https://travis-ci.org/sshwsfc/django-xadmin - -.. |Build Status2| image:: https://drone.io/github.com/sshwsfc/django-xadmin/status.png - :target: https://drone.io/github.com/sshwsfc/django-xadmin/latest +.. |Build Status| image:: https://travis-ci.org/sshwsfc/xadmin.png?branch=master + :target: https://travis-ci.org/sshwsfc/xadmin Drop-in replacement of Django admin comes with lots of goodies, fully extensible with plugin support, pretty UI based on Twitter Bootstrap. @@ -57,23 +54,31 @@ Xadmin is best installed via PyPI. To install the latest version, run: .. code:: bash - pip install django-xadmin + pip install xadmin or Install from github source: .. code:: bash - pip install git+git://github.com/sshwsfc/django-xadmin.git + pip install git+git://github.com/sshwsfc/xadmin.git + +Install from github source for Django 2.0: + +.. code:: bash + + pip install git+git://github.com/sshwsfc/xadmin.git@django2 Install Requires ---------------- -- `django`_ >=1.4 +- `django`_ >=1.9 -- `django-crispy-forms`_ >=1.2.3 (For xadmin crispy forms) +- `django-crispy-forms`_ >=1.6.0 (For xadmin crispy forms) - `django-reversion`_ ([OPTION] For object history and reversion feature, please select right version by your django, see `changelog`_ ) +- `django-formtools`_ ([OPTION] For wizward form) + - `xlwt`_ ([OPTION] For export xls files) - `xlsxwriter`_ ([OPTION] For export xlsx files) @@ -81,7 +86,8 @@ Install Requires .. _django: http://djangoproject.com .. _django-crispy-forms: http://django-crispy-forms.rtfd.org .. _django-reversion: https://github.com/etianen/django-reversion -.. _changelog: https://github.com/etianen/django-reversion/blob/master/CHANGELOG.markdown +.. _changelog: https://github.com/etianen/django-reversion/blob/master/CHANGELOG.rst +.. _django-formtools: https://github.com/django/django-formtools .. _xlwt: http://www.python-excel.org/ .. _xlsxwriter: https://github.com/jmcnamara/XlsxWriter @@ -96,6 +102,12 @@ Documentation Changelogs ------------- +0.6.0 +^^^^^ +- Compact with Django1.9. +- Add Clock Picker widget for timepicker. +- Fixed some userface errors. + 0.5.0 ^^^^^ @@ -125,6 +137,7 @@ Run Demo Locally .. code:: bash cd demo_app + ./manage.py migrate ./manage.py runserver Open http://127.0.0.1:8000 in your browser, the admin user password is ``admin`` diff --git a/demo_app/app/adminx.py b/demo_app/app/adminx.py index 716188884..f6755962c 100644 --- a/demo_app/app/adminx.py +++ b/demo_app/app/adminx.py @@ -1,163 +1,196 @@ +from __future__ import absolute_import import xadmin from xadmin import views -from models import IDC, Host, MaintainLog, HostGroup, AccessRecord +from .models import IDC, Host, MaintainLog, HostGroup, AccessRecord from xadmin.layout import Main, TabHolder, Tab, Fieldset, Row, Col, AppendedText, Side from xadmin.plugins.inline import Inline from xadmin.plugins.batch import BatchChangeAction + +@xadmin.sites.register(views.website.IndexView) class MainDashboard(object): widgets = [ [ - {"type": "html", "title": "Test Widget", "content": "

Welcome to Xadmin!

Join Online Group:
QQ Qun : 282936295

"}, - {"type": "chart", "model": "app.accessrecord", 'chart': 'user_count', 'params': {'_p_date__gte': '2013-01-08', 'p': 1, '_p_date__lt': '2013-01-29'}}, - {"type": "list", "model": "app.host", 'params': { - 'o':'-guarantee_date'}}, + {"type": "html", "title": "Test Widget", + "content": "

Welcome to Xadmin!

Join Online Group:
QQ Qun : 282936295

"}, + {"type": "chart", "model": "app.accessrecord", "chart": "user_count", + "params": {"_p_date__gte": "2013-01-08", "p": 1, "_p_date__lt": "2013-01-29"}}, + {"type": "list", "model": "app.host", "params": {"o": "-guarantee_date"}}, ], [ - {"type": "qbutton", "title": "Quick Start", "btns": [{'model': Host}, {'model':IDC}, {'title': "Google", 'url': "http://www.google.com/"}]}, + {"type": "qbutton", "title": "Quick Start", + "btns": [{"model": Host}, {"model": IDC}, {"title": "Google", "url": "http://www.google.com/"}]}, {"type": "addform", "model": MaintainLog}, ] ] -xadmin.site.register(views.website.IndexView, MainDashboard) +@xadmin.sites.register(views.BaseAdminView) class BaseSetting(object): enable_themes = True use_bootswatch = True -xadmin.site.register(views.BaseAdminView, BaseSetting) +@xadmin.sites.register(views.CommAdminView) class GlobalSetting(object): global_search_models = [Host, IDC] global_models_icon = { - Host: 'fa fa-laptop', IDC: 'fa fa-cloud' + Host: "fa fa-laptop", IDC: "fa fa-cloud" } - menu_style = 'default'#'accordion' -xadmin.site.register(views.CommAdminView, GlobalSetting) + menu_style = 'default' # 'accordion' class MaintainInline(object): model = MaintainLog extra = 1 - style = 'accordion' + style = "accordion" +@xadmin.sites.register(IDC) class IDCAdmin(object): - list_display = ('name', 'description', 'create_time') - list_display_links = ('name',) + list_display = ("name", "description", "create_time", "contact", "telphone", "address", "customer_id") + list_display_links = ("name",) wizard_form_list = [ - ('First\'s Form', ('name', 'description')), - ('Second Form', ('contact', 'telphone', 'address')), - ('Thread Form', ('customer_id',)) + ("First's Form", ("name", "description")), + ("Second Form", ("contact", "telphone", "address")), + ("Thread Form", ("customer_id",)) + ] + search_fields = ["name", "description", "contact", "telphone", "address"] + list_filter = [ + "name" ] + list_quick_filter = [{"field": "name", "limit": 10}] - search_fields = ['name'] - relfield_style = 'fk-ajax' + search_fields = ["name"] + relfield_style = "fk-select" reversion_enable = True actions = [BatchChangeAction, ] - batch_fields = ('contact', 'create_time') + batch_fields = ("contact", "description", "address", "customer_id") +@xadmin.sites.register(Host) class HostAdmin(object): def open_web(self, instance): - return "Open" % instance.ip + return """Open""" % instance.ip + open_web.short_description = "Acts" open_web.allow_tags = True open_web.is_column = True - list_display = ('name', 'idc', 'guarantee_date', 'service_type', - 'status', 'open_web', 'description') - list_display_links = ('name',) + list_display = ( + "name", "idc", "guarantee_date", "service_type", "status", "open_web", + "description", "ip", + ) + list_display_links = ("name",) - raw_id_fields = ('idc',) - style_fields = {'system': "radio-inline"} + raw_id_fields = ("idc",) + style_fields = {"system": "radio-inline"} - search_fields = ['name', 'ip', 'description'] - list_filter = ['idc', 'guarantee_date', 'status', 'brand', 'model', - 'cpu', 'core_num', 'hard_disk', 'memory', ('service_type',xadmin.filters.MultiSelectFieldListFilter)] - - list_quick_filter = ['service_type',{'field':'idc__name','limit':10}] - list_bookmarks = [{'title': "Need Guarantee", 'query': {'status__exact': 2}, 'order': ('-guarantee_date',), 'cols': ('brand', 'guarantee_date', 'service_type')}] + search_fields = ["name", "ip", "description"] + list_filter = [ + "idc", "guarantee_date", "status", "brand", "model", "cpu", "core_num", + "hard_disk", "memory", ( + "service_type", + xadmin.filters.MultiSelectFieldListFilter, + ), + ] - show_detail_fields = ('idc',) + list_quick_filter = ["service_type", {"field": "idc__name", "limit": 10}] + # list_quick_filter = ["idc_id"] + list_bookmarks = [{ + "title": "Need Guarantee", + "query": {"status__exact": 2}, + "order": ("-guarantee_date",), + "cols": ("brand", "guarantee_date", "service_type"), + }] + + show_detail_fields = ("idc",) list_editable = ( - 'name', 'idc', 'guarantee_date', 'service_type', 'description') + "name", "idc", "guarantee_date", "service_type", "description", "ip" + ) save_as = True aggregate_fields = {"guarantee_date": "min"} - grid_layouts = ('table', 'thumbnails') + grid_layouts = ("table", "thumbnails") form_layout = ( Main( TabHolder( - Tab('Comm Fields', - Fieldset('Company data', - 'name', 'idc', - description="some comm fields, required" - ), - Inline(MaintainLog), + Tab( + "Comm Fields", + Fieldset( + "Company data", "name", "idc", + description="some comm fields, required", ), - Tab('Extend Fields', - Fieldset('Contact details', - 'service_type', - Row('brand', 'model'), - Row('cpu', 'core_num'), - Row(AppendedText( - 'hard_disk', 'G'), AppendedText('memory', "G")), - 'guarantee_date' - ), + Inline(MaintainLog), + ), + Tab( + "Extend Fields", + Fieldset( + "Contact details", + "service_type", + Row("brand", "model"), + Row("cpu", "core_num"), + Row( + AppendedText("hard_disk", "G"), + AppendedText("memory", "G") + ), + "guarantee_date" ), + ), ), ), Side( - Fieldset('Status data', - 'status', 'ssh_port', 'ip' - ), + Fieldset("Status data", "status", "ssh_port", "ip"), ) ) inlines = [MaintainInline] reversion_enable = True - + data_charts = { - "host_service_type_counts": {'title': u"Host service type count", "x-field": "service_type", "y-field": ("service_type",), - "option": { - "series": {"bars": {"align": "center", "barWidth": 0.8,'show':True}}, + "host_service_type_counts": {'title': u"Host service type count", "x-field": "service_type", + "y-field": ("service_type",), + "option": { + "series": {"bars": {"align": "center", "barWidth": 0.8, 'show': True}}, "xaxis": {"aggregate": "count", "mode": "categories"}, - }, - }, + }, + }, } - + + +@xadmin.sites.register(HostGroup) class HostGroupAdmin(object): - list_display = ('name', 'description') - list_display_links = ('name',) + list_display = ("name", "description") + list_display_links = ("name",) - search_fields = ['name'] - style_fields = {'hosts': 'checkbox-inline'} + search_fields = ["name"] + style_fields = {"hosts": "checkbox-inline"} +@xadmin.sites.register(MaintainLog) class MaintainLogAdmin(object): list_display = ( - 'host', 'maintain_type', 'hard_type', 'time', 'operator', 'note') - list_display_links = ('host',) + "host", "maintain_type", "hard_type", "time", "operator", "note") + list_display_links = ("host",) - list_filter = ['host', 'maintain_type', 'hard_type', 'time', 'operator'] - search_fields = ['note'] + list_filter = ["host", "maintain_type", "hard_type", "time", "operator"] + search_fields = ["note"] form_layout = ( Col("col2", - Fieldset('Record data', - 'time', 'note', - css_class='unsort short_label no_title' + Fieldset("Record data", + "time", "note", + css_class="unsort short_label no_title" ), span=9, horizontal=True ), Col("col1", - Fieldset('Comm data', - 'host', 'maintain_type' + Fieldset("Comm data", + "host", "maintain_type" ), - Fieldset('Maintain details', - 'hard_type', 'operator' + Fieldset("Maintain details", + "hard_type", "operator" ), span=3 ) @@ -165,38 +198,39 @@ class MaintainLogAdmin(object): reversion_enable = True +@xadmin.sites.register(AccessRecord) class AccessRecordAdmin(object): def avg_count(self, instance): return int(instance.view_count / instance.user_count) + avg_count.short_description = "Avg Count" avg_count.allow_tags = True avg_count.is_column = True - list_display = ('date', 'user_count', 'view_count', 'avg_count') - list_display_links = ('date',) + list_display = ("date", "user_count", "view_count", "avg_count") + list_display_links = ("date",) - list_filter = ['date', 'user_count', 'view_count'] + list_filter = ["date", "user_count", "view_count"] actions = None - aggregate_fields = {"user_count": "sum", 'view_count': "sum"} + aggregate_fields = {"user_count": "sum", "view_count": "sum"} refresh_times = (3, 5, 10) data_charts = { - "user_count": {'title': u"User Report", "x-field": "date", "y-field": ("user_count", "view_count"), "order": ('date',)}, + "user_count": {'title': u"User Report", "x-field": "date", "y-field": ("user_count", "view_count"), + "order": ('date',)}, "avg_count": {'title': u"Avg Report", "x-field": "date", "y-field": ('avg_count',), "order": ('date',)}, - "per_month": {'title': u"Monthly Users", "x-field": "_chart_month", "y-field": ("user_count", ), - "option": { - "series": {"bars": {"align": "center", "barWidth": 0.8,'show':True}}, - "xaxis": {"aggregate": "sum", "mode": "categories"}, - }, - }, + "per_month": {'title': u"Monthly Users", "x-field": "_chart_month", "y-field": ("user_count",), + "option": { + "series": {"bars": {"align": "center", "barWidth": 0.8, 'show': True}}, + "xaxis": {"aggregate": "sum", "mode": "categories"}, + }, + }, } - - def _chart_month(self,obj): + + def _chart_month(self, obj): return obj.date.strftime("%B") - -xadmin.site.register(Host, HostAdmin) -xadmin.site.register(HostGroup, HostGroupAdmin) -xadmin.site.register(MaintainLog, MaintainLogAdmin) -xadmin.site.register(IDC, IDCAdmin) -xadmin.site.register(AccessRecord, AccessRecordAdmin) +# xadmin.sites.site.register(HostGroup, HostGroupAdmin) +# xadmin.sites.site.register(MaintainLog, MaintainLogAdmin) +# xadmin.sites.site.register(IDC, IDCAdmin) +# xadmin.sites.site.register(AccessRecord, AccessRecordAdmin) diff --git a/demo_app/app/migrations/0001_initial.py b/demo_app/app/migrations/0001_initial.py new file mode 100644 index 000000000..39154fd5b --- /dev/null +++ b/demo_app/app/migrations/0001_initial.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.4 on 2016-03-20 15:50 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='AccessRecord', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date', models.DateField()), + ('user_count', models.IntegerField()), + ('view_count', models.IntegerField()), + ], + options={ + 'verbose_name': 'Access Record', + 'verbose_name_plural': 'Access Record', + }, + ), + migrations.CreateModel( + name='Host', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=64)), + ('nagios_name', models.CharField(blank=True, max_length=64, null=True, verbose_name='Nagios Host ID')), + ('ip', models.GenericIPAddressField(blank=True, null=True)), + ('internal_ip', models.GenericIPAddressField(blank=True, null=True)), + ('user', models.CharField(max_length=64)), + ('password', models.CharField(max_length=128)), + ('ssh_port', models.IntegerField(blank=True, null=True)), + ('status', models.SmallIntegerField(choices=[(0, 'Normal'), (1, 'Down'), (2, 'No Connect'), (3, 'Error')])), + ('brand', models.CharField(choices=[('DELL', 'DELL'), ('HP', 'HP'), ('Other', 'Other')], max_length=64)), + ('model', models.CharField(max_length=64)), + ('cpu', models.CharField(max_length=64)), + ('core_num', models.SmallIntegerField(choices=[(2, b'2 Cores'), (4, b'4 Cores'), (6, b'6 Cores'), (8, b'8 Cores'), (10, b'10 Cores'), (12, b'12 Cores'), (14, b'14 Cores'), (16, b'16 Cores'), (18, b'18 Cores'), (20, b'20 Cores'), (22, b'22 Cores'), (24, b'24 Cores'), (26, b'26 Cores'), (28, b'28 Cores')])), + ('hard_disk', models.IntegerField()), + ('memory', models.IntegerField()), + ('system', models.CharField(choices=[('CentOS', 'CentOS'), ('FreeBSD', 'FreeBSD'), ('Ubuntu', 'Ubuntu')], max_length=32, verbose_name='System OS')), + ('system_version', models.CharField(max_length=32)), + ('system_arch', models.CharField(choices=[('x86_64', 'x86_64'), ('i386', 'i386')], max_length=32)), + ('create_time', models.DateField()), + ('guarantee_date', models.DateField()), + ('service_type', models.CharField(choices=[(b'moniter', 'Moniter'), (b'lvs', 'LVS'), (b'db', 'Database'), (b'analysis', 'Analysis'), (b'admin', 'Admin'), (b'storge', 'Storge'), (b'web', 'WEB'), (b'email', 'Email'), (b'mix', 'Mix')], max_length=32)), + ('description', models.TextField()), + ], + options={ + 'verbose_name': 'Host', + 'verbose_name_plural': 'Host', + }, + ), + migrations.CreateModel( + name='HostGroup', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=32)), + ('description', models.TextField()), + ('hosts', models.ManyToManyField(blank=True, related_name='groups', to='app.Host', verbose_name='Hosts')), + ], + options={ + 'verbose_name': 'Host Group', + 'verbose_name_plural': 'Host Group', + }, + ), + migrations.CreateModel( + name='IDC', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=64)), + ('description', models.TextField()), + ('contact', models.CharField(max_length=32)), + ('telphone', models.CharField(max_length=32)), + ('address', models.CharField(max_length=128)), + ('customer_id', models.CharField(max_length=128)), + ('create_time', models.DateField(auto_now=True)), + ], + options={ + 'verbose_name': 'IDC', + 'verbose_name_plural': 'IDC', + }, + ), + migrations.CreateModel( + name='MaintainLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('maintain_type', models.CharField(max_length=32)), + ('hard_type', models.CharField(max_length=16)), + ('time', models.DateTimeField()), + ('operator', models.CharField(max_length=16)), + ('note', models.TextField()), + ('host', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.Host')), + ], + options={ + 'verbose_name': 'Maintain Log', + 'verbose_name_plural': 'Maintain Log', + }, + ), + migrations.AddField( + model_name='host', + name='idc', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.IDC'), + ), + ] diff --git a/demo_app/app/migrations/0002_idc_groups.py b/demo_app/app/migrations/0002_idc_groups.py new file mode 100644 index 000000000..e043672a0 --- /dev/null +++ b/demo_app/app/migrations/0002_idc_groups.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-05-20 14:04 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0007_alter_validators_add_error_messages'), + ('app', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='idc', + name='groups', + field=models.ManyToManyField(to='auth.Group'), + ), + ] diff --git a/demo_app/app/migrations/0003_host_administrator.py b/demo_app/app/migrations/0003_host_administrator.py new file mode 100644 index 000000000..eb78bc227 --- /dev/null +++ b/demo_app/app/migrations/0003_host_administrator.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-07 07:47 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('app', '0002_idc_groups'), + ] + + operations = [ + migrations.AddField( + model_name='host', + name='administrator', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name=b'Admin'), + preserve_default=False, + ), + ] diff --git a/tests/xtests/__init__.py b/demo_app/app/migrations/__init__.py similarity index 100% rename from tests/xtests/__init__.py rename to demo_app/app/migrations/__init__.py diff --git a/demo_app/app/models.py b/demo_app/app/models.py index e0c740e7b..5f2ddcc74 100644 --- a/demo_app/app/models.py +++ b/demo_app/app/models.py @@ -1,5 +1,9 @@ from django.db import models +from django.contrib.auth.models import Group +from django.conf import settings +from django.utils.encoding import python_2_unicode_compatible +AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User') SERVER_STATUS = ( (0, u"Normal"), @@ -19,7 +23,7 @@ ('mix', u"Mix"), ) - +@python_2_unicode_compatible class IDC(models.Model): name = models.CharField(max_length=64) description = models.TextField() @@ -28,10 +32,11 @@ class IDC(models.Model): telphone = models.CharField(max_length=32) address = models.CharField(max_length=128) customer_id = models.CharField(max_length=128) + groups = models.ManyToManyField(Group) # many create_time = models.DateField(auto_now=True) - def __unicode__(self): + def __str__(self): return self.name class Meta: @@ -39,12 +44,13 @@ class Meta: verbose_name_plural = verbose_name +@python_2_unicode_compatible class Host(models.Model): idc = models.ForeignKey(IDC) name = models.CharField(max_length=64) nagios_name = models.CharField(u"Nagios Host ID", max_length=64, blank=True, null=True) - ip = models.IPAddressField(blank=True, null=True) - internal_ip = models.IPAddressField(blank=True, null=True) + ip = models.GenericIPAddressField(blank=True, null=True) + internal_ip = models.GenericIPAddressField(blank=True, null=True) user = models.CharField(max_length=64) password = models.CharField(max_length=128) ssh_port = models.IntegerField(blank=True, null=True) @@ -66,7 +72,9 @@ class Host(models.Model): service_type = models.CharField(max_length=32, choices=SERVICE_TYPES) description = models.TextField() - def __unicode__(self): + administrator = models.ForeignKey(AUTH_USER_MODEL, verbose_name="Admin") + + def __str__(self): return self.name class Meta: @@ -74,6 +82,7 @@ class Meta: verbose_name_plural = verbose_name +@python_2_unicode_compatible class MaintainLog(models.Model): host = models.ForeignKey(Host) maintain_type = models.CharField(max_length=32) @@ -82,7 +91,7 @@ class MaintainLog(models.Model): operator = models.CharField(max_length=16) note = models.TextField() - def __unicode__(self): + def __str__(self): return '%s maintain-log [%s] %s %s' % (self.host.name, self.time.strftime('%Y-%m-%d %H:%M:%S'), self.maintain_type, self.hard_type) @@ -91,6 +100,7 @@ class Meta: verbose_name_plural = verbose_name +@python_2_unicode_compatible class HostGroup(models.Model): name = models.CharField(max_length=32) @@ -102,10 +112,11 @@ class Meta: verbose_name = u"Host Group" verbose_name_plural = verbose_name - def __unicode__(self): + def __str__(self): return self.name +@python_2_unicode_compatible class AccessRecord(models.Model): date = models.DateField() user_count = models.IntegerField() @@ -115,5 +126,5 @@ class Meta: verbose_name = u"Access Record" verbose_name_plural = verbose_name - def __unicode__(self): + def __str__(self): return "%s Access Record" % self.date.strftime('%Y-%m-%d') diff --git a/demo_app/app/tests.py b/demo_app/app/tests.py new file mode 100644 index 000000000..7ce503c2d --- /dev/null +++ b/demo_app/app/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/demo_app/demo/settings.py b/demo_app/demo/settings.py index 67907560a..ba583a1bc 100644 --- a/demo_app/demo/settings.py +++ b/demo_app/demo/settings.py @@ -2,16 +2,20 @@ import sys import os.path +from django.utils import six -reload(sys) -sys.setdefaultencoding('utf-8') -gettext = lambda s: s +if six.PY2 and sys.getdefaultencoding()=='ascii': + import imp + imp.reload(sys) + sys.setdefaultencoding('utf-8') + +from django.utils.translation import ugettext_lazy as _ PROJECT_ROOT = os.path.join( os.path.realpath(os.path.dirname(__file__)), os.pardir) +# PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DEBUG = True -TEMPLATE_DEBUG = DEBUG ADMINS = ( # ('Your Name', 'your_email@example.com'), @@ -31,7 +35,7 @@ } # Hosts/domain names that are valid for this site; required if DEBUG is False # See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts -ALLOWED_HOSTS = '*' +ALLOWED_HOSTS = ['*'] # Local time zone for this installation. Choices can be found here: # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name @@ -44,8 +48,8 @@ LANGUAGE_CODE = 'en-us' LANGUAGES = ( - ('en', gettext('English')), - ('zh_CN', gettext('Chinese')), + ('en', _('English')), + ('zh-hans', _('Chinese')), ) SITE_ID = 1 @@ -98,19 +102,15 @@ # Make this unique, and don't share it with anybody. SECRET_KEY = '5=!nss_+^nvyyc_j(tdcf!7(_una*3gtw+_8v5jaa=)j0g^d_2' -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - # 'django.template.loaders.eggs.Loader', -) - MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', + 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.locale.LocaleMiddleware', # Uncomment the next line for simple clickjacking protection: # 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) @@ -120,12 +120,28 @@ # Python dotted path to the WSGI application used by Django's runserver. WSGI_APPLICATION = 'demo.wsgi.application' -TEMPLATE_DIRS = ( - # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. - os.path.join(PROJECT_ROOT, "templates"), -) +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + os.path.join(PROJECT_ROOT,"templates"), + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'django.template.context_processors.tz', + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + 'debug': DEBUG, + }, + }, +] INSTALLED_APPS = ( 'django.contrib.auth', @@ -137,14 +153,12 @@ 'xadmin', 'crispy_forms', - #'reversion', + 'reversion', 'app', ) -DATE_FORMAT = 'Y-m-d' -DATETIME_FORMAT = 'Y-m-d H:i' -TIME_FORMAT = 'H:i' +TEST_RUNNER = 'django.test.runner.DiscoverRunner' # A sample logging configuration. The only tangible logging # performed by this configuration is to send an email to diff --git a/demo_app/demo/urls.py b/demo_app/demo/urls.py index 7b677eca3..409cde35d 100644 --- a/demo_app/demo/urls.py +++ b/demo_app/demo/urls.py @@ -1,16 +1,17 @@ -from django.conf.urls import patterns, include, url +# -*- coding: utf-8 -*- +from django.conf.urls import include, url # Uncomment the next two lines to enable the admin: import xadmin xadmin.autodiscover() -# from xadmin.plugins import xversion -# xversion.register_models() +# version模块自动注册需要版本控制的 Model +from xadmin.plugins import xversion +xversion.register_models() from django.contrib import admin -admin.autodiscover() -urlpatterns = patterns('', +urlpatterns = [ url(https://github.com/r'%5Eadmin/',%20include(admin.site.urls)), url(https://github.com/r'%5E',%20include(xadmin.site.urls)) -) +] diff --git a/requirements.txt b/requirements.txt index 04b203477..22c7cf752 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,8 @@ -django==1.5 -django-crispy-forms==1.4.0 \ No newline at end of file +django>=1.9.0 +django-crispy-forms>=1.6.0 +django-import-export>=0.5.1 +django-reversion>=2.0.0 +django-formtools==1.0 +future==0.15.2 +httplib2==0.9.2 +six==1.10.0 diff --git a/setup.py b/setup.py index 929437579..26bf2e698 100644 --- a/setup.py +++ b/setup.py @@ -1,29 +1,35 @@ #!/usr/bin/env python +from io import open from setuptools import setup - -# version_tuple = __import__('xadmin.version').VERSION +# version_tuple = __import__('xadmin').VERSION # version = ".".join([str(v) for v in version_tuple]) setup( - name='django-xadmin', - version='0.5.0', + name='xadmin', + version='0.6.1', description='Drop-in replacement of Django admin comes with lots of goodies, fully extensible with plugin support, pretty UI based on Twitter Bootstrap.', - long_description=open('README.rst').read(), + long_description=open('README.rst', encoding='utf-8').read(), author='sshwsfc', author_email='sshwsfc@gmail.com', - license=open('LICENSE').read(), + license=open('LICENSE', encoding='utf-8').read(), url='http://www.xadmin.io/', download_url='http://github.com/sshwsfc/django-xadmin/archive/master.zip', - packages=['xadmin', 'xadmin.plugins', 'xadmin.templatetags', 'xadmin.views'], + packages=['xadmin', 'xadmin.migrations', 'xadmin.plugins', 'xadmin.templatetags', 'xadmin.views'], include_package_data=True, install_requires=[ 'setuptools', - 'django>=1.5', - 'django-crispy-forms>=1.4.0', + 'django>=1.9.0', + 'django-crispy-forms>=1.6.0', + 'django-reversion>=2.0.0', + 'django-formtools>=1.0', + 'django-import-export>=0.5.1', + 'httplib2==0.9.2', + 'future', + 'six' ], extras_require={ 'Excel': ['xlwt', 'xlsxwriter'], - 'Reversion': ['django-reversion'], + 'Reversion': ['django-reversion>=2.0.0'], }, zip_safe=False, keywords=['admin', 'django', 'xadmin', 'bootstrap'], @@ -37,6 +43,7 @@ "Programming Language :: JavaScript", 'Programming Language :: Python', "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.4", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", diff --git a/tests/runtests.py b/tests/runtests.py index a9426937f..5f8677b25 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -1,9 +1,15 @@ #!/usr/bin/env python +from __future__ import print_function import os import shutil import sys import tempfile +import django +from django.apps import AppConfig,apps +from django.utils.encoding import smart_text + + TEST_ROOT = os.path.realpath(os.path.dirname(__file__)) RUNTESTS_DIR = os.path.join(TEST_ROOT, 'xtests') @@ -28,9 +34,13 @@ def get_test_modules(): modules = [] for f in os.listdir(RUNTESTS_DIR): - if (f.startswith('__init__') or - f.startswith('.') or - f.startswith('sql') or not os.path.isdir(os.path.join(RUNTESTS_DIR, f))): + if ( + f.startswith('__init__') + or f.startswith('__pycache__') + or f.startswith('.') + or f.startswith('sql') + or not os.path.isdir(os.path.join(RUNTESTS_DIR, f)) + ): continue modules.append(f) return modules @@ -72,26 +82,24 @@ def setup(verbosity, test_labels): # Load all the ALWAYS_INSTALLED_APPS. # (This import statement is intentionally delayed until after we # access settings because of the USE_I18N dependency.) - from django.db.models.loading import get_apps, load_app - get_apps() + # Load all the test model apps. test_labels_set = set([label.split('.')[0] for label in test_labels]) test_modules = get_test_modules() - for module_name in test_modules: - module_label = '.'.join(['xtests', module_name]) + module_label = module_name # if the module was named on the command line, or # no modules were named (i.e., run all), import # this module and add it to the list to test. if not test_labels or module_name in test_labels_set: if verbosity >= 2: - print "Importing application %s" % module_name - mod = load_app(module_label) - if mod: - if module_label not in settings.INSTALLED_APPS: - settings.INSTALLED_APPS.append(module_label) + print("Importing application %s" % module_name) + if module_label not in settings.INSTALLED_APPS: + settings.INSTALLED_APPS.append(module_label) + django.setup() + [a.models_module for a in apps.get_app_configs()] return state def teardown(state): @@ -100,7 +108,7 @@ def teardown(state): # so that it will successfully remove temp trees containing # non-ASCII filenames on Windows. (We're assuming the temp dir # name itself does not contain non-ASCII characters.) - shutil.rmtree(unicode(TEMP_DIR)) + shutil.rmtree(smart_text(TEMP_DIR)) # Restore the old settings. for key, value in state.items(): setattr(settings, key, value) @@ -159,7 +167,6 @@ def django_tests(verbosity, interactive, failfast, test_labels): if options.liveserver is not None: os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = options.liveserver - failures = django_tests(int(options.verbosity), options.interactive, options.failfast, args) if failures: diff --git a/tests/settings.py b/tests/settings.py index f1bfda658..c07079818 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -4,7 +4,7 @@ 'ENGINE': 'django.db.backends.sqlite3', } } - +MIDDLEWARE_CLASSES = () # Required for Django 1.4+ STATIC_URL = '/static/' diff --git a/tests/urls.py b/tests/urls.py index 080c69e14..28b9250d2 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -1,5 +1,5 @@ from django.conf.urls import patterns, include urlpatterns = patterns('', - (r'^view_base/', include('xtests.view_base.urls')), + (r'^view_base/', include('view_base.urls')), ) \ No newline at end of file diff --git a/tests/xtests/site/apps.py b/tests/xtests/site/apps.py new file mode 100644 index 000000000..37777566c --- /dev/null +++ b/tests/xtests/site/apps.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +#coding:utf-8 +import sys +from django.utils import six +if six.PY2 and sys.getdefaultencoding()=='ascii': + import imp + imp.reload(sys) + sys.setdefaultencoding('utf-8') + +from django.apps import AppConfig + +class SiteApp(AppConfig): + name = "site" diff --git a/tests/xtests/site/tests.py b/tests/xtests/site/tests.py index 5d9beef39..808997f40 100644 --- a/tests/xtests/site/tests.py +++ b/tests/xtests/site/tests.py @@ -1,10 +1,11 @@ +from __future__ import absolute_import from django.http import HttpResponse -from xtests.base import BaseTest +from base import BaseTest from xadmin.sites import AdminSite from xadmin.views import BaseAdminView, BaseAdminPlugin, ModelAdminView, filter_hook -from models import ModelA +from .models import ModelA class ModelAAdmin(object): diff --git a/tests/xtests/view_base/adminx.py b/tests/xtests/view_base/adminx.py index 7db81e35f..b75fc8f8a 100644 --- a/tests/xtests/view_base/adminx.py +++ b/tests/xtests/view_base/adminx.py @@ -1,6 +1,7 @@ +from __future__ import absolute_import from xadmin.sites import AdminSite from xadmin.views import BaseAdminView, CommAdminView, ListAdminView -from models import ModelA, ModelB +from .models import ModelA, ModelB site = AdminSite('views_base') diff --git a/tests/xtests/view_base/apps.py b/tests/xtests/view_base/apps.py new file mode 100644 index 000000000..5b59ac85d --- /dev/null +++ b/tests/xtests/view_base/apps.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +#coding:utf-8 +import sys +from django.utils import six +if six.PY2 and sys.getdefaultencoding()=='ascii': + import imp + imp.reload(sys) + sys.setdefaultencoding('utf-8') + +from django.apps import AppConfig + +class ViewBaseApp(AppConfig): + name = "view_base" diff --git a/tests/xtests/view_base/tests.py b/tests/xtests/view_base/tests.py index 8d01984d7..a779341f4 100644 --- a/tests/xtests/view_base/tests.py +++ b/tests/xtests/view_base/tests.py @@ -1,11 +1,12 @@ +from __future__ import absolute_import from django.contrib.auth.models import User -from xtests.base import BaseTest +from base import BaseTest from xadmin.views import BaseAdminView, BaseAdminPlugin, ModelAdminView, ListAdminView -from models import ModelA, ModelB -from adminx import site, ModelAAdmin, TestBaseView, TestCommView, TestAView, OptionA +from .models import ModelA, ModelB +from .adminx import site, ModelAAdmin, TestBaseView, TestCommView, TestAView, OptionA class BaseAdminTest(BaseTest): @@ -57,8 +58,3 @@ def setUp(self): def test_model_icon(self): self.assertEqual(self.test_view.get_model_icon(ModelA), 'flag') self.assertEqual(self.test_view.get_model_icon(ModelB), 'test') - - - - - diff --git a/tests/xtests/view_base/urls.py b/tests/xtests/view_base/urls.py index 5f76a1c80..a6a3601ec 100644 --- a/tests/xtests/view_base/urls.py +++ b/tests/xtests/view_base/urls.py @@ -1,5 +1,6 @@ +from __future__ import absolute_import from django.conf.urls import patterns, include -from adminx import site +from .adminx import site urlpatterns = patterns('', (r'', include(site.urls)), diff --git a/xadmin/__init__.py b/xadmin/__init__.py index 2eaa6c267..3e1a0522c 100644 --- a/xadmin/__init__.py +++ b/xadmin/__init__.py @@ -1,7 +1,7 @@ -from xadmin.sites import AdminSite, site -VERSION = [0,5,0] +VERSION = (0,6,0) +from xadmin.sites import AdminSite, site class Settings(object): pass @@ -14,9 +14,10 @@ def autodiscover(): may want. """ + from importlib import import_module from django.conf import settings - from django.utils.importlib import import_module from django.utils.module_loading import module_has_submodule + from django.apps import apps setattr(settings, 'CRISPY_TEMPLATE_PACK', 'bootstrap3') setattr(settings, 'CRISPY_CLASS_CONVERTERS', { @@ -47,12 +48,12 @@ def autodiscover(): from xadmin.plugins import register_builtin_plugins register_builtin_plugins(site) - for app in settings.INSTALLED_APPS: - mod = import_module(app) + for app_config in apps.get_app_configs(): + mod = import_module(app_config.name) # Attempt to import the app's admin module. try: before_import_registry = site.copy_registry() - import_module('%s.adminx' % app) + import_module('%s.adminx' % app_config.name) except: # Reset the model registry to the state before the last import as # this import will have to reoccur on the next request and this @@ -65,3 +66,5 @@ def autodiscover(): # attempting to import it, otherwise we want it to bubble up. if module_has_submodule(mod, 'adminx'): raise + +default_app_config = 'xadmin.apps.XAdminConfig' diff --git a/xadmin/adminx.py b/xadmin/adminx.py index 1fece0dcb..e7a66e0ff 100644 --- a/xadmin/adminx.py +++ b/xadmin/adminx.py @@ -1,9 +1,32 @@ +from __future__ import absolute_import import xadmin -from models import UserSettings +from .models import UserSettings, Log from xadmin.layout import * +from django.utils.translation import ugettext_lazy as _, ugettext class UserSettingsAdmin(object): model_icon = 'fa fa-cog' hidden_menu = True + xadmin.site.register(UserSettings, UserSettingsAdmin) + +class LogAdmin(object): + + def link(self, instance): + if instance.content_type and instance.object_id and instance.action_flag != 'delete': + admin_url = self.get_admin_url('https://github.com/%s_%s_change'%20%%20(instance.content_type.app_label,%20instance.content_type.model), + instance.object_id) + return "%s" % (admin_url, _('Admin Object')) + else: + return '' + link.short_description = "" + link.allow_tags = True + link.is_column = False + + list_display = ('action_time', 'user', 'ip_addr', '__str__', 'link') + list_filter = ['user', 'action_time'] + search_fields = ['ip_addr', 'message'] + model_icon = 'fa fa-cog' + +xadmin.site.register(Log, LogAdmin) diff --git a/xadmin/apps.py b/xadmin/apps.py new file mode 100644 index 000000000..6bae500a6 --- /dev/null +++ b/xadmin/apps.py @@ -0,0 +1,15 @@ +from django.apps import AppConfig +from django.core import checks +from django.utils.translation import ugettext_lazy as _ +import xadmin + + +class XAdminConfig(AppConfig): + """Simple AppConfig which does not do automatic discovery.""" + + name = 'xadmin' + verbose_name = _("Administration") + + def ready(self): + self.module.autodiscover() + setattr(xadmin,'site',xadmin.site) diff --git a/xadmin/filters.py b/xadmin/filters.py index f4eb6e9d9..9eba01e99 100644 --- a/xadmin/filters.py +++ b/xadmin/filters.py @@ -1,22 +1,25 @@ +from __future__ import absolute_import from django.db import models from django.core.exceptions import ImproperlyConfigured -from django.utils.encoding import smart_unicode +from django.utils.encoding import smart_text from django.utils.translation import ugettext_lazy as _ from django.utils import timezone from django.template.loader import get_template from django.template.context import Context +from django.utils import six from django.utils.safestring import mark_safe from django.utils.html import escape,format_html from django.utils.text import Truncator -from django.core.cache import cache, get_cache +from django.core.cache import cache, caches from xadmin.views.list import EMPTY_CHANGELIST_VALUE +from xadmin.util import is_related_field,is_related_field2 import datetime FILTER_PREFIX = '_p_' SEARCH_VAR = '_q_' -from util import (get_model_from_relation, +from .util import (get_model_from_relation, reverse_field_path, get_limit_choices_to_from_path, prepare_lookup_value) @@ -44,8 +47,10 @@ def query_string(self, new_params=None, remove=None): return self.admin_view.get_query_string(new_params, remove) def form_params(self): - return self.admin_view.get_form_params( - remove=map(lambda k: FILTER_PREFIX + k, self.used_params.keys())) + arr = map(lambda k: FILTER_PREFIX + k, self.used_params.keys()) + if six.PY3: + arr = list(arr) + return self.admin_view.get_form_params(remove=arr) def has_output(self): """ @@ -68,7 +73,7 @@ def get_context(self): def __str__(self): tpl = get_template(self.template) - return mark_safe(tpl.render(Context(self.get_context()))) + return mark_safe(tpl.render(context=self.get_context())) class FieldFilterManager(object): @@ -119,14 +124,20 @@ def __init__(self, field, request, params, model, admin_view, field_path): else: self.context_params["%s_val" % name] = '' - map(lambda kv: setattr( - self, 'lookup_' + kv[0], kv[1]), self.context_params.items()) + arr = map( + lambda kv: setattr(self, 'lookup_' + kv[0], kv[1]), + self.context_params.items() + ) + if six.PY3: + list(arr) def get_context(self): context = super(FieldFilter, self).get_context() context.update(self.context_params) - context['remove_url'] = self.query_string( - {}, map(lambda k: FILTER_PREFIX + k, self.used_params.keys())) + obj = map(lambda k: FILTER_PREFIX + k, self.used_params.keys()) + if six.PY3: + obj = list(obj) + context['remove_url'] = self.query_string({}, obj) return context def has_output(self): @@ -157,22 +168,28 @@ def choices(self): for lookup, title in ( ('', _('All')), ('1', _('Yes')), - ('0', _('No'))): + ('0', _('No')), + ): yield { - 'selected': self.lookup_exact_val == lookup and not self.lookup_isnull_val, - 'query_string': self.query_string({ - self.lookup_exact_name: lookup, - }, [self.lookup_isnull_name]), - 'display': title, - } + 'selected': ( + self.lookup_exact_val == lookup + and not self.lookup_isnull_val + ), + 'query_string': self.query_string( + {self.lookup_exact_name: lookup}, + [self.lookup_isnull_name], + ), + 'display': title, + } if isinstance(self.field, models.NullBooleanField): yield { - 'selected': self.lookup_isnull_val == 'True', - 'query_string': self.query_string({ - self.lookup_isnull_name: 'True', - }, [self.lookup_exact_name]), - 'display': _('Unknown'), - } + 'selected': self.lookup_isnull_val == 'True', + 'query_string': self.query_string( + {self.lookup_isnull_name: 'True'}, + [self.lookup_exact_name], + ), + 'display': _('Unknown'), + } @manager.register @@ -191,7 +208,7 @@ def choices(self): } for lookup, title in self.field.flatchoices: yield { - 'selected': smart_unicode(lookup) == self.lookup_exact_val, + 'selected': smart_text(lookup) == self.lookup_exact_val, 'query_string': self.query_string({self.lookup_exact_name: lookup}), 'display': title, } @@ -200,11 +217,15 @@ def choices(self): @manager.register class TextFieldListFilter(FieldFilter): template = 'xadmin/filters/char.html' - lookup_formats = {'in': '%s__in','search': '%s__contains'} + lookup_formats = {'in': '%s__in', 'search': '%s__contains'} @classmethod def test(cls, field, request, params, model, admin_view, field_path): - return (isinstance(field, models.CharField) and field.max_length > 20) or isinstance(field, models.TextField) + return ( + isinstance(field, models.CharField) + and field.max_length > 20 + or isinstance(field, models.TextField) + ) @manager.register @@ -310,11 +331,11 @@ class RelatedFieldSearchFilter(FieldFilter): @classmethod def test(cls, field, request, params, model, admin_view, field_path): - if not (hasattr(field, 'rel') and bool(field.rel) or isinstance(field, models.related.RelatedObject)): + if not is_related_field2(field): return False related_modeladmin = admin_view.admin_site._registry.get( get_model_from_relation(field)) - return related_modeladmin and getattr(related_modeladmin, 'relfield_style', None) == 'fk-ajax' + return related_modeladmin and getattr(related_modeladmin, 'relfield_style', None) in ('fk-ajax', 'fk-select') def __init__(self, field, request, params, model, model_admin, field_path): other_model = get_model_from_relation(field) @@ -327,13 +348,16 @@ def __init__(self, field, request, params, model, model_admin, field_path): super(RelatedFieldSearchFilter, self).__init__( field, request, params, model, model_admin, field_path) + related_modeladmin = self.admin_view.admin_site._registry.get(other_model) + self.relfield_style = related_modeladmin.relfield_style + if hasattr(field, 'verbose_name'): self.lookup_title = field.verbose_name else: self.lookup_title = other_model._meta.verbose_name self.title = self.lookup_title self.search_url = model_admin.get_admin_url('%s_%s_changelist' % ( - other_model._meta.app_label, other_model._meta.module_name)) + other_model._meta.app_label, other_model._meta.model_name)) self.label = self.label_for_value(other_model, rel_name, self.lookup_exact_val) if self.lookup_exact_val else "" self.choices = '?' if field.rel.limit_choices_to: @@ -353,6 +377,7 @@ def get_context(self): context['search_url'] = self.search_url context['label'] = self.label context['choices'] = self.choices + context['relfield_style'] = self.relfield_style return context @@ -361,7 +386,7 @@ class RelatedFieldListFilter(ListFieldFilter): @classmethod def test(cls, field, request, params, model, admin_view, field_path): - return (hasattr(field, 'rel') and bool(field.rel) or isinstance(field, models.related.RelatedObject)) + return is_related_field2(field) def __init__(self, field, request, params, model, model_admin, field_path): other_model = get_model_from_relation(field) @@ -383,7 +408,7 @@ def __init__(self, field, request, params, model, model_admin, field_path): self.title = self.lookup_title def has_output(self): - if (isinstance(self.field, models.related.RelatedObject) + if (is_related_field(self.field) and self.field.field.null or hasattr(self.field, 'rel') and self.field.null): extra = 1 @@ -403,13 +428,13 @@ def choices(self): } for pk_val, val in self.lookup_choices: yield { - 'selected': self.lookup_exact_val == smart_unicode(pk_val), + 'selected': self.lookup_exact_val == smart_text(pk_val), 'query_string': self.query_string({ self.lookup_exact_name: pk_val, }, [self.lookup_isnull_name]), 'display': val, } - if (isinstance(self.field, models.related.RelatedObject) + if (is_related_field(self.field) and self.field.field.null or hasattr(self.field, 'rel') and self.field.null): yield { @@ -439,13 +464,13 @@ def test(cls, field, request, params, model, admin_view, field_path): def get_cached_choices(self): if not self.cache_config['enabled']: return None - c = get_cache(self.cache_config['cache']) + c = caches(self.cache_config['cache']) return c.get(self.cache_config['key']%self.field_path) def set_cached_choices(self,choices): if not self.cache_config['enabled']: return - c = get_cache(self.cache_config['cache']) + c = caches(self.cache_config['cache']) return c.set(self.cache_config['key']%self.field_path,choices) def __init__(self, field, request, params, model, model_admin, field_path,field_order_by=None,field_limit=None,sort_key=None,cache_config=None): @@ -489,7 +514,7 @@ def choices(self): } for val in self.lookup_choices: yield { - 'selected': smart_unicode(val) in self.lookup_in_val, + 'selected': smart_text(val) in self.lookup_in_val, 'query_string': self.query_string({self.lookup_in_name: ",".join([val]+self.lookup_in_val),}), 'remove_query_string': self.query_string({self.lookup_in_name: ",".join([v for v in self.lookup_in_val if v != val]),}), 'display': val, @@ -530,7 +555,7 @@ def choices(self): if val is None: include_none = True continue - val = smart_unicode(val) + val = smart_text(val) yield { 'selected': self.lookup_exact_val == val, 'query_string': self.query_string({self.lookup_exact_name: val}, @@ -543,4 +568,4 @@ def choices(self): 'query_string': self.query_string({self.lookup_isnull_name: 'True'}, [self.lookup_exact_name]), 'display': EMPTY_CHANGELIST_VALUE, - } \ No newline at end of file + } diff --git a/xadmin/forms.py b/xadmin/forms.py index 8ef880c53..512de103b 100644 --- a/xadmin/forms.py +++ b/xadmin/forms.py @@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy, ugettext as _ -from xadmin.util import User +from django.contrib.auth import get_user_model ERROR_MESSAGE = ugettext_lazy("Please enter the correct username and password " "for a staff account. Note that both fields are case-sensitive.") @@ -30,6 +30,7 @@ def clean(self): username=username, password=password) if self.user_cache is None: if u'@' in username: + User = get_user_model() # Mistakenly entered e-mail address instead of username? Look it up. try: user = User.objects.get(email=username) diff --git a/xadmin/layout.py b/xadmin/layout.py index 443830bcf..1d3c7a920 100644 --- a/xadmin/layout.py +++ b/xadmin/layout.py @@ -1,7 +1,7 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import * from crispy_forms.bootstrap import * -from crispy_forms.utils import render_field, flatatt +from crispy_forms.utils import render_field, flatatt, TEMPLATE_PACK from crispy_forms import layout from crispy_forms import bootstrap @@ -70,17 +70,28 @@ def __init__(self, field, *args, **kwargs): if '@@' not in args: self.inputs.append('@@') + self.input_size = None + css_class = kwargs.get('css_class', '') + if 'input-lg' in css_class: + self.input_size = 'input-lg' + if 'input-sm' in css_class: + self.input_size = 'input-sm' + super(InputGroup, self).__init__(field, **kwargs) - def render(self, form, form_style, context, template_pack='bootstrap'): + def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs): classes = form.fields[self.field].widget.attrs.get('class', '') - context.update( - {'inputs': self.inputs, 'classes': classes.replace('form-control', '')}) + extra_context = { + 'inputs': self.inputs, + 'input_size': self.input_size, + 'classes': classes.replace('form-control', '') + } if hasattr(self, 'wrapper_class'): - context['wrapper_class'] = self.wrapper_class + extra_context['wrapper_class'] = self.wrapper_class + return render_field( self.field, form, form_style, context, template=self.template, - attrs=self.attrs, template_pack=template_pack) + attrs=self.attrs, template_pack=template_pack, extra_context=extra_context, **kwargs) class PrependedText(InputGroup): diff --git a/xadmin/locale/de_DE/LC_MESSAGES/django.mo b/xadmin/locale/de_DE/LC_MESSAGES/django.mo index 83384667b..e594acb7e 100644 Binary files a/xadmin/locale/de_DE/LC_MESSAGES/django.mo and b/xadmin/locale/de_DE/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/de_DE/LC_MESSAGES/django.po b/xadmin/locale/de_DE/LC_MESSAGES/django.po index 07c19c358..65ab4726a 100644 --- a/xadmin/locale/de_DE/LC_MESSAGES/django.po +++ b/xadmin/locale/de_DE/LC_MESSAGES/django.po @@ -10,63 +10,77 @@ msgid "" msgstr "" "Project-Id-Version: xadmin-core\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-10 10:31+0800\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: 2013-12-19 11:06+0000\n" "Last-Translator: Sebastian Morkisch \n" -"Language-Team: German (Germany) (http://www.transifex.com/projects/p/xadmin/language/de_DE/)\n" +"Language-Team: German (Germany) (http://www.transifex.com/projects/p/xadmin/" +"language/de_DE/)\n" "Language: de_DE\n" "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" -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "Alle" -#: filters.py:158 plugins/export.py:117 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "Ja" -#: filters.py:159 plugins/export.py:117 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "Nein" -#: filters.py:173 +#: filters.py:175 msgid "Unknown" msgstr "Unbekannt" -#: filters.py:265 +#: filters.py:267 msgid "Any date" msgstr "Beliebiges Datum" -#: filters.py:266 +#: filters.py:268 msgid "Has date" msgstr "Hat ein Datum" -#: filters.py:269 +#: filters.py:271 msgid "Has no date" msgstr "Hat kein Datum" -#: filters.py:272 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "Heute" -#: filters.py:276 +#: filters.py:278 msgid "Past 7 days" msgstr "Letzten 7 Tage" -#: filters.py:280 +#: filters.py:282 msgid "This month" msgstr "Diesen Monat" -#: filters.py:284 +#: filters.py:286 msgid "This year" msgstr "Dieses Jahr" #: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." -msgstr "Bitte geben Sie den richtigen Benutzernamen und das Kennwort für ein Mitarbeiter Konto an. Beachten Sie die Groß-und Kleinschreibung in den beiden Feldern." +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." +msgstr "" +"Bitte geben Sie den richtigen Benutzernamen und das Kennwort für ein " +"Mitarbeiter Konto an. Beachten Sie die Groß-und Kleinschreibung in den " +"beiden Feldern." #: forms.py:21 msgid "Please log in again, because your session has expired." @@ -77,107 +91,171 @@ msgstr "Ihre Sitzung ist abgelaufen - bitte melden Sie sich erneut an." msgid "Your e-mail address is not your username. Try '%s' instead." msgstr "Ihre Email ist nicht ihr Benutzername. Probieren sie anstelle %s." -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "Titel" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "Benutzer" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "URL Name" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "Abfrage String" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "Wird geteilt" -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "Lesezeichen" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "Lesezeichen" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "Einstellungsschlüssel" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "Einstellungsinhalt" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "Benutzereinstellung" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "Benutzereinstelllungen" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "Seite" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "Widget Typ" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "Widget Parameter" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "Benutzer Widget" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "Benutzer Widgets" -#: widgets.py:48 -msgid "Now" -msgstr "Jetzt" +#: models.py:142 +#, fuzzy +#| msgid "Date/time" +msgid "action time" +msgstr "Datum/Uhrzeit" + +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" + +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +#, fuzzy +#| msgid "Change %s" +msgid "change message" +msgstr "Ändern %s" + +#: models.py:164 +#, fuzzy +#| msgid "log in" +msgid "log entry" +msgstr "einloggen" -#: plugins/actions.py:54 +#: models.py:165 +msgid "log entries" +msgstr "" + +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, fuzzy, python-format +#| msgid "Change one %(objects_name)s" +#| msgid_plural "Batch change %(counter)s %(objects_name)s" +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "Anpassung von %(objects_name)s" + +#: models.py:180 +#, fuzzy, python-format +#| msgid "Related Objects" +msgid "Deleted \"%(object)s.\"" +msgstr "Abhängige Objekte" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "Lösche ausgewählte %(verbose_name_plural)s" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, fuzzy, python-format +#| msgid "Successfully deleted %(count)d %(items)s." +msgid "Batch delete %(count)d %(items)s." +msgstr "Erfolgreich gelöscht %(count)d %(items)s." + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "Erfolgreich gelöscht %(count)d %(items)s." -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "Kann nicht gelöscht werden %(name)s" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "Sind Sie sicher?" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" msgstr[0] "%(total_count)s ausgewählt" msgstr[1] "Alle %(total_count)s ausgewählt" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "0 von %(cnt)s ausgewählt" -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." +#: plugins/actions.py:179 plugins/actions.py:189 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." msgstr "" #: plugins/aggregation.py:14 @@ -246,20 +324,20 @@ msgstr "Status" msgid "Permission Name" msgstr "Berechtigungen" -#: plugins/auth.py:159 +#: plugins/auth.py:167 msgid "Change Password" msgstr "Passwort ändern" -#: plugins/auth.py:189 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "Passwort ändern: %s" -#: plugins/auth.py:214 plugins/auth.py:246 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "Passwort erfolgreich geändert." -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -274,7 +352,7 @@ msgstr "Änderung des Feldes" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "Anpassung aller gewählten %(verbose_name_plural)s" -#: plugins/batch.py:90 +#: plugins/batch.py:89 #, python-format msgid "Successfully change %(count)d %(items)s." msgstr "Es wurden %(count)d %(items)s erfolgreich geändert." @@ -284,19 +362,19 @@ msgstr "Es wurden %(count)d %(items)s erfolgreich geändert." msgid "Batch change %s" msgstr "" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 msgid "bookmark" msgstr "Als Lesezeichen abspeichern" -#: plugins/bookmark.py:173 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." msgstr "" -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "Einfaches Diagramm der Modelle anzeigen." -#: plugins/chart.py:49 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "%s Diagramme" @@ -344,27 +422,28 @@ msgid_plural "%(count)s comments were successfully %(action)s." msgstr[0] "" msgstr[1] "" -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "Einzelheiten von %s" -#: plugins/editable.py:47 +#: plugins/editable.py:46 #, python-format msgid "Enter %s" msgstr "Eingabe %s" -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." -msgstr "%(name)s bezeichnetes Objekt mit dem Primärschlüssel %(key)r existiert nicht." +msgstr "" +"%(name)s bezeichnetes Objekt mit dem Primärschlüssel %(key)r existiert nicht." -#: plugins/export.py:87 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "Seite" -#: plugins/filters.py:125 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "Fehlerhaftes Filtern: %s" @@ -389,11 +468,11 @@ msgstr "Download" msgid "Change:" msgstr "Änderung:" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "Tabelle" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "Thumbnails" @@ -401,20 +480,26 @@ msgstr "Thumbnails" msgid "Forgotten your password or username?" msgstr "Haben Sie Ihr Passwort oder den Benutzernamen vergessen?" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "Erstelle %s neu" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "Abhängige Objekte" -#: plugins/relfield.py:29 plugins/topnav.py:35 +#: plugins/relfield.py:29 plugins/topnav.py:38 #, python-format msgid "Search %s" msgstr "Suche %s" +#: plugins/relfield.py:67 +#, fuzzy, python-format +#| msgid "Select Date" +msgid "Select %s" +msgstr "Datum wählen" + #: plugins/themes.py:47 msgid "Default" msgstr "Standard" @@ -431,98 +516,104 @@ msgstr "Bootstrap2" msgid "Bootstrap 2.x theme" msgstr "Bootstrap 2.x Thema" -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "Hinzufügen %s" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "Erste Version." -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "Version ändern." -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "Version zurückfallen." -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "Version wiederherstellen." -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "Gelöschte %(verbose_name)s." -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "Verlauf" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "Gelöschte %(name)s wiederherstellen" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "Änderungen: %s" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "Es müssen zwei Versionen ausgewählt sein." -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "Bitte wählen Sie zwei unterschiedliche Versionen aus." -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "Aktuell: %s" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "Auf %s zurückfallen" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." msgstr "" -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "Stelle %s wieder her" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." msgstr "" -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "Seite konnte nicht gefunden werden" #: templates/xadmin/404.html:10 msgid "We're sorry, but the requested page could not be found." -msgstr "Es tut uns leid, aber die angeforderte Seite konnte nicht gefunden werden." +msgstr "" +"Es tut uns leid, aber die angeforderte Seite konnte nicht gefunden werden." -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -533,7 +624,7 @@ msgstr "Es tut uns leid, aber die angeforderte Seite konnte nicht gefunden werde #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "Startseite" @@ -550,20 +641,13 @@ msgid "Server Error (500)" msgstr "Server Fehler (500)" #: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "Es ist ein Fehler aufgetreten. Der Siteadmin wurde via E-Mail informiert und wird sich in Kürze um die Behebung des Fehlers kümmern. Wir danken für Ihre Geduld." - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "Willkommen," - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "Abmelden" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." -msgstr "Sie haben nicht die notwendige Berechtigung etwas zu ändern." +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." +msgstr "" +"Es ist ein Fehler aufgetreten. Der Siteadmin wurde via E-Mail informiert und " +"wird sich in Kürze um die Behebung des Fehlers kümmern. Wir danken für Ihre " +"Geduld." #: templates/xadmin/auth/password_reset/complete.html:11 #: templates/xadmin/auth/password_reset/done.html:11 @@ -583,8 +667,12 @@ msgid "Enter new password" msgstr "Geben Sie Ihr neues Passwort ein." #: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." -msgstr "Bitte geben Sie Ihr neues Passwort zweimal ein, damit die Identität festgestellt werden kann." +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." +msgstr "" +"Bitte geben Sie Ihr neues Passwort zweimal ein, damit die Identität " +"festgestellt werden kann." #: templates/xadmin/auth/password_reset/confirm.html:19 msgid "Change my password" @@ -595,16 +683,27 @@ msgid "Password reset unsuccessful" msgstr "Passwort zurücksetzen fehlgeschlagen" #: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." -msgstr "Der Passwort-zurücksetzen Link war ungültig, weil dieser möglicherweise schon verwendet wurde. Bitte fordern Sie einen neuen Link an." +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." +msgstr "" +"Der Passwort-zurücksetzen Link war ungültig, weil dieser möglicherweise " +"schon verwendet wurde. Bitte fordern Sie einen neuen Link an." #: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." -msgstr "Wir haben Ihnen eine E-Mail mit Anweisungen zum Zurücksetzen Ihres Passwortes an die Adresse geschickt, die Sie uns übermittelt haben. Sie sollten sie in Kürze erhalten." +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." +msgstr "" +"Wir haben Ihnen eine E-Mail mit Anweisungen zum Zurücksetzen Ihres " +"Passwortes an die Adresse geschickt, die Sie uns übermittelt haben. Sie " +"sollten sie in Kürze erhalten." #: templates/xadmin/auth/password_reset/email.html:2 #, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." msgstr "" #: templates/xadmin/auth/password_reset/email.html:4 @@ -629,8 +728,13 @@ msgid "Password reset" msgstr "Passwort zurücksetzen" #: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." -msgstr "Haben Sie Ihr Passwort vergessen? Geben Sie unten Ihre E-Mail Adresse ein und wir werden Ihnen eine Nachricht mit Anweisungen schicken, wie ein Neues erstellt wird." +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." +msgstr "" +"Haben Sie Ihr Passwort vergessen? Geben Sie unten Ihre E-Mail Adresse ein " +"und wir werden Ihnen eine Nachricht mit Anweisungen schicken, wie ein Neues " +"erstellt wird." #: templates/xadmin/auth/password_reset/form.html:25 msgid "E-mail address:" @@ -641,8 +745,12 @@ msgid "Reset my password" msgstr "Passwort zurücksetzen" #: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." -msgstr "Bitte tragen Sie einen Benutzernamen und Passwort ein. Anschließend können Sie weitere Benutzerinformationen bearbeiten." +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." +msgstr "" +"Bitte tragen Sie einen Benutzernamen und Passwort ein. Anschließend können " +"Sie weitere Benutzerinformationen bearbeiten." #: templates/xadmin/auth/user/add_form.html:8 msgid "Enter a username and password." @@ -664,21 +772,36 @@ msgstr "Geben Sie Ihr neues Passwort ein." #: templates/xadmin/auth/user/change_password.html:40 #, python-format msgid "Enter a new password for the user %(username)s." -msgstr "Vergeben Sie ein neues Passwort für den Benutzer %(username)s." +msgstr "" +"Vergeben Sie ein neues Passwort für den Benutzer %(username)s." + +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "Willkommen," + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "Abmelden" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "Sie haben nicht die notwendige Berechtigung etwas zu ändern." #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "Themeneinstellungen" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "Suchen" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "Hinzufügen" @@ -696,7 +819,7 @@ msgstr "Nächstes" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "Speichern" @@ -742,8 +865,8 @@ msgstr "Klicken Sie hier, um alle Objekte über alle Seiten hinweg auszuwählen. #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" -msgstr "Alles auswählen %(total_count)s %(module_name)s" +msgid "Select all %(total_count)s %(model_name)s" +msgstr "Alles auswählen %(total_count)s %(model_name)s" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 msgid "Clear selection" @@ -756,26 +879,27 @@ msgstr "Diagramme" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:47 msgid "Export" msgstr "Exportieren" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 msgid "Export with table header." msgstr "Export mit Tabellenkopf." -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:38 msgid "Export with format." msgstr "Exportieren mit Formatierung." -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:42 msgid "Export all data." msgstr "Komplette Daten exportieren." -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:46 +#: templates/xadmin/widgets/base.html:41 msgid "Close" msgstr "Schließen" @@ -792,8 +916,12 @@ msgstr "Säubern" msgid "Every %(t)s seconds" msgstr "Alle %(t)s Sekunden" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "Null" @@ -831,7 +959,7 @@ msgstr "Tag" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "Anwenden" @@ -852,7 +980,13 @@ msgstr "Von" msgid "To" msgstr "Bis" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +#, fuzzy +#| msgid "Select Date" +msgid "Select" +msgstr "Datum wählen" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "Entfernen" @@ -885,7 +1019,7 @@ msgid "Choose" msgstr "Wähle" #: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 +#: templates/xadmin/widgets/base.html:40 msgid "Remove" msgstr "Entferne" @@ -907,7 +1041,7 @@ msgstr "Alles anzeigen" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "Speichern..." @@ -924,7 +1058,7 @@ msgid "Save and continue editing" msgstr "Speichern und weiter bearbeiten" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "Löschen" @@ -955,7 +1089,10 @@ msgid "Add Widget" msgstr "Widget hinzufügen" #: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." msgstr "" #: templates/xadmin/views/logged_out.html:16 @@ -997,17 +1134,24 @@ msgstr "Bearbeiten" #: templates/xadmin/views/model_delete_confirm.html:11 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:19 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:27 #, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:34 @@ -1026,17 +1170,24 @@ msgstr "Mehrere Objekte löschen" #: templates/xadmin/views/model_delete_selected_confirm.html:18 #, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:26 #, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:34 #, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" msgstr "" #: templates/xadmin/views/model_history.html:26 @@ -1061,7 +1212,9 @@ msgid "Diff Select Versions" msgstr "" #: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." msgstr "" #: templates/xadmin/views/model_list.html:29 @@ -1088,7 +1241,8 @@ msgid "Press the recover button below to recover this version of the object." msgstr "" #: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." +msgid "" +"Choose a date from the list below to recover a deleted version of an object." msgstr "" #: templates/xadmin/views/recover_list.html:39 @@ -1147,127 +1301,154 @@ msgstr "" msgid "Quick Add" msgstr "Schnelles Hinzufügen" -#: templates/xadmin/widgets/base.html:30 +#: templates/xadmin/widgets/base.html:31 msgid "Widget Options" msgstr "Widget Optionen" -#: templates/xadmin/widgets/base.html:41 +#: templates/xadmin/widgets/base.html:42 msgid "Save changes" msgstr "Änderungen speichern" -#: views/base.py:430 +#: views/base.py:315 msgid "Django Xadmin" msgstr "Django Xadmin" -#: views/dashboard.py:185 +#: views/base.py:316 +msgid "my-company.inc" +msgstr "" + +#: views/dashboard.py:186 msgid "Widget ID" msgstr "Widget ID" -#: views/dashboard.py:186 +#: views/dashboard.py:187 msgid "Widget Title" msgstr "Widget Titel" -#: views/dashboard.py:248 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." msgstr "" -#: views/dashboard.py:251 +#: views/dashboard.py:255 msgid "Html Content" msgstr "Html Inhalt" -#: views/dashboard.py:314 +#: views/dashboard.py:318 msgid "Target Model" msgstr "Zielmodell" -#: views/dashboard.py:365 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." -msgstr "Schnellauswahlbutton Widget, zum schnellen Öffnen einer beliebigen Seite." +msgstr "" +"Schnellauswahlbutton Widget, zum schnellen Öffnen einer beliebigen Seite." -#: views/dashboard.py:367 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "Schnellauswahl Buttons" -#: views/dashboard.py:408 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "Beliebige Objektliste Widget." -#: views/dashboard.py:447 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "Fügen Sie ein beliebiges Modell Objekt Widget hinzu." -#: views/dashboard.py:481 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "Armaturentafel" -#: views/dashboard.py:622 +#: views/dashboard.py:633 #, python-format msgid "%s Dashboard" msgstr "%s Armaturentafel" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "" -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "Andere Felder" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "%s Einzelheiten" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, fuzzy, python-format +#| msgid "Change %s" +msgid "Changed %s." +msgstr "Ändern %s" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "%(name)s \"%(obj)s\" wurde erfolgreich hinzugefügt." -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "Sie können es trotzdem nochmals bearbeiten." -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "Sie können unten ein weiteres %s hinzufügen." -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "Ändern %s" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "" -#: views/form.py:164 +#: views/form.py:165 #, fuzzy, python-format msgid "The %s was changed successfully." msgstr "Passwort erfolgreich geändert." -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "Datenbankfehler" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "%s Liste" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "Aufsteigend sortieren" -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "Absteigend sortieren" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "Sortierung abbrechen" #: views/website.py:16 msgid "Main Dashboard" msgstr "Hauptübersicht" + +#: widgets.py:48 +msgid "Now" +msgstr "Jetzt" diff --git a/xadmin/locale/en/LC_MESSAGES/django.mo b/xadmin/locale/en/LC_MESSAGES/django.mo index 8b93a2104..46394b0a4 100644 Binary files a/xadmin/locale/en/LC_MESSAGES/django.mo and b/xadmin/locale/en/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/en/LC_MESSAGES/django.po b/xadmin/locale/en/LC_MESSAGES/django.po index df836c5f6..8f291d5b1 100644 --- a/xadmin/locale/en/LC_MESSAGES/django.po +++ b/xadmin/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: 2014-01-10 10:31+0800\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,52 +18,62 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=1;\n" -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "" -#: filters.py:158 plugins/export.py:117 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "" -#: filters.py:159 plugins/export.py:117 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "" -#: filters.py:173 +#: filters.py:175 msgid "Unknown" msgstr "" -#: filters.py:265 +#: filters.py:267 msgid "Any date" msgstr "" -#: filters.py:266 +#: filters.py:268 msgid "Has date" msgstr "" -#: filters.py:269 +#: filters.py:271 msgid "Has no date" msgstr "" -#: filters.py:272 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "" -#: filters.py:276 +#: filters.py:278 msgid "Past 7 days" msgstr "" -#: filters.py:280 +#: filters.py:282 msgid "This month" msgstr "" -#: filters.py:284 +#: filters.py:286 msgid "This year" msgstr "" #: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." msgstr "" #: forms.py:21 @@ -75,107 +85,161 @@ msgstr "" msgid "Your e-mail address is not your username. Try '%s' instead." msgstr "" -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "" -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "" -#: widgets.py:48 -msgid "Now" +#: models.py:142 +msgid "action time" +msgstr "" + +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" + +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +msgid "change message" +msgstr "" + +#: models.py:164 +msgid "log entry" +msgstr "" + +#: models.py:165 +msgid "log entries" msgstr "" -#: plugins/actions.py:54 +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, python-format +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "" + +#: models.py:180 +#, python-format +msgid "Deleted \"%(object)s.\"" +msgstr "" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, python-format +msgid "Batch delete %(count)d %(items)s." +msgstr "" + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "" -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" msgstr[0] "" msgstr[1] "" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "" -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." +#: plugins/actions.py:179 plugins/actions.py:189 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." msgstr "" #: plugins/aggregation.py:14 @@ -243,21 +307,21 @@ msgstr "" msgid "Permission Name" msgstr "" -#: plugins/auth.py:159 +#: plugins/auth.py:167 #, fuzzy msgid "Change Password" msgstr "Changed Password" -#: plugins/auth.py:189 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "" -#: plugins/auth.py:214 plugins/auth.py:246 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "" -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -272,7 +336,7 @@ msgstr "" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "" -#: plugins/batch.py:90 +#: plugins/batch.py:89 #, python-format msgid "Successfully change %(count)d %(items)s." msgstr "" @@ -282,19 +346,19 @@ msgstr "" msgid "Batch change %s" msgstr "" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 msgid "bookmark" msgstr "" -#: plugins/bookmark.py:173 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." msgstr "" -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "" -#: plugins/chart.py:49 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "" @@ -340,27 +404,27 @@ msgid_plural "%(count)s comments were successfully %(action)s." msgstr[0] "" msgstr[1] "" -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "" -#: plugins/editable.py:47 +#: plugins/editable.py:46 #, python-format msgid "Enter %s" msgstr "" -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "" -#: plugins/export.py:87 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "" -#: plugins/filters.py:125 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "" @@ -385,11 +449,11 @@ msgstr "" msgid "Change:" msgstr "" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "" @@ -397,20 +461,25 @@ msgstr "" msgid "Forgotten your password or username?" msgstr "" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "" -#: plugins/relfield.py:29 plugins/topnav.py:35 +#: plugins/relfield.py:29 plugins/topnav.py:38 #, python-format msgid "Search %s" msgstr "" +#: plugins/relfield.py:67 +#, python-format +msgid "Select %s" +msgstr "" + #: plugins/themes.py:47 msgid "Default" msgstr "" @@ -427,88 +496,92 @@ msgstr "" msgid "Bootstrap 2.x theme" msgstr "" -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "" -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "" -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "" -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "" -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "" -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "" -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "" -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." msgstr "" -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." msgstr "" -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "" @@ -516,9 +589,10 @@ msgstr "" msgid "We're sorry, but the requested page could not be found." msgstr "" -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -529,7 +603,7 @@ msgstr "" #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "" @@ -546,19 +620,9 @@ msgid "Server Error (500)" msgstr "" #: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "" - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "" - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." msgstr "" #: templates/xadmin/auth/password_reset/complete.html:11 @@ -579,7 +643,9 @@ msgid "Enter new password" msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:19 @@ -591,16 +657,22 @@ msgid "Password reset unsuccessful" msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." msgstr "" #: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." msgstr "" #: templates/xadmin/auth/password_reset/email.html:2 #, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." msgstr "" #: templates/xadmin/auth/password_reset/email.html:4 @@ -625,7 +697,9 @@ msgid "Password reset" msgstr "" #: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." msgstr "" #: templates/xadmin/auth/password_reset/form.html:25 @@ -637,7 +711,9 @@ msgid "Reset my password" msgstr "" #: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." msgstr "" #: templates/xadmin/auth/user/add_form.html:8 @@ -662,19 +738,32 @@ msgstr "" msgid "Enter a new password for the user %(username)s." msgstr "" +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "" + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "" + #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "" @@ -692,7 +781,7 @@ msgstr "" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "" @@ -738,7 +827,7 @@ msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" +msgid "Select all %(total_count)s %(model_name)s" msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 @@ -752,26 +841,27 @@ msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:47 msgid "Export" msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 msgid "Export with table header." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:38 msgid "Export with format." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:42 msgid "Export all data." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:46 +#: templates/xadmin/widgets/base.html:41 msgid "Close" msgstr "" @@ -788,8 +878,12 @@ msgstr "" msgid "Every %(t)s seconds" msgstr "" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "" @@ -827,7 +921,7 @@ msgstr "" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "" @@ -848,7 +942,11 @@ msgstr "" msgid "To" msgstr "" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +msgid "Select" +msgstr "" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "" @@ -881,7 +979,7 @@ msgid "Choose" msgstr "" #: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 +#: templates/xadmin/widgets/base.html:40 msgid "Remove" msgstr "" @@ -903,7 +1001,7 @@ msgstr "" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "" @@ -920,7 +1018,7 @@ msgid "Save and continue editing" msgstr "" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "" @@ -951,7 +1049,10 @@ msgid "Add Widget" msgstr "" #: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." msgstr "" #: templates/xadmin/views/logged_out.html:16 @@ -993,17 +1094,24 @@ msgstr "" #: templates/xadmin/views/model_delete_confirm.html:11 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:19 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:27 #, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:34 @@ -1022,17 +1130,24 @@ msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:18 #, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:26 #, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:34 #, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" msgstr "" #: templates/xadmin/views/model_history.html:26 @@ -1057,7 +1172,9 @@ msgid "Diff Select Versions" msgstr "" #: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." msgstr "" #: templates/xadmin/views/model_list.html:29 @@ -1083,7 +1200,8 @@ msgid "Press the recover button below to recover this version of the object." msgstr "" #: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." +msgid "" +"Choose a date from the list below to recover a deleted version of an object." msgstr "" #: templates/xadmin/views/recover_list.html:39 @@ -1142,127 +1260,152 @@ msgstr "" msgid "Quick Add" msgstr "" -#: templates/xadmin/widgets/base.html:30 +#: templates/xadmin/widgets/base.html:31 msgid "Widget Options" msgstr "" -#: templates/xadmin/widgets/base.html:41 +#: templates/xadmin/widgets/base.html:42 msgid "Save changes" msgstr "" -#: views/base.py:430 +#: views/base.py:315 msgid "Django Xadmin" msgstr "" -#: views/dashboard.py:185 -msgid "Widget ID" +#: views/base.py:316 +msgid "my-company.inc" msgstr "" #: views/dashboard.py:186 +msgid "Widget ID" +msgstr "" + +#: views/dashboard.py:187 msgid "Widget Title" msgstr "" -#: views/dashboard.py:248 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." msgstr "" -#: views/dashboard.py:251 +#: views/dashboard.py:255 msgid "Html Content" msgstr "" -#: views/dashboard.py:314 +#: views/dashboard.py:318 msgid "Target Model" msgstr "" -#: views/dashboard.py:365 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." msgstr "" -#: views/dashboard.py:367 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "" -#: views/dashboard.py:408 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "" -#: views/dashboard.py:447 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "" -#: views/dashboard.py:481 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "" -#: views/dashboard.py:622 +#: views/dashboard.py:633 #, python-format msgid "%s Dashboard" msgstr "" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "" -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, fuzzy, python-format +msgid "Changed %s." +msgstr "Changed Password" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "" -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "" -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "" -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "" -#: views/form.py:164 +#: views/form.py:165 #, python-format msgid "The %s was changed successfully." msgstr "" -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "" -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "" #: views/website.py:16 msgid "Main Dashboard" msgstr "" + +#: widgets.py:48 +msgid "Now" +msgstr "" diff --git a/xadmin/locale/es_MX/LC_MESSAGES/django.mo b/xadmin/locale/es_MX/LC_MESSAGES/django.mo index af31b6018..4044840c1 100644 Binary files a/xadmin/locale/es_MX/LC_MESSAGES/django.mo and b/xadmin/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/es_MX/LC_MESSAGES/django.po b/xadmin/locale/es_MX/LC_MESSAGES/django.po index fe3fab7e2..62ed01107 100644 --- a/xadmin/locale/es_MX/LC_MESSAGES/django.po +++ b/xadmin/locale/es_MX/LC_MESSAGES/django.po @@ -14,65 +14,78 @@ msgid "" msgstr "" "Project-Id-Version: xadmin-core\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-10 10:31+0800\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: 2013-05-12 18:45+0000\n" "Last-Translator: sacrac \n" -"Language-Team: Spanish (Mexico) (http://www.transifex.com/projects/p/xadmin/language/es_MX/)\n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/projects/p/xadmin/" +"language/es_MX/)\n" "Language: es_MX\n" "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" -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "Todo" -#: filters.py:158 plugins/export.py:117 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "Sí" -#: filters.py:159 plugins/export.py:117 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "No" -#: filters.py:173 +#: filters.py:175 msgid "Unknown" msgstr "Desconocido" -#: filters.py:265 +#: filters.py:267 msgid "Any date" msgstr "Cualquier fecha" -#: filters.py:266 +#: filters.py:268 #, fuzzy msgid "Has date" msgstr "Cualquier fecha" -#: filters.py:269 +#: filters.py:271 #, fuzzy msgid "Has no date" msgstr "Cualquier fecha" -#: filters.py:272 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "Hoy" -#: filters.py:276 +#: filters.py:278 msgid "Past 7 days" msgstr "Pasados ​​7 días" -#: filters.py:280 +#: filters.py:282 msgid "This month" msgstr "Este mes" -#: filters.py:284 +#: filters.py:286 msgid "This year" msgstr "Este año" #: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." -msgstr "Por favor, introduzca el nombre de usuario y contraseña correctos de su cuenta. Note que ambos campos son sensibles a mayúsculas y minúsculas." +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." +msgstr "" +"Por favor, introduzca el nombre de usuario y contraseña correctos de su " +"cuenta. Note que ambos campos son sensibles a mayúsculas y minúsculas." #: forms.py:21 msgid "Please log in again, because your session has expired." @@ -81,110 +94,175 @@ msgstr "Por favor, ingrese de nuevo, debido a que su sesión ha caducado." #: forms.py:41 #, python-format msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "Tu dirección de correo no es tu nombre de usuario. Prueba '%s' nuevamente." +msgstr "" +"Tu dirección de correo no es tu nombre de usuario. Prueba '%s' nuevamente." -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "Titulo" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "Nombre de Url" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "Cadena de consulta" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "Es compartido" -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "Marcador" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "Marcadores" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "Configuración llave" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "Configuración de contenidos" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "Configuración del usuario" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "Configuraciones de los usuarios" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "Página" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "Tipo de Widget" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "Parametros del Widget" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "Widget del Usuario" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "Widgets del Usuario" -#: widgets.py:48 -msgid "Now" -msgstr "Ahora" +#: models.py:142 +#, fuzzy +#| msgid "Date/time" +msgid "action time" +msgstr "Fecha/hora" + +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" + +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +#, fuzzy +#| msgid "Change %s" +msgid "change message" +msgstr "Cambiar %s" + +#: models.py:164 +#, fuzzy +#| msgid "log in" +msgid "log entry" +msgstr "Iniciar sesión" + +#: models.py:165 +msgid "log entries" +msgstr "" + +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, fuzzy, python-format +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "Cambiar multiples objetos" -#: plugins/actions.py:54 +#: models.py:180 +#, fuzzy, python-format +#| msgid "Related Objects" +msgid "Deleted \"%(object)s.\"" +msgstr "Objetos relacionados" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "Borrar selección %(verbose_name_plural)s" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, fuzzy, python-format +#| msgid "Successfully deleted %(count)d %(items)s." +msgid "Batch delete %(count)d %(items)s." +msgstr "Correctamente eliminado %(count)d %(items)s." + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "Correctamente eliminado %(count)d %(items)s." -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "No se puede eliminar %(name)s" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "Esta seguro?" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" msgstr[0] "%(total_count)s seleccionados" msgstr[1] "Todos los %(total_count)s seleccionados" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "0 de %(cnt)s seleccionado" -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." -msgstr "Los articulos deben de ser seleccionados en orden para realizar la acción. No existen artículos que han cambiado" +#: plugins/actions.py:179 plugins/actions.py:189 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Los articulos deben de ser seleccionados en orden para realizar la acción. " +"No existen artículos que han cambiado" #: plugins/aggregation.py:14 msgid "Min" @@ -252,21 +330,21 @@ msgstr "Estados" msgid "Permission Name" msgstr "Permisos" -#: plugins/auth.py:159 +#: plugins/auth.py:167 #, fuzzy msgid "Change Password" msgstr "Cambiar Contraseña" -#: plugins/auth.py:189 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "Cambiar contraseña: %s" -#: plugins/auth.py:214 plugins/auth.py:246 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "Contraseña cambiada correctamente" -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -282,7 +360,7 @@ msgstr "Historial de cambios: %s" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "Cambio de grupo seleccionado %(verbose_name_plural)s" -#: plugins/batch.py:90 +#: plugins/batch.py:89 #, fuzzy, python-format msgid "Successfully change %(count)d %(items)s." msgstr "Correctamente eliminado %(count)d %(items)s." @@ -292,20 +370,22 @@ msgstr "Correctamente eliminado %(count)d %(items)s." msgid "Batch change %s" msgstr "Cambiar %s" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 #, fuzzy msgid "bookmark" msgstr "Marcador" -#: plugins/bookmark.py:173 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." -msgstr "Widget de marcador, puede mostrar datos de la lista de favoritos del usuario en el widget." +msgstr "" +"Widget de marcador, puede mostrar datos de la lista de favoritos del usuario " +"en el widget." -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "Mostrar simple grafos para los modelos" -#: plugins/chart.py:49 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "%s Graficos" @@ -353,27 +433,27 @@ msgid_plural "%(count)s comments were successfully %(action)s." msgstr[0] "" msgstr[1] "" -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "Detalles de %s" -#: plugins/editable.py:47 +#: plugins/editable.py:46 #, python-format msgid "Enter %s" msgstr "Entre %s" -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "%(name)s el objeto con la llave primaria %(key)r no existe." -#: plugins/export.py:87 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "Hoja" -#: plugins/filters.py:125 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "" @@ -398,11 +478,11 @@ msgstr "Descargar" msgid "Change:" msgstr "Cambiar:" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "" @@ -410,20 +490,26 @@ msgstr "" msgid "Forgotten your password or username?" msgstr "¿Olvidó su contraseña o nombre de usuario?" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "Objetos relacionados" -#: plugins/relfield.py:29 plugins/topnav.py:35 +#: plugins/relfield.py:29 plugins/topnav.py:38 #, python-format msgid "Search %s" msgstr "Buscar %s" +#: plugins/relfield.py:67 +#, fuzzy, python-format +#| msgid "Select Date" +msgid "Select %s" +msgstr "Seleccionar Fecha" + #: plugins/themes.py:47 #, fuzzy msgid "Default" @@ -443,88 +529,96 @@ msgstr "" msgid "Bootstrap 2.x theme" msgstr "Tema bootstrap por defecto" -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "Añadir %s" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "Versión inicial." -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "Cambiar la versión." -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "Revertir la versión." -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "Recuperar versión" -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "Borrado %(verbose_name)s." -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "Recuperar" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "Historico" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "Recuperar borrado %(name)s" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "Historial de cambios: %s" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "Debe seleccionar dos versiones." -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "Por favor seleccione dos versiones diferente." -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "Actual: %s" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "Revertir %s" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." -msgstr "El %(model)s \"%(name)s\" se revirtió con éxito. Puede editarlo de nuevo a continuación." +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." +msgstr "" +"El %(model)s \"%(name)s\" se revirtió con éxito. Puede editarlo de nuevo a " +"continuación." -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "Recuperar %s" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." -msgstr "El %(model)s \"%(name) s\" se recuperó con éxito. Puede editarlo de nuevo a continuación." +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." +msgstr "" +"El %(model)s \"%(name) s\" se recuperó con éxito. Puede editarlo de nuevo a " +"continuación." -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "Pagina no encontrada" @@ -532,9 +626,10 @@ msgstr "Pagina no encontrada" msgid "We're sorry, but the requested page could not be found." msgstr "Lo sentimos pero la pagina que usted solicita no se encuentra." -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -545,7 +640,7 @@ msgstr "Lo sentimos pero la pagina que usted solicita no se encuentra." #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "Inicio" @@ -562,20 +657,13 @@ msgid "Server Error (500)" msgstr "Error en el servidor (500)" #: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "Ha habido un error. Se nos ha informado a los administradores del sitio a través de un correo electrónico y debe repararse en la breve. Gracias por su paciencia." - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "Bienvenidos," - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "Salir" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." -msgstr "No tiene permiso para editar nada. " +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." +msgstr "" +"Ha habido un error. Se nos ha informado a los administradores del sitio a " +"través de un correo electrónico y debe repararse en la breve. Gracias por su " +"paciencia." #: templates/xadmin/auth/password_reset/complete.html:11 #: templates/xadmin/auth/password_reset/done.html:11 @@ -595,8 +683,12 @@ msgid "Enter new password" msgstr "Escriba la nueva contraseña" #: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." -msgstr "Introduzca su nueva contraseña dos veces para que podamos verificar que la ha escrito correctamente." +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." +msgstr "" +"Introduzca su nueva contraseña dos veces para que podamos verificar que la " +"ha escrito correctamente." #: templates/xadmin/auth/password_reset/confirm.html:19 msgid "Change my password" @@ -607,17 +699,31 @@ msgid "Password reset unsuccessful" msgstr "Restablecimiento de contraseña sin éxito" #: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." -msgstr "El enlace de restablecimiento de contraseña no es válida, posiblemente debido a que ya se ha utilizado. Por favor, solicite un nuevo restablecimiento de contraseña." +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." +msgstr "" +"El enlace de restablecimiento de contraseña no es válida, posiblemente " +"debido a que ya se ha utilizado. Por favor, solicite un nuevo " +"restablecimiento de contraseña." #: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." -msgstr "Nosotro te hemos enviado por correo electrónico las instrucciones para configurar la contraseña a la dirección de correo electrónico que ha enviado. Usted debe recibirlo en breve momento." +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." +msgstr "" +"Nosotro te hemos enviado por correo electrónico las instrucciones para " +"configurar la contraseña a la dirección de correo electrónico que ha " +"enviado. Usted debe recibirlo en breve momento." #: templates/xadmin/auth/password_reset/email.html:2 #, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." -msgstr "Tu has recibido este correo debido a que has solicitado restablecimiento de contraseña para tu cuenta de usuario en %(site_name)s." +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." +msgstr "" +"Tu has recibido este correo debido a que has solicitado restablecimiento de " +"contraseña para tu cuenta de usuario en %(site_name)s." #: templates/xadmin/auth/password_reset/email.html:4 msgid "Please go to the following page and choose a new password:" @@ -641,8 +747,12 @@ msgid "Password reset" msgstr "restablecimiento de contraseña" #: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." -msgstr "¿Olvidaste tu contraseña? Escribe tu dirección de e-mail debajo, y le enviaremos un e-mail para el establecimiento de una nueva." +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." +msgstr "" +"¿Olvidaste tu contraseña? Escribe tu dirección de e-mail debajo, y le " +"enviaremos un e-mail para el establecimiento de una nueva." #: templates/xadmin/auth/password_reset/form.html:25 msgid "E-mail address:" @@ -653,8 +763,12 @@ msgid "Reset my password" msgstr "Cambiar contraseña" #: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." -msgstr "Primero, ingrese usuario y contraseña. Luego, sera capaz de editar mas opciones de usuario." +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." +msgstr "" +"Primero, ingrese usuario y contraseña. Luego, sera capaz de editar mas " +"opciones de usuario." #: templates/xadmin/auth/user/add_form.html:8 msgid "Enter a username and password." @@ -676,21 +790,35 @@ msgstr "Ingresa una nueva contraseña" #: templates/xadmin/auth/user/change_password.html:40 #, python-format msgid "Enter a new password for the user %(username)s." -msgstr "Introduzca una nueva contraseña para el usuario %(username)s" +msgstr "" +"Introduzca una nueva contraseña para el usuario %(username)s" + +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "Bienvenidos," + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "Salir" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "No tiene permiso para editar nada. " #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "Temas" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "Buscar" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "Agregar" @@ -708,7 +836,7 @@ msgstr "Próximo paso" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "Guardar" @@ -750,12 +878,13 @@ msgstr "Limpiar Filtros" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 msgid "Click here to select the objects across all pages" -msgstr "Haz clic aquí para seleccionar los objetos a través de todas las páginas" +msgstr "" +"Haz clic aquí para seleccionar los objetos a través de todas las páginas" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" -msgstr "Seleccionar todo %(total_count)s %(module_name)s" +msgid "Select all %(total_count)s %(model_name)s" +msgstr "Seleccionar todo %(total_count)s %(model_name)s" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 msgid "Clear selection" @@ -768,26 +897,27 @@ msgstr "Graficos" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:47 msgid "Export" msgstr "Exportar" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 msgid "Export with table header." msgstr "Exportar con la cabecera de la tabla." -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:38 msgid "Export with format." msgstr "Exportar con formato" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:42 msgid "Export all data." msgstr "Exportar todos los datos." -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:46 +#: templates/xadmin/widgets/base.html:41 msgid "Close" msgstr "Cerrar" @@ -804,8 +934,12 @@ msgstr "Limpiar Refrescar" msgid "Every %(t)s seconds" msgstr "Por %(t)s segundos" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "Nulo" @@ -843,7 +977,7 @@ msgstr "día" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "Aplicar" @@ -864,7 +998,13 @@ msgstr "De" msgid "To" msgstr "Para" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +#, fuzzy +#| msgid "Select Date" +msgid "Select" +msgstr "Seleccionar Fecha" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "Limpiar" @@ -897,7 +1037,7 @@ msgid "Choose" msgstr "Elegir" #: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 +#: templates/xadmin/widgets/base.html:40 msgid "Remove" msgstr "Eliminar" @@ -919,7 +1059,7 @@ msgstr "Mostrar todos" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "" @@ -936,7 +1076,7 @@ msgid "Save and continue editing" msgstr "Guardar y continuar editando" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "Borrar" @@ -967,8 +1107,14 @@ msgid "Add Widget" msgstr "Añadir Widget" #: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." -msgstr "Algo está mal con tu instalación de base de datos. Asegúrese de que las tablas de la bases de datos se han creado apropiadamente, y asegúrese de que la base de datos puede ser leído por el usuario apropiado" +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." +msgstr "" +"Algo está mal con tu instalación de base de datos. Asegúrese de que las " +"tablas de la bases de datos se han creado apropiadamente, y asegúrese de que " +"la base de datos puede ser leído por el usuario apropiado" #: templates/xadmin/views/logged_out.html:16 msgid "Logout Success" @@ -1011,18 +1157,32 @@ msgstr "Editar." #: templates/xadmin/views/model_delete_confirm.html:11 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" -msgstr "Eliminando los %(verbose_name)s '%(escaped_object)s terminaría eliminando objetos relacionados, pero su cuenta no tiene permisos para eliminar los siguientes tipo de objetos:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" +msgstr "" +"Eliminando los %(verbose_name)s '%(escaped_object)s terminaría eliminando " +"objetos relacionados, pero su cuenta no tiene permisos para eliminar los " +"siguientes tipo de objetos:" #: templates/xadmin/views/model_delete_confirm.html:19 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" -msgstr "Eliminando los %(verbose_name)s '%(escaped_object)s requeriría eliminar los siguientes objetos relacionas protegidos:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" +msgstr "" +"Eliminando los %(verbose_name)s '%(escaped_object)s requeriría eliminar los " +"siguientes objetos relacionas protegidos:" #: templates/xadmin/views/model_delete_confirm.html:27 #, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" -msgstr "¿Estas seguro de querer eliminar los %(verbose_name)s \"%(escaped_object)s\" ? Todos los siguientes artículos relacionados serán eliminados:" +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" +msgstr "" +"¿Estas seguro de querer eliminar los %(verbose_name)s \"%(escaped_object)s" +"\" ? Todos los siguientes artículos relacionados serán eliminados:" #: templates/xadmin/views/model_delete_confirm.html:34 #: templates/xadmin/views/model_delete_selected_confirm.html:49 @@ -1041,18 +1201,32 @@ msgstr "Eliminar múltiples objetos." #: templates/xadmin/views/model_delete_selected_confirm.html:18 #, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" -msgstr "Eliminando los %(objects_name)s terminaría eliminando objetos relacionados, pero su cuenta no tiene permisos para eliminar los siguientes tipo de objetos:" +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Eliminando los %(objects_name)s terminaría eliminando objetos relacionados, " +"pero su cuenta no tiene permisos para eliminar los siguientes tipo de " +"objetos:" #: templates/xadmin/views/model_delete_selected_confirm.html:26 #, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" -msgstr "Eliminando los %(objects_name)s seleccionados terminaria emilinando los siguientes objetos relacionados protegidos:" +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" +msgstr "" +"Eliminando los %(objects_name)s seleccionados terminaria emilinando los " +"siguientes objetos relacionados protegidos:" #: templates/xadmin/views/model_delete_selected_confirm.html:34 #, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" -msgstr "¿Estas seguro de querer borrar los %(objects_name)s seleccionados? Todos los siguientes objetos y sus artículos relacionados serán eliminados:" +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" +msgstr "" +"¿Estas seguro de querer borrar los %(objects_name)s seleccionados? Todos los " +"siguientes objetos y sus artículos relacionados serán eliminados:" #: templates/xadmin/views/model_history.html:26 msgid "Diff" @@ -1076,8 +1250,12 @@ msgid "Diff Select Versions" msgstr "Seleccionar diferentes versiones" #: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." -msgstr "Este objeto no tiene un historial de cambios, Es probable que no se haya añadido a través de este sitio de admin.|" +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." +msgstr "" +"Este objeto no tiene un historial de cambios, Es probable que no se haya " +"añadido a través de este sitio de admin.|" #: templates/xadmin/views/model_list.html:29 #, python-format @@ -1100,11 +1278,16 @@ msgstr "Lista vacia" #: templates/xadmin/views/recover_form.html:20 msgid "Press the recover button below to recover this version of the object." -msgstr "Presione el botón de recuperación abajo para recuperar esta versión del objeto." +msgstr "" +"Presione el botón de recuperación abajo para recuperar esta versión del " +"objeto." #: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." -msgstr "Selecciona una fecha de la lista de abajo para recuperar una versión eliminada de un objeto." +msgid "" +"Choose a date from the list below to recover a deleted version of an object." +msgstr "" +"Selecciona una fecha de la lista de abajo para recuperar una versión " +"eliminada de un objeto." #: templates/xadmin/views/recover_list.html:39 msgid "There are no deleted objects to recover." @@ -1144,7 +1327,8 @@ msgstr "Revertir %(verbose_name)s" #: templates/xadmin/views/revision_form.html:21 msgid "Press the revert button below to revert to this version of the object." -msgstr "Presiona el botón revertir de abajo para revertir a esta versión del objeto." +msgstr "" +"Presiona el botón revertir de abajo para revertir a esta versión del objeto." #: templates/xadmin/views/revision_form.html:27 msgid "Revert this revision" @@ -1156,130 +1340,154 @@ msgstr "Éxito" #: templates/xadmin/widgets/addform.html:14 msgid "Add success, click edit to edit." -msgstr "Agregado exitosa mente, presiona edit para editar." +msgstr "" +"Agregado exitosa mente, presiona edit para editar." #: templates/xadmin/widgets/addform.html:17 msgid "Quick Add" msgstr "Agregar rápidamente." -#: templates/xadmin/widgets/base.html:30 +#: templates/xadmin/widgets/base.html:31 msgid "Widget Options" msgstr "Opciones del Widget" -#: templates/xadmin/widgets/base.html:41 +#: templates/xadmin/widgets/base.html:42 msgid "Save changes" msgstr "Guardar cambios" -#: views/base.py:430 +#: views/base.py:315 msgid "Django Xadmin" msgstr "Django Xadmin" -#: views/dashboard.py:185 +#: views/base.py:316 +msgid "my-company.inc" +msgstr "" + +#: views/dashboard.py:186 msgid "Widget ID" msgstr "ID del Widget" -#: views/dashboard.py:186 +#: views/dashboard.py:187 msgid "Widget Title" msgstr "Titulo del Widget" -#: views/dashboard.py:248 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." -msgstr "Contenido html del Widget, puede escribir cualquier contenido del widget." +msgstr "" +"Contenido html del Widget, puede escribir cualquier contenido del widget." -#: views/dashboard.py:251 +#: views/dashboard.py:255 msgid "Html Content" msgstr "Contenido HTML" -#: views/dashboard.py:314 +#: views/dashboard.py:318 msgid "Target Model" msgstr "Modelo objeto" -#: views/dashboard.py:365 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." msgstr "botón rapido del widget, abrir rápidamente cualquier página." -#: views/dashboard.py:367 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "Botones rapidos" -#: views/dashboard.py:408 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "Cualquier objeto listado en el widget" -#: views/dashboard.py:447 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "Añadir cualquier modelo de objeto al Widget." -#: views/dashboard.py:481 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "Panel de control" -#: views/dashboard.py:622 +#: views/dashboard.py:633 #, fuzzy, python-format msgid "%s Dashboard" msgstr "Panel de control" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "El %(name)s \"%(obj)s\" fue eliminado exitosa mente." -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "Otros campos" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "%s Detalles" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, fuzzy, python-format +#| msgid "Change %s" +msgid "Changed %s." +msgstr "Cambiar %s" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "El %(name)s \"%(obj)s\" fue agregado exitosa mente." -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "Puedes editarlo de nuevo abajo." -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "Puedes agregar otro %s debajo." -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "Cambiar %s" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "El %(name)s \"%(obj)s\" fue editado exitosa mente." -#: views/form.py:164 +#: views/form.py:165 #, fuzzy, python-format msgid "The %s was changed successfully." msgstr "El %(name)s \"%(obj)s\" fue editado exitosa mente." -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "Error de base de datos" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "%s Lista" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "Ordenar ascendente mente." -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "Ordenar descendente mente" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "Cancelar ordenación" @@ -1287,6 +1495,10 @@ msgstr "Cancelar ordenación" msgid "Main Dashboard" msgstr "Dashboard principal." +#: widgets.py:48 +msgid "Now" +msgstr "Ahora" + #~ msgid "Add Other %s" #~ msgstr "Añadir otro %s" @@ -1305,8 +1517,13 @@ msgstr "Dashboard principal." #~ msgid "Your password was changed." #~ msgstr "Tu contraseña fue cambiada." -#~ msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." -#~ msgstr "Introduzca su antigua contraseña, por el bien de la seguridad, y luego ingrese su nueva contraseña dos veces para que podamos verificar que la ha escrito correctamente." +#~ msgid "" +#~ "Please enter your old password, for security's sake, and then enter your " +#~ "new password twice so we can verify you typed it in correctly." +#~ msgstr "" +#~ "Introduzca su antigua contraseña, por el bien de la seguridad, y luego " +#~ "ingrese su nueva contraseña dos veces para que podamos verificar que la " +#~ "ha escrito correctamente." #~ msgid "Old password" #~ msgstr "Vieja contraseña" diff --git a/xadmin/locale/eu/LC_MESSAGES/django.mo b/xadmin/locale/eu/LC_MESSAGES/django.mo index c785bc888..f6c51c6f2 100644 Binary files a/xadmin/locale/eu/LC_MESSAGES/django.mo and b/xadmin/locale/eu/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/eu/LC_MESSAGES/django.po b/xadmin/locale/eu/LC_MESSAGES/django.po index 352cbcd12..61f5e85f5 100644 --- a/xadmin/locale/eu/LC_MESSAGES/django.po +++ b/xadmin/locale/eu/LC_MESSAGES/django.po @@ -8,63 +8,76 @@ msgid "" msgstr "" "Project-Id-Version: xadmin-core\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-10 10:31+0800\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: 2013-11-20 10:21+0000\n" "Last-Translator: sshwsfc \n" -"Language-Team: Basque (http://www.transifex.com/projects/p/xadmin/language/eu/)\n" +"Language-Team: Basque (http://www.transifex.com/projects/p/xadmin/language/" +"eu/)\n" "Language: eu\n" "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" -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "Guztia" -#: filters.py:158 plugins/export.py:117 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "Bai" -#: filters.py:159 plugins/export.py:117 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "Ez" -#: filters.py:173 +#: filters.py:175 msgid "Unknown" msgstr "Ezezaguna" -#: filters.py:265 +#: filters.py:267 msgid "Any date" msgstr "Edozein data" -#: filters.py:266 +#: filters.py:268 msgid "Has date" msgstr "" -#: filters.py:269 +#: filters.py:271 msgid "Has no date" msgstr "" -#: filters.py:272 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "Gaur" -#: filters.py:276 +#: filters.py:278 msgid "Past 7 days" msgstr "Duela 7 egun" -#: filters.py:280 +#: filters.py:282 msgid "This month" msgstr "Hilabete hau" -#: filters.py:284 +#: filters.py:286 msgid "This year" msgstr "Urte hau" #: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." -msgstr "Mesedez sartu langile kontu baten erabiltzaile eta pasahitz egokiak. Kontuan hartu bi eremuek maiuskula eta minuskulak bereizten dituztela." +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." +msgstr "" +"Mesedez sartu langile kontu baten erabiltzaile eta pasahitz egokiak. Kontuan " +"hartu bi eremuek maiuskula eta minuskulak bereizten dituztela." #: forms.py:21 msgid "Please log in again, because your session has expired." @@ -73,110 +86,176 @@ msgstr "Mesedez hasi berriro saioa, zure uneko saioa iraungi da eta." #: forms.py:41 #, python-format msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "Zure e-posta helbidea ez da zure erabiltzaile izena. Horren ordez saiatu '%s'." +msgstr "" +"Zure e-posta helbidea ez da zure erabiltzaile izena. Horren ordez saiatu " +"'%s'." -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "Izenburua" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "Url Izena" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "Kontsulta Katea" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "Partekatua da." -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "Laster-marketara gehitu" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "Laster-markak" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "Ezarpenen Gakoa" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "Ezarpenen Edukia" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "Erabiltzaile Ezarpenak" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "Erabiltzaile Ezarpenak" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "Orrialdea" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "Widget Mota" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "Widget Parametroak" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "Erabiltzaile Widgeta" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "Erabiltzaile Widgetak" -#: widgets.py:48 -msgid "Now" -msgstr "Orain" +#: models.py:142 +#, fuzzy +#| msgid "Date/time" +msgid "action time" +msgstr "Data/ordua" -#: plugins/actions.py:54 +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" + +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +#, fuzzy +#| msgid "Change %s" +msgid "change message" +msgstr "Aldaketa %s" + +#: models.py:164 +#, fuzzy +#| msgid "log in" +msgid "log entry" +msgstr "hasi saioa" + +#: models.py:165 +msgid "log entries" +msgstr "" + +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, python-format +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "" + +#: models.py:180 +#, fuzzy, python-format +#| msgid "Related Objects" +msgid "Deleted \"%(object)s.\"" +msgstr "Erlazionatutako Objetuak" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "Aukeratutako %(verbose_name_plural)s ezabatu" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, fuzzy, python-format +#| msgid "Successfully deleted %(count)d %(items)s." +msgid "Batch delete %(count)d %(items)s." +msgstr "Aukeratutako %(count)d %(items)s arrakastaz ezabatuak." + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "Aukeratutako %(count)d %(items)s arrakastaz ezabatuak." -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "Ezin izan da %(name)s ezabatu" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "Ziur al zaude?" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" msgstr[0] "%(total_count)s aukeratua" msgstr[1] "%(total_count)s guztiak aukeratuak" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "%(cnt)stik 0 aukeratuak" -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." -msgstr "Elementuren bat aukeratzea beharrezkoa da ekintza bat burutzeko. Ez da elementurik aldatu." +#: plugins/actions.py:179 plugins/actions.py:189 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Elementuren bat aukeratzea beharrezkoa da ekintza bat burutzeko. Ez da " +"elementurik aldatu." #: plugins/aggregation.py:14 msgid "Min" @@ -244,20 +323,20 @@ msgstr "Egoera" msgid "Permission Name" msgstr "Baimenak" -#: plugins/auth.py:159 +#: plugins/auth.py:167 msgid "Change Password" msgstr "Pasahitza Aldatu" -#: plugins/auth.py:189 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "Pasahitza aldatu: %s" -#: plugins/auth.py:214 plugins/auth.py:246 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "Pasahitza arrakastaz aldatua." -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -272,7 +351,7 @@ msgstr "" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "Sorta moduko Aldaketa aukeratua %(verbose_name_plural)s" -#: plugins/batch.py:90 +#: plugins/batch.py:89 #, python-format msgid "Successfully change %(count)d %(items)s." msgstr "" @@ -282,19 +361,21 @@ msgstr "" msgid "Batch change %s" msgstr "" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 msgid "bookmark" msgstr "" -#: plugins/bookmark.py:173 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." -msgstr "Laster-marken Widgeta, erabiltzailearen laster-marka zerrenda widgetean erakutsi dezake." +msgstr "" +"Laster-marken Widgeta, erabiltzailearen laster-marka zerrenda widgetean " +"erakutsi dezake." -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "Erabili modeluen diagrama sinplea." -#: plugins/chart.py:49 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "%s Diagrama" @@ -342,27 +423,27 @@ msgid_plural "%(count)s comments were successfully %(action)s." msgstr[0] "" msgstr[1] "" -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "%sren xehetasunak" -#: plugins/editable.py:47 +#: plugins/editable.py:46 #, python-format msgid "Enter %s" msgstr "Sartu %s" -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "Ez da %(key)r eremua nagusitzat duen %(name)srik." -#: plugins/export.py:87 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "Xafla" -#: plugins/filters.py:125 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "" @@ -387,11 +468,11 @@ msgstr "Deskargatu" msgid "Change:" msgstr "Aldatu:" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "" @@ -399,20 +480,26 @@ msgstr "" msgid "Forgotten your password or username?" msgstr "Zure pasahitza edo erabiltzailea ahaztu duzu?" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "Erlazionatutako Objetuak" -#: plugins/relfield.py:29 plugins/topnav.py:35 +#: plugins/relfield.py:29 plugins/topnav.py:38 #, python-format msgid "Search %s" msgstr "Bilatu %s" +#: plugins/relfield.py:67 +#, fuzzy, python-format +#| msgid "Select Date" +msgid "Select %s" +msgstr "Data Aukeratu" + #: plugins/themes.py:47 msgid "Default" msgstr "" @@ -429,88 +516,96 @@ msgstr "" msgid "Bootstrap 2.x theme" msgstr "" -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "%s gehitu" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "Hasierako bertsioa." -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "Bertsioa aldatu." -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "Aurreko bertsiora itzuli." -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "Bertsioa berreskuratu." -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "%(verbose_name)s ezabatua." -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "Berreskuratu" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "Historiala" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "Ezabatutako %(name)sa berreskuratu" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "Historiala aldatu: %s" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "Bi bertsio aukeratu behar dira." -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "Mesedez aukeratu bi bertsio ezberdin." -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "Unekoa: %s" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "%s aurreko bertsiora itzuli" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." -msgstr "\"%(name)s\" %(model)sa aurreko bertsiora arrakastaz itzularazi da. Azpian berriro editatu dezakezu." +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." +msgstr "" +"\"%(name)s\" %(model)sa aurreko bertsiora arrakastaz itzularazi da. Azpian " +"berriro editatu dezakezu." -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "%s berreskuratu" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." -msgstr "\"%(name)s\" %(model)sa arrakastaz berreskuratu da. Azpian berriro editatu dezakezu." +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." +msgstr "" +"\"%(name)s\" %(model)sa arrakastaz berreskuratu da. Azpian berriro editatu " +"dezakezu." -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "Orria ez da aurkitu" @@ -518,9 +613,10 @@ msgstr "Orria ez da aurkitu" msgid "We're sorry, but the requested page could not be found." msgstr "Sentitzen dugu baina eskatutako orria ezin izan da aurkitu." -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -531,7 +627,7 @@ msgstr "Sentitzen dugu baina eskatutako orria ezin izan da aurkitu." #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "Hasiera" @@ -548,20 +644,12 @@ msgid "Server Error (500)" msgstr "Zerbitzariaren errorea " #: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "Errore bat egon da. Eposta bidez bidali zaio webgunearen kudeatzaileari eta laister konpondu beharko litzake. Milesker zure pazientziagatik." - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "Ongietorri," - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "Saioa amaitu" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." -msgstr "Ez daukazu ezer editatzeko baimenik." +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." +msgstr "" +"Errore bat egon da. Eposta bidez bidali zaio webgunearen kudeatzaileari eta " +"laister konpondu beharko litzake. Milesker zure pazientziagatik." #: templates/xadmin/auth/password_reset/complete.html:11 #: templates/xadmin/auth/password_reset/done.html:11 @@ -581,8 +669,11 @@ msgid "Enter new password" msgstr "Pasahitz berria idatzi" #: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." -msgstr "Mesedez idatzi zure pasahitz berria bi aldiz ongi idatzi duzun egiaztatzeko." +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." +msgstr "" +"Mesedez idatzi zure pasahitz berria bi aldiz ongi idatzi duzun egiaztatzeko." #: templates/xadmin/auth/password_reset/confirm.html:19 msgid "Change my password" @@ -593,17 +684,29 @@ msgid "Password reset unsuccessful" msgstr "Pasahitzaren berrezartzea gaizki joan da" #: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." -msgstr "Pasahitzaren berrezartze esteka baliogabea zen, ziur aski iadanik erabilia izan delak. Mesedez, eskatu pasahitzaren berrezartze berri bat." +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." +msgstr "" +"Pasahitzaren berrezartze esteka baliogabea zen, ziur aski iadanik erabilia " +"izan delak. Mesedez, eskatu pasahitzaren berrezartze berri bat." #: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." -msgstr "Eposta biez zure pasahitza ezartzeko argibideak bidali dizkizugu eman diguzun eposta helbidera. Laister jaso beharko zenituzke." +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." +msgstr "" +"Eposta biez zure pasahitza ezartzeko argibideak bidali dizkizugu eman " +"diguzun eposta helbidera. Laister jaso beharko zenituzke." #: templates/xadmin/auth/password_reset/email.html:2 #, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." -msgstr "%(site_name)sen zure erabiltzailearen pasahitzaren berrezarpen bat eskatu duzulako ari zera eposta hau jasotzen." +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." +msgstr "" +"%(site_name)sen zure erabiltzailearen pasahitzaren berrezarpen bat eskatu " +"duzulako ari zera eposta hau jasotzen." #: templates/xadmin/auth/password_reset/email.html:4 msgid "Please go to the following page and choose a new password:" @@ -627,8 +730,12 @@ msgid "Password reset" msgstr "Pasahitza berrezarri" #: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." -msgstr "Pasahitza ahaztu duzu? Idatzi zure eposta helbidea behean eta berri bat ezartzeko argibideak bidaliko dizkizugu." +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." +msgstr "" +"Pasahitza ahaztu duzu? Idatzi zure eposta helbidea behean eta berri bat " +"ezartzeko argibideak bidaliko dizkizugu." #: templates/xadmin/auth/password_reset/form.html:25 msgid "E-mail address:" @@ -639,8 +746,12 @@ msgid "Reset my password" msgstr "Nire pasahitza berrezarri" #: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." -msgstr "Lehendabizi, erabiltzaile eta pasahitz bat sartu. Ondoren, erabiltzaile aukera gehiago editatzeko gai izango zara." +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." +msgstr "" +"Lehendabizi, erabiltzaile eta pasahitz bat sartu. Ondoren, erabiltzaile " +"aukera gehiago editatzeko gai izango zara." #: templates/xadmin/auth/user/add_form.html:8 msgid "Enter a username and password." @@ -662,21 +773,35 @@ msgstr "Zure pasahitz berria sartu." #: templates/xadmin/auth/user/change_password.html:40 #, python-format msgid "Enter a new password for the user %(username)s." -msgstr "%(username)s erabiltzailearentzat pasahitz berri bat sartu." +msgstr "" +"%(username)s erabiltzailearentzat pasahitz berri bat sartu." + +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "Ongietorri," + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "Saioa amaitu" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "Ez daukazu ezer editatzeko baimenik." #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "Itsura-gaiak" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "Bilatu" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "Gehitu" @@ -694,7 +819,7 @@ msgstr "Ondo pausua" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "Gorde" @@ -740,8 +865,8 @@ msgstr "Klikatu hemen orrialde guztiko objetuak aukeratzeko" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" -msgstr "Aukeratu %(total_count)s %(module_name)sak" +msgid "Select all %(total_count)s %(model_name)s" +msgstr "Aukeratu %(total_count)s %(model_name)sak" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 msgid "Clear selection" @@ -754,26 +879,27 @@ msgstr "Diagramak" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:47 msgid "Export" msgstr "Esportatu" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 msgid "Export with table header." msgstr "Esportatu taularen goiburuarekin." -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:38 msgid "Export with format." msgstr "Formatuarekin esportatu." -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:42 msgid "Export all data." msgstr "Data guztiak esportatu." -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:46 +#: templates/xadmin/widgets/base.html:41 msgid "Close" msgstr "Itxi" @@ -790,8 +916,12 @@ msgstr "Garbitu Freskatzea" msgid "Every %(t)s seconds" msgstr "" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "Null" @@ -829,7 +959,7 @@ msgstr "eguna" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "Aplikatu" @@ -850,7 +980,13 @@ msgstr "Nork" msgid "To" msgstr "Nori" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +#, fuzzy +#| msgid "Select Date" +msgid "Select" +msgstr "Data Aukeratu" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "Garbitu" @@ -883,7 +1019,7 @@ msgid "Choose" msgstr "Aukeratu" #: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 +#: templates/xadmin/widgets/base.html:40 msgid "Remove" msgstr "Ezabatu" @@ -905,7 +1041,7 @@ msgstr "Guztia erakutsi" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "" @@ -922,7 +1058,7 @@ msgid "Save and continue editing" msgstr "Gorde eta editatzen jarraitu" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "Ezabatu" @@ -953,8 +1089,14 @@ msgid "Add Widget" msgstr "Widgeta Gehitu" #: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." -msgstr "Zerbait txarto dago zure datubasearen instalazioarekin. Ziurtatu beharrezko datubase taulak sortuak izan direla eta datubasea erabiltzaile egokiak irakurri dezakela." +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." +msgstr "" +"Zerbait txarto dago zure datubasearen instalazioarekin. Ziurtatu beharrezko " +"datubase taulak sortuak izan direla eta datubasea erabiltzaile egokiak " +"irakurri dezakela." #: templates/xadmin/views/logged_out.html:16 msgid "Logout Success" @@ -995,18 +1137,32 @@ msgstr "Editatu" #: templates/xadmin/views/model_delete_confirm.html:11 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" -msgstr "'%(escaped_object)s' %(verbose_name)sa ezabatzeak erlazionatutako beste objetu batzuk ezabatuzko lituzke baina zure kontuak ez dauzka ondorengo objetu motak ezabatzeko baimenik:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" +msgstr "" +"'%(escaped_object)s' %(verbose_name)sa ezabatzeak erlazionatutako beste " +"objetu batzuk ezabatuzko lituzke baina zure kontuak ez dauzka ondorengo " +"objetu motak ezabatzeko baimenik:" #: templates/xadmin/views/model_delete_confirm.html:19 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" -msgstr "'%(escaped_object)s' %(verbose_name)sa ezabatzeak ondorengo babestutako erlazionatutako objetuak ezabatuko lituzke:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" +msgstr "" +"'%(escaped_object)s' %(verbose_name)sa ezabatzeak ondorengo babestutako " +"erlazionatutako objetuak ezabatuko lituzke:" #: templates/xadmin/views/model_delete_confirm.html:27 #, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" -msgstr "Ziur al zaude \"%(escaped_object)s\" %(verbose_name)sa ezabatu nahi duzula? Ondorengo erlazionatutako objetuak ezabatuko lirateke:" +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" +msgstr "" +"Ziur al zaude \"%(escaped_object)s\" %(verbose_name)sa ezabatu nahi duzula? " +"Ondorengo erlazionatutako objetuak ezabatuko lirateke:" #: templates/xadmin/views/model_delete_confirm.html:34 #: templates/xadmin/views/model_delete_selected_confirm.html:49 @@ -1024,18 +1180,32 @@ msgstr "Bizpahiru objetu ezabatu" #: templates/xadmin/views/model_delete_selected_confirm.html:18 #, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" -msgstr "Aukeratutako %(objects_name)s objetua ezabatzeak erlazionatutako objetuak ezabatuko lituzke, baina zure kontuak ez dauzka ondorengo objetu motak ezabatzeko baimenik:" +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Aukeratutako %(objects_name)s objetua ezabatzeak erlazionatutako objetuak " +"ezabatuko lituzke, baina zure kontuak ez dauzka ondorengo objetu motak " +"ezabatzeko baimenik:" #: templates/xadmin/views/model_delete_selected_confirm.html:26 #, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" -msgstr "Aukeratutako %(objects_name)s objetua ezabatzeak ondorengo objetuak ezabatuko lituzke:" +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" +msgstr "" +"Aukeratutako %(objects_name)s objetua ezabatzeak ondorengo objetuak " +"ezabatuko lituzke:" #: templates/xadmin/views/model_delete_selected_confirm.html:34 #, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" -msgstr "Ziur zaude aukeratutako %(objects_name)s ezabatu nahi duzula? Ondorengo objetuak eta haiekin erlazionatuta daudenak ezabatuak izango dira:" +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" +msgstr "" +"Ziur zaude aukeratutako %(objects_name)s ezabatu nahi duzula? Ondorengo " +"objetuak eta haiekin erlazionatuta daudenak ezabatuak izango dira:" #: templates/xadmin/views/model_history.html:26 msgid "Diff" @@ -1059,8 +1229,12 @@ msgid "Diff Select Versions" msgstr "Aukeratutako Bertsioen Ezberdintasunak" #: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." -msgstr "Objetu honek ez dauka aldaketa historialik. Ziurrenik ez zen kudeaketa gune honen bitartez gehitua izango." +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." +msgstr "" +"Objetu honek ez dauka aldaketa historialik. Ziurrenik ez zen kudeaketa gune " +"honen bitartez gehitua izango." #: templates/xadmin/views/model_list.html:29 #, python-format @@ -1082,11 +1256,15 @@ msgstr "Zerrenda hustu" #: templates/xadmin/views/recover_form.html:20 msgid "Press the recover button below to recover this version of the object." -msgstr "Sakatu beheko berreskuratze botoia objetuaren bertsio hau berreskuratzeko." +msgstr "" +"Sakatu beheko berreskuratze botoia objetuaren bertsio hau berreskuratzeko." #: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." -msgstr "Aukeratu beheko zerrendatik data bat objetu baten ezabatutako bertsioa berreskuratzeko." +msgid "" +"Choose a date from the list below to recover a deleted version of an object." +msgstr "" +"Aukeratu beheko zerrendatik data bat objetu baten ezabatutako bertsioa " +"berreskuratzeko." #: templates/xadmin/views/recover_list.html:39 msgid "There are no deleted objects to recover." @@ -1138,133 +1316,160 @@ msgstr "Arrakasta" #: templates/xadmin/widgets/addform.html:14 msgid "Add success, click edit to edit." -msgstr "Gehitze arrakastatsua, klikatu editatu editatzeko." +msgstr "" +"Gehitze arrakastatsua, klikatu editatu editatzeko." #: templates/xadmin/widgets/addform.html:17 msgid "Quick Add" msgstr "Gehitze Azkarra" -#: templates/xadmin/widgets/base.html:30 +#: templates/xadmin/widgets/base.html:31 msgid "Widget Options" msgstr "Widget Aukerak" -#: templates/xadmin/widgets/base.html:41 +#: templates/xadmin/widgets/base.html:42 msgid "Save changes" msgstr "Aldaketak gorde" -#: views/base.py:430 +#: views/base.py:315 msgid "Django Xadmin" msgstr "Django Xadmin" -#: views/dashboard.py:185 +#: views/base.py:316 +msgid "my-company.inc" +msgstr "" + +#: views/dashboard.py:186 msgid "Widget ID" msgstr "Widget IDa" -#: views/dashboard.py:186 +#: views/dashboard.py:187 msgid "Widget Title" msgstr "Widget Izenburua" -#: views/dashboard.py:248 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." msgstr "Html Eduki Widgeta, edozein html eduki idatzi daiteke widgetan." -#: views/dashboard.py:251 +#: views/dashboard.py:255 msgid "Html Content" msgstr "Html Edukia" -#: views/dashboard.py:314 +#: views/dashboard.py:318 msgid "Target Model" msgstr "Helburu den Modelua" -#: views/dashboard.py:365 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." msgstr "Botoi azkarra Widgeta, edozein orri azkar ireki." -#: views/dashboard.py:367 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "Botoi Azkarrak" -#: views/dashboard.py:408 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "Edozein Objetu zerrenda Widgeta." -#: views/dashboard.py:447 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "Edozein objetu gehitu Widgeta." -#: views/dashboard.py:481 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "Arbela" -#: views/dashboard.py:622 +#: views/dashboard.py:633 #, python-format msgid "%s Dashboard" msgstr "" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "\"%(obj)s\" %(name)sa arrakastaz ezabatua izan da." -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "Beste Eremuak" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "%s Xehetasunak" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, fuzzy, python-format +#| msgid "Change %s" +msgid "Changed %s." +msgstr "Aldaketa %s" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "\"%(obj)s\" %(name)sa arrakastaz gehitua izan da." -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "Behean editatu dezakezu berriro." -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "Behean beste %s bat gehitu dezakezu." -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "Aldaketa %s" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "\"%(obj)s\" %(name)sa arrakastaz gehitua izan da." -#: views/form.py:164 +#: views/form.py:165 #, fuzzy, python-format msgid "The %s was changed successfully." msgstr "\"%(obj)s\" %(name)sa arrakastaz gehitua izan da." -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "Datubase errorea" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "%s Zerrenda" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "GOR Ordenatu" -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "BEH Ordenatu" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "Ezeztatu Ordenaketa" #: views/website.py:16 msgid "Main Dashboard" msgstr "Arbela Nagusia" + +#: widgets.py:48 +msgid "Now" +msgstr "Orain" diff --git a/xadmin/locale/id_ID/LC_MESSAGES/django.mo b/xadmin/locale/id_ID/LC_MESSAGES/django.mo index be9342ad5..434b6454a 100644 Binary files a/xadmin/locale/id_ID/LC_MESSAGES/django.mo and b/xadmin/locale/id_ID/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/id_ID/LC_MESSAGES/django.po b/xadmin/locale/id_ID/LC_MESSAGES/django.po index 1e91c9135..1cc66c5e7 100644 --- a/xadmin/locale/id_ID/LC_MESSAGES/django.po +++ b/xadmin/locale/id_ID/LC_MESSAGES/django.po @@ -7,62 +7,73 @@ msgid "" msgstr "" "Project-Id-Version: xadmin-core\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-10 10:31+0800\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: 2013-11-20 10:21+0000\n" "Last-Translator: sshwsfc \n" -"Language-Team: Indonesian (Indonesia) (http://www.transifex.com/projects/p/xadmin/language/id_ID/)\n" +"Language-Team: Indonesian (Indonesia) (http://www.transifex.com/projects/p/" +"xadmin/language/id_ID/)\n" "Language: id_ID\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "" -#: filters.py:158 plugins/export.py:117 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "" -#: filters.py:159 plugins/export.py:117 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "" -#: filters.py:173 +#: filters.py:175 msgid "Unknown" msgstr "" -#: filters.py:265 +#: filters.py:267 msgid "Any date" msgstr "" -#: filters.py:266 +#: filters.py:268 msgid "Has date" msgstr "" -#: filters.py:269 +#: filters.py:271 msgid "Has no date" msgstr "" -#: filters.py:272 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "" -#: filters.py:276 +#: filters.py:278 msgid "Past 7 days" msgstr "" -#: filters.py:280 +#: filters.py:282 msgid "This month" msgstr "" -#: filters.py:284 +#: filters.py:286 msgid "This year" msgstr "" #: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." msgstr "" #: forms.py:21 @@ -74,106 +85,160 @@ msgstr "" msgid "Your e-mail address is not your username. Try '%s' instead." msgstr "" -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "" -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "" -#: widgets.py:48 -msgid "Now" +#: models.py:142 +msgid "action time" +msgstr "" + +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" + +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +msgid "change message" +msgstr "" + +#: models.py:164 +msgid "log entry" +msgstr "" + +#: models.py:165 +msgid "log entries" msgstr "" -#: plugins/actions.py:54 +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, python-format +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "" + +#: models.py:180 +#, python-format +msgid "Deleted \"%(object)s.\"" +msgstr "" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, python-format +msgid "Batch delete %(count)d %(items)s." +msgstr "" + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "" -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" msgstr[0] "" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "" -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." +#: plugins/actions.py:179 plugins/actions.py:189 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." msgstr "" #: plugins/aggregation.py:14 @@ -241,20 +306,20 @@ msgstr "" msgid "Permission Name" msgstr "" -#: plugins/auth.py:159 +#: plugins/auth.py:167 msgid "Change Password" msgstr "" -#: plugins/auth.py:189 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "" -#: plugins/auth.py:214 plugins/auth.py:246 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "" -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -269,7 +334,7 @@ msgstr "" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "" -#: plugins/batch.py:90 +#: plugins/batch.py:89 #, python-format msgid "Successfully change %(count)d %(items)s." msgstr "" @@ -279,19 +344,19 @@ msgstr "" msgid "Batch change %s" msgstr "" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 msgid "bookmark" msgstr "" -#: plugins/bookmark.py:173 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." msgstr "" -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "" -#: plugins/chart.py:49 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "" @@ -333,27 +398,27 @@ msgid "1 comment was successfully %(action)s." msgid_plural "%(count)s comments were successfully %(action)s." msgstr[0] "" -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "" -#: plugins/editable.py:47 +#: plugins/editable.py:46 #, python-format msgid "Enter %s" msgstr "" -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "" -#: plugins/export.py:87 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "" -#: plugins/filters.py:125 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "" @@ -378,11 +443,11 @@ msgstr "" msgid "Change:" msgstr "" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "" @@ -390,20 +455,25 @@ msgstr "" msgid "Forgotten your password or username?" msgstr "" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "" -#: plugins/relfield.py:29 plugins/topnav.py:35 +#: plugins/relfield.py:29 plugins/topnav.py:38 #, python-format msgid "Search %s" msgstr "" +#: plugins/relfield.py:67 +#, python-format +msgid "Select %s" +msgstr "" + #: plugins/themes.py:47 msgid "Default" msgstr "" @@ -420,88 +490,92 @@ msgstr "" msgid "Bootstrap 2.x theme" msgstr "" -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "" -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "" -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "" -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "" -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "" -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "" -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "" -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." msgstr "" -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." msgstr "" -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "" @@ -509,9 +583,10 @@ msgstr "" msgid "We're sorry, but the requested page could not be found." msgstr "" -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -522,7 +597,7 @@ msgstr "" #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "" @@ -539,19 +614,9 @@ msgid "Server Error (500)" msgstr "" #: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "" - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "" - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." msgstr "" #: templates/xadmin/auth/password_reset/complete.html:11 @@ -572,7 +637,9 @@ msgid "Enter new password" msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:19 @@ -584,16 +651,22 @@ msgid "Password reset unsuccessful" msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." msgstr "" #: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." msgstr "" #: templates/xadmin/auth/password_reset/email.html:2 #, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." msgstr "" #: templates/xadmin/auth/password_reset/email.html:4 @@ -618,7 +691,9 @@ msgid "Password reset" msgstr "" #: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." msgstr "" #: templates/xadmin/auth/password_reset/form.html:25 @@ -630,7 +705,9 @@ msgid "Reset my password" msgstr "" #: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." msgstr "" #: templates/xadmin/auth/user/add_form.html:8 @@ -654,19 +731,32 @@ msgstr "" msgid "Enter a new password for the user %(username)s." msgstr "" +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "" + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "" + #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "" @@ -684,7 +774,7 @@ msgstr "" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "" @@ -730,7 +820,7 @@ msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" +msgid "Select all %(total_count)s %(model_name)s" msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 @@ -744,26 +834,27 @@ msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:47 msgid "Export" msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 msgid "Export with table header." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:38 msgid "Export with format." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:42 msgid "Export all data." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:46 +#: templates/xadmin/widgets/base.html:41 msgid "Close" msgstr "" @@ -780,8 +871,12 @@ msgstr "" msgid "Every %(t)s seconds" msgstr "" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "" @@ -819,7 +914,7 @@ msgstr "" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "" @@ -840,7 +935,11 @@ msgstr "" msgid "To" msgstr "" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +msgid "Select" +msgstr "" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "" @@ -873,7 +972,7 @@ msgid "Choose" msgstr "" #: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 +#: templates/xadmin/widgets/base.html:40 msgid "Remove" msgstr "" @@ -895,7 +994,7 @@ msgstr "" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "" @@ -912,7 +1011,7 @@ msgid "Save and continue editing" msgstr "" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "" @@ -942,7 +1041,10 @@ msgid "Add Widget" msgstr "" #: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." msgstr "" #: templates/xadmin/views/logged_out.html:16 @@ -984,17 +1086,24 @@ msgstr "" #: templates/xadmin/views/model_delete_confirm.html:11 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:19 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:27 #, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:34 @@ -1013,17 +1122,24 @@ msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:18 #, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:26 #, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:34 #, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" msgstr "" #: templates/xadmin/views/model_history.html:26 @@ -1048,7 +1164,9 @@ msgid "Diff Select Versions" msgstr "" #: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." msgstr "" #: templates/xadmin/views/model_list.html:29 @@ -1074,7 +1192,8 @@ msgid "Press the recover button below to recover this version of the object." msgstr "" #: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." +msgid "" +"Choose a date from the list below to recover a deleted version of an object." msgstr "" #: templates/xadmin/views/recover_list.html:39 @@ -1133,127 +1252,152 @@ msgstr "" msgid "Quick Add" msgstr "" -#: templates/xadmin/widgets/base.html:30 +#: templates/xadmin/widgets/base.html:31 msgid "Widget Options" msgstr "" -#: templates/xadmin/widgets/base.html:41 +#: templates/xadmin/widgets/base.html:42 msgid "Save changes" msgstr "" -#: views/base.py:430 +#: views/base.py:315 msgid "Django Xadmin" msgstr "" -#: views/dashboard.py:185 -msgid "Widget ID" +#: views/base.py:316 +msgid "my-company.inc" msgstr "" #: views/dashboard.py:186 +msgid "Widget ID" +msgstr "" + +#: views/dashboard.py:187 msgid "Widget Title" msgstr "" -#: views/dashboard.py:248 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." msgstr "" -#: views/dashboard.py:251 +#: views/dashboard.py:255 msgid "Html Content" msgstr "" -#: views/dashboard.py:314 +#: views/dashboard.py:318 msgid "Target Model" msgstr "" -#: views/dashboard.py:365 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." msgstr "" -#: views/dashboard.py:367 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "" -#: views/dashboard.py:408 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "" -#: views/dashboard.py:447 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "" -#: views/dashboard.py:481 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "" -#: views/dashboard.py:622 +#: views/dashboard.py:633 #, python-format msgid "%s Dashboard" msgstr "" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "" -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, python-format +msgid "Changed %s." +msgstr "" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "" -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "" -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "" -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "" -#: views/form.py:164 +#: views/form.py:165 #, python-format msgid "The %s was changed successfully." msgstr "" -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "" -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "" #: views/website.py:16 msgid "Main Dashboard" msgstr "" + +#: widgets.py:48 +msgid "Now" +msgstr "" diff --git a/xadmin/locale/ja/LC_MESSAGES/django.mo b/xadmin/locale/ja/LC_MESSAGES/django.mo index 6e431fe54..42bffc08a 100644 Binary files a/xadmin/locale/ja/LC_MESSAGES/django.mo and b/xadmin/locale/ja/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/ja/LC_MESSAGES/django.po b/xadmin/locale/ja/LC_MESSAGES/django.po index 31955a84e..1d716b0c3 100644 --- a/xadmin/locale/ja/LC_MESSAGES/django.po +++ b/xadmin/locale/ja/LC_MESSAGES/django.po @@ -7,62 +7,73 @@ msgid "" msgstr "" "Project-Id-Version: xadmin-core\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-10 10:31+0800\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: 2013-11-20 10:21+0000\n" "Last-Translator: sshwsfc \n" -"Language-Team: Japanese (http://www.transifex.com/projects/p/xadmin/language/ja/)\n" +"Language-Team: Japanese (http://www.transifex.com/projects/p/xadmin/language/" +"ja/)\n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "" -#: filters.py:158 plugins/export.py:117 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "" -#: filters.py:159 plugins/export.py:117 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "" -#: filters.py:173 +#: filters.py:175 msgid "Unknown" msgstr "" -#: filters.py:265 +#: filters.py:267 msgid "Any date" msgstr "" -#: filters.py:266 +#: filters.py:268 msgid "Has date" msgstr "" -#: filters.py:269 +#: filters.py:271 msgid "Has no date" msgstr "" -#: filters.py:272 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "" -#: filters.py:276 +#: filters.py:278 msgid "Past 7 days" msgstr "" -#: filters.py:280 +#: filters.py:282 msgid "This month" msgstr "" -#: filters.py:284 +#: filters.py:286 msgid "This year" msgstr "" #: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." msgstr "" #: forms.py:21 @@ -74,106 +85,160 @@ msgstr "" msgid "Your e-mail address is not your username. Try '%s' instead." msgstr "" -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "" -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "" -#: widgets.py:48 -msgid "Now" +#: models.py:142 +msgid "action time" +msgstr "" + +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" + +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +msgid "change message" +msgstr "" + +#: models.py:164 +msgid "log entry" +msgstr "" + +#: models.py:165 +msgid "log entries" msgstr "" -#: plugins/actions.py:54 +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, python-format +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "" + +#: models.py:180 +#, python-format +msgid "Deleted \"%(object)s.\"" +msgstr "" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, python-format +msgid "Batch delete %(count)d %(items)s." +msgstr "" + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "" -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" msgstr[0] "" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "" -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." +#: plugins/actions.py:179 plugins/actions.py:189 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." msgstr "" #: plugins/aggregation.py:14 @@ -241,20 +306,20 @@ msgstr "" msgid "Permission Name" msgstr "" -#: plugins/auth.py:159 +#: plugins/auth.py:167 msgid "Change Password" msgstr "" -#: plugins/auth.py:189 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "" -#: plugins/auth.py:214 plugins/auth.py:246 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "" -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -269,7 +334,7 @@ msgstr "" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "" -#: plugins/batch.py:90 +#: plugins/batch.py:89 #, python-format msgid "Successfully change %(count)d %(items)s." msgstr "" @@ -279,19 +344,19 @@ msgstr "" msgid "Batch change %s" msgstr "" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 msgid "bookmark" msgstr "" -#: plugins/bookmark.py:173 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." msgstr "" -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "" -#: plugins/chart.py:49 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "" @@ -333,27 +398,27 @@ msgid "1 comment was successfully %(action)s." msgid_plural "%(count)s comments were successfully %(action)s." msgstr[0] "" -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "" -#: plugins/editable.py:47 +#: plugins/editable.py:46 #, python-format msgid "Enter %s" msgstr "" -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "" -#: plugins/export.py:87 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "" -#: plugins/filters.py:125 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "" @@ -378,11 +443,11 @@ msgstr "" msgid "Change:" msgstr "" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "" @@ -390,20 +455,25 @@ msgstr "" msgid "Forgotten your password or username?" msgstr "" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "" -#: plugins/relfield.py:29 plugins/topnav.py:35 +#: plugins/relfield.py:29 plugins/topnav.py:38 #, python-format msgid "Search %s" msgstr "" +#: plugins/relfield.py:67 +#, python-format +msgid "Select %s" +msgstr "" + #: plugins/themes.py:47 msgid "Default" msgstr "" @@ -420,88 +490,92 @@ msgstr "" msgid "Bootstrap 2.x theme" msgstr "" -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "" -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "" -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "" -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "" -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "" -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "" -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "" -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." msgstr "" -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." msgstr "" -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "" @@ -509,9 +583,10 @@ msgstr "" msgid "We're sorry, but the requested page could not be found." msgstr "" -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -522,7 +597,7 @@ msgstr "" #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "" @@ -539,19 +614,9 @@ msgid "Server Error (500)" msgstr "" #: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "" - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "" - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." msgstr "" #: templates/xadmin/auth/password_reset/complete.html:11 @@ -572,7 +637,9 @@ msgid "Enter new password" msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:19 @@ -584,16 +651,22 @@ msgid "Password reset unsuccessful" msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." msgstr "" #: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." msgstr "" #: templates/xadmin/auth/password_reset/email.html:2 #, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." msgstr "" #: templates/xadmin/auth/password_reset/email.html:4 @@ -618,7 +691,9 @@ msgid "Password reset" msgstr "" #: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." msgstr "" #: templates/xadmin/auth/password_reset/form.html:25 @@ -630,7 +705,9 @@ msgid "Reset my password" msgstr "" #: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." msgstr "" #: templates/xadmin/auth/user/add_form.html:8 @@ -654,19 +731,32 @@ msgstr "" msgid "Enter a new password for the user %(username)s." msgstr "" +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "" + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "" + #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "" @@ -684,7 +774,7 @@ msgstr "" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "" @@ -730,7 +820,7 @@ msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" +msgid "Select all %(total_count)s %(model_name)s" msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 @@ -744,26 +834,27 @@ msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:47 msgid "Export" msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 msgid "Export with table header." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:38 msgid "Export with format." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:42 msgid "Export all data." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:46 +#: templates/xadmin/widgets/base.html:41 msgid "Close" msgstr "" @@ -780,8 +871,12 @@ msgstr "" msgid "Every %(t)s seconds" msgstr "" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "" @@ -819,7 +914,7 @@ msgstr "" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "" @@ -840,7 +935,11 @@ msgstr "" msgid "To" msgstr "" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +msgid "Select" +msgstr "" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "" @@ -873,7 +972,7 @@ msgid "Choose" msgstr "" #: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 +#: templates/xadmin/widgets/base.html:40 msgid "Remove" msgstr "" @@ -895,7 +994,7 @@ msgstr "" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "" @@ -912,7 +1011,7 @@ msgid "Save and continue editing" msgstr "" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "" @@ -942,7 +1041,10 @@ msgid "Add Widget" msgstr "" #: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." msgstr "" #: templates/xadmin/views/logged_out.html:16 @@ -984,17 +1086,24 @@ msgstr "" #: templates/xadmin/views/model_delete_confirm.html:11 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:19 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:27 #, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:34 @@ -1013,17 +1122,24 @@ msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:18 #, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:26 #, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:34 #, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" msgstr "" #: templates/xadmin/views/model_history.html:26 @@ -1048,7 +1164,9 @@ msgid "Diff Select Versions" msgstr "" #: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." msgstr "" #: templates/xadmin/views/model_list.html:29 @@ -1074,7 +1192,8 @@ msgid "Press the recover button below to recover this version of the object." msgstr "" #: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." +msgid "" +"Choose a date from the list below to recover a deleted version of an object." msgstr "" #: templates/xadmin/views/recover_list.html:39 @@ -1133,127 +1252,152 @@ msgstr "" msgid "Quick Add" msgstr "" -#: templates/xadmin/widgets/base.html:30 +#: templates/xadmin/widgets/base.html:31 msgid "Widget Options" msgstr "" -#: templates/xadmin/widgets/base.html:41 +#: templates/xadmin/widgets/base.html:42 msgid "Save changes" msgstr "" -#: views/base.py:430 +#: views/base.py:315 msgid "Django Xadmin" msgstr "" -#: views/dashboard.py:185 -msgid "Widget ID" +#: views/base.py:316 +msgid "my-company.inc" msgstr "" #: views/dashboard.py:186 +msgid "Widget ID" +msgstr "" + +#: views/dashboard.py:187 msgid "Widget Title" msgstr "" -#: views/dashboard.py:248 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." msgstr "" -#: views/dashboard.py:251 +#: views/dashboard.py:255 msgid "Html Content" msgstr "" -#: views/dashboard.py:314 +#: views/dashboard.py:318 msgid "Target Model" msgstr "" -#: views/dashboard.py:365 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." msgstr "" -#: views/dashboard.py:367 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "" -#: views/dashboard.py:408 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "" -#: views/dashboard.py:447 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "" -#: views/dashboard.py:481 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "" -#: views/dashboard.py:622 +#: views/dashboard.py:633 #, python-format msgid "%s Dashboard" msgstr "" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "" -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, python-format +msgid "Changed %s." +msgstr "" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "" -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "" -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "" -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "" -#: views/form.py:164 +#: views/form.py:165 #, python-format msgid "The %s was changed successfully." msgstr "" -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "" -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "" #: views/website.py:16 msgid "Main Dashboard" msgstr "" + +#: widgets.py:48 +msgid "Now" +msgstr "" diff --git a/xadmin/locale/lt/LC_MESSAGES/django.mo b/xadmin/locale/lt/LC_MESSAGES/django.mo index 9a7add4cd..7a23b22c4 100644 Binary files a/xadmin/locale/lt/LC_MESSAGES/django.mo and b/xadmin/locale/lt/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/lt/LC_MESSAGES/django.po b/xadmin/locale/lt/LC_MESSAGES/django.po index 1d9fb88ee..1e7dcbfe9 100644 --- a/xadmin/locale/lt/LC_MESSAGES/django.po +++ b/xadmin/locale/lt/LC_MESSAGES/django.po @@ -7,62 +7,74 @@ msgid "" msgstr "" "Project-Id-Version: xadmin-core\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-10 10:31+0800\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: 2013-11-20 10:21+0000\n" "Last-Translator: sshwsfc \n" -"Language-Team: Lithuanian (http://www.transifex.com/projects/p/xadmin/language/lt/)\n" +"Language-Team: Lithuanian (http://www.transifex.com/projects/p/xadmin/" +"language/lt/)\n" "Language: lt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "" -#: filters.py:158 plugins/export.py:117 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "" -#: filters.py:159 plugins/export.py:117 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "" -#: filters.py:173 +#: filters.py:175 msgid "Unknown" msgstr "" -#: filters.py:265 +#: filters.py:267 msgid "Any date" msgstr "" -#: filters.py:266 +#: filters.py:268 msgid "Has date" msgstr "" -#: filters.py:269 +#: filters.py:271 msgid "Has no date" msgstr "" -#: filters.py:272 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "" -#: filters.py:276 +#: filters.py:278 msgid "Past 7 days" msgstr "" -#: filters.py:280 +#: filters.py:282 msgid "This month" msgstr "" -#: filters.py:284 +#: filters.py:286 msgid "This year" msgstr "" #: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." msgstr "" #: forms.py:21 @@ -74,94 +86,146 @@ msgstr "" msgid "Your e-mail address is not your username. Try '%s' instead." msgstr "" -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "" -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "" -#: widgets.py:48 -msgid "Now" +#: models.py:142 +msgid "action time" +msgstr "" + +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" + +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +msgid "change message" +msgstr "" + +#: models.py:164 +msgid "log entry" +msgstr "" + +#: models.py:165 +msgid "log entries" msgstr "" -#: plugins/actions.py:54 +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, python-format +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "" + +#: models.py:180 +#, python-format +msgid "Deleted \"%(object)s.\"" +msgstr "" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, python-format +msgid "Batch delete %(count)d %(items)s." +msgstr "" + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "" -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" @@ -169,13 +233,15 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "" -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." +#: plugins/actions.py:179 plugins/actions.py:189 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." msgstr "" #: plugins/aggregation.py:14 @@ -243,20 +309,20 @@ msgstr "" msgid "Permission Name" msgstr "" -#: plugins/auth.py:159 +#: plugins/auth.py:167 msgid "Change Password" msgstr "" -#: plugins/auth.py:189 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "" -#: plugins/auth.py:214 plugins/auth.py:246 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "" -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -271,7 +337,7 @@ msgstr "" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "" -#: plugins/batch.py:90 +#: plugins/batch.py:89 #, python-format msgid "Successfully change %(count)d %(items)s." msgstr "" @@ -281,19 +347,19 @@ msgstr "" msgid "Batch change %s" msgstr "" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 msgid "bookmark" msgstr "" -#: plugins/bookmark.py:173 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." msgstr "" -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "" -#: plugins/chart.py:49 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "" @@ -343,27 +409,27 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "" -#: plugins/editable.py:47 +#: plugins/editable.py:46 #, python-format msgid "Enter %s" msgstr "" -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "" -#: plugins/export.py:87 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "" -#: plugins/filters.py:125 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "" @@ -388,11 +454,11 @@ msgstr "" msgid "Change:" msgstr "" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "" @@ -400,20 +466,25 @@ msgstr "" msgid "Forgotten your password or username?" msgstr "" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "" -#: plugins/relfield.py:29 plugins/topnav.py:35 +#: plugins/relfield.py:29 plugins/topnav.py:38 #, python-format msgid "Search %s" msgstr "" +#: plugins/relfield.py:67 +#, python-format +msgid "Select %s" +msgstr "" + #: plugins/themes.py:47 msgid "Default" msgstr "" @@ -430,88 +501,92 @@ msgstr "" msgid "Bootstrap 2.x theme" msgstr "" -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "" -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "" -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "" -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "" -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "" -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "" -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "" -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." msgstr "" -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." msgstr "" -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "" @@ -519,9 +594,10 @@ msgstr "" msgid "We're sorry, but the requested page could not be found." msgstr "" -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -532,7 +608,7 @@ msgstr "" #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "" @@ -549,19 +625,9 @@ msgid "Server Error (500)" msgstr "" #: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "" - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "" - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." msgstr "" #: templates/xadmin/auth/password_reset/complete.html:11 @@ -582,7 +648,9 @@ msgid "Enter new password" msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:19 @@ -594,16 +662,22 @@ msgid "Password reset unsuccessful" msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." msgstr "" #: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." msgstr "" #: templates/xadmin/auth/password_reset/email.html:2 #, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." msgstr "" #: templates/xadmin/auth/password_reset/email.html:4 @@ -628,7 +702,9 @@ msgid "Password reset" msgstr "" #: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." msgstr "" #: templates/xadmin/auth/password_reset/form.html:25 @@ -640,7 +716,9 @@ msgid "Reset my password" msgstr "" #: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." msgstr "" #: templates/xadmin/auth/user/add_form.html:8 @@ -666,19 +744,32 @@ msgstr "" msgid "Enter a new password for the user %(username)s." msgstr "" +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "" + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "" + #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "" @@ -696,7 +787,7 @@ msgstr "" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "" @@ -742,7 +833,7 @@ msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" +msgid "Select all %(total_count)s %(model_name)s" msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 @@ -756,26 +847,27 @@ msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:47 msgid "Export" msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 msgid "Export with table header." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:38 msgid "Export with format." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:42 msgid "Export all data." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:46 +#: templates/xadmin/widgets/base.html:41 msgid "Close" msgstr "" @@ -792,8 +884,12 @@ msgstr "" msgid "Every %(t)s seconds" msgstr "" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "" @@ -831,7 +927,7 @@ msgstr "" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "" @@ -852,7 +948,11 @@ msgstr "" msgid "To" msgstr "" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +msgid "Select" +msgstr "" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "" @@ -885,7 +985,7 @@ msgid "Choose" msgstr "" #: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 +#: templates/xadmin/widgets/base.html:40 msgid "Remove" msgstr "" @@ -907,7 +1007,7 @@ msgstr "" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "" @@ -924,7 +1024,7 @@ msgid "Save and continue editing" msgstr "" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "" @@ -956,7 +1056,10 @@ msgid "Add Widget" msgstr "" #: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." msgstr "" #: templates/xadmin/views/logged_out.html:16 @@ -998,17 +1101,24 @@ msgstr "" #: templates/xadmin/views/model_delete_confirm.html:11 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:19 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:27 #, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:34 @@ -1027,17 +1137,24 @@ msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:18 #, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:26 #, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:34 #, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" msgstr "" #: templates/xadmin/views/model_history.html:26 @@ -1062,7 +1179,9 @@ msgid "Diff Select Versions" msgstr "" #: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." msgstr "" #: templates/xadmin/views/model_list.html:29 @@ -1088,7 +1207,8 @@ msgid "Press the recover button below to recover this version of the object." msgstr "" #: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." +msgid "" +"Choose a date from the list below to recover a deleted version of an object." msgstr "" #: templates/xadmin/views/recover_list.html:39 @@ -1147,127 +1267,152 @@ msgstr "" msgid "Quick Add" msgstr "" -#: templates/xadmin/widgets/base.html:30 +#: templates/xadmin/widgets/base.html:31 msgid "Widget Options" msgstr "" -#: templates/xadmin/widgets/base.html:41 +#: templates/xadmin/widgets/base.html:42 msgid "Save changes" msgstr "" -#: views/base.py:430 +#: views/base.py:315 msgid "Django Xadmin" msgstr "" -#: views/dashboard.py:185 -msgid "Widget ID" +#: views/base.py:316 +msgid "my-company.inc" msgstr "" #: views/dashboard.py:186 +msgid "Widget ID" +msgstr "" + +#: views/dashboard.py:187 msgid "Widget Title" msgstr "" -#: views/dashboard.py:248 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." msgstr "" -#: views/dashboard.py:251 +#: views/dashboard.py:255 msgid "Html Content" msgstr "" -#: views/dashboard.py:314 +#: views/dashboard.py:318 msgid "Target Model" msgstr "" -#: views/dashboard.py:365 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." msgstr "" -#: views/dashboard.py:367 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "" -#: views/dashboard.py:408 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "" -#: views/dashboard.py:447 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "" -#: views/dashboard.py:481 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "" -#: views/dashboard.py:622 +#: views/dashboard.py:633 #, python-format msgid "%s Dashboard" msgstr "" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "" -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, python-format +msgid "Changed %s." +msgstr "" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "" -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "" -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "" -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "" -#: views/form.py:164 +#: views/form.py:165 #, python-format msgid "The %s was changed successfully." msgstr "" -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "" -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "" #: views/website.py:16 msgid "Main Dashboard" msgstr "" + +#: widgets.py:48 +msgid "Now" +msgstr "" diff --git a/xadmin/locale/nl_NL/LC_MESSAGES/django.mo b/xadmin/locale/nl_NL/LC_MESSAGES/django.mo index 63ffa4ce8..f197a007b 100644 Binary files a/xadmin/locale/nl_NL/LC_MESSAGES/django.mo and b/xadmin/locale/nl_NL/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/nl_NL/LC_MESSAGES/django.po b/xadmin/locale/nl_NL/LC_MESSAGES/django.po index 08c3a5cc6..b7832866f 100644 --- a/xadmin/locale/nl_NL/LC_MESSAGES/django.po +++ b/xadmin/locale/nl_NL/LC_MESSAGES/django.po @@ -7,62 +7,73 @@ msgid "" msgstr "" "Project-Id-Version: xadmin-core\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-10 10:31+0800\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: 2013-11-20 10:21+0000\n" "Last-Translator: sshwsfc \n" -"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/xadmin/language/nl_NL/)\n" +"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/" +"xadmin/language/nl_NL/)\n" "Language: nl_NL\n" "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" -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "" -#: filters.py:158 plugins/export.py:117 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "" -#: filters.py:159 plugins/export.py:117 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "" -#: filters.py:173 +#: filters.py:175 msgid "Unknown" msgstr "" -#: filters.py:265 +#: filters.py:267 msgid "Any date" msgstr "" -#: filters.py:266 +#: filters.py:268 msgid "Has date" msgstr "" -#: filters.py:269 +#: filters.py:271 msgid "Has no date" msgstr "" -#: filters.py:272 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "" -#: filters.py:276 +#: filters.py:278 msgid "Past 7 days" msgstr "" -#: filters.py:280 +#: filters.py:282 msgid "This month" msgstr "" -#: filters.py:284 +#: filters.py:286 msgid "This year" msgstr "" #: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." msgstr "" #: forms.py:21 @@ -74,107 +85,161 @@ msgstr "" msgid "Your e-mail address is not your username. Try '%s' instead." msgstr "" -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "" -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "" -#: widgets.py:48 -msgid "Now" +#: models.py:142 +msgid "action time" +msgstr "" + +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" + +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +msgid "change message" +msgstr "" + +#: models.py:164 +msgid "log entry" +msgstr "" + +#: models.py:165 +msgid "log entries" msgstr "" -#: plugins/actions.py:54 +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, python-format +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "" + +#: models.py:180 +#, python-format +msgid "Deleted \"%(object)s.\"" +msgstr "" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, python-format +msgid "Batch delete %(count)d %(items)s." +msgstr "" + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "" -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" msgstr[0] "" msgstr[1] "" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "" -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." +#: plugins/actions.py:179 plugins/actions.py:189 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." msgstr "" #: plugins/aggregation.py:14 @@ -242,20 +307,20 @@ msgstr "" msgid "Permission Name" msgstr "" -#: plugins/auth.py:159 +#: plugins/auth.py:167 msgid "Change Password" msgstr "" -#: plugins/auth.py:189 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "" -#: plugins/auth.py:214 plugins/auth.py:246 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "" -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -270,7 +335,7 @@ msgstr "" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "" -#: plugins/batch.py:90 +#: plugins/batch.py:89 #, python-format msgid "Successfully change %(count)d %(items)s." msgstr "" @@ -280,19 +345,19 @@ msgstr "" msgid "Batch change %s" msgstr "" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 msgid "bookmark" msgstr "" -#: plugins/bookmark.py:173 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." msgstr "" -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "" -#: plugins/chart.py:49 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "" @@ -338,27 +403,27 @@ msgid_plural "%(count)s comments were successfully %(action)s." msgstr[0] "" msgstr[1] "" -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "" -#: plugins/editable.py:47 +#: plugins/editable.py:46 #, python-format msgid "Enter %s" msgstr "" -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "" -#: plugins/export.py:87 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "" -#: plugins/filters.py:125 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "" @@ -383,11 +448,11 @@ msgstr "" msgid "Change:" msgstr "" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "" @@ -395,20 +460,25 @@ msgstr "" msgid "Forgotten your password or username?" msgstr "" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "" -#: plugins/relfield.py:29 plugins/topnav.py:35 +#: plugins/relfield.py:29 plugins/topnav.py:38 #, python-format msgid "Search %s" msgstr "" +#: plugins/relfield.py:67 +#, python-format +msgid "Select %s" +msgstr "" + #: plugins/themes.py:47 msgid "Default" msgstr "" @@ -425,88 +495,92 @@ msgstr "" msgid "Bootstrap 2.x theme" msgstr "" -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "" -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "" -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "" -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "" -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "" -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "" -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "" -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." msgstr "" -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." msgstr "" -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "" @@ -514,9 +588,10 @@ msgstr "" msgid "We're sorry, but the requested page could not be found." msgstr "" -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -527,7 +602,7 @@ msgstr "" #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "" @@ -544,19 +619,9 @@ msgid "Server Error (500)" msgstr "" #: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "" - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "" - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." msgstr "" #: templates/xadmin/auth/password_reset/complete.html:11 @@ -577,7 +642,9 @@ msgid "Enter new password" msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:19 @@ -589,16 +656,22 @@ msgid "Password reset unsuccessful" msgstr "" #: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." msgstr "" #: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." msgstr "" #: templates/xadmin/auth/password_reset/email.html:2 #, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." msgstr "" #: templates/xadmin/auth/password_reset/email.html:4 @@ -623,7 +696,9 @@ msgid "Password reset" msgstr "" #: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." msgstr "" #: templates/xadmin/auth/password_reset/form.html:25 @@ -635,7 +710,9 @@ msgid "Reset my password" msgstr "" #: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." msgstr "" #: templates/xadmin/auth/user/add_form.html:8 @@ -660,19 +737,32 @@ msgstr "" msgid "Enter a new password for the user %(username)s." msgstr "" +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "" + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "" + #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "" @@ -690,7 +780,7 @@ msgstr "" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "" @@ -736,7 +826,7 @@ msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" +msgid "Select all %(total_count)s %(model_name)s" msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 @@ -750,26 +840,27 @@ msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:47 msgid "Export" msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 msgid "Export with table header." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:38 msgid "Export with format." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:42 msgid "Export all data." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:46 +#: templates/xadmin/widgets/base.html:41 msgid "Close" msgstr "" @@ -786,8 +877,12 @@ msgstr "" msgid "Every %(t)s seconds" msgstr "" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "" @@ -825,7 +920,7 @@ msgstr "" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "" @@ -846,7 +941,11 @@ msgstr "" msgid "To" msgstr "" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +msgid "Select" +msgstr "" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "" @@ -879,7 +978,7 @@ msgid "Choose" msgstr "" #: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 +#: templates/xadmin/widgets/base.html:40 msgid "Remove" msgstr "" @@ -901,7 +1000,7 @@ msgstr "" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "" @@ -918,7 +1017,7 @@ msgid "Save and continue editing" msgstr "" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "" @@ -949,7 +1048,10 @@ msgid "Add Widget" msgstr "" #: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." msgstr "" #: templates/xadmin/views/logged_out.html:16 @@ -991,17 +1093,24 @@ msgstr "" #: templates/xadmin/views/model_delete_confirm.html:11 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:19 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:27 #, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:34 @@ -1020,17 +1129,24 @@ msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:18 #, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:26 #, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:34 #, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" msgstr "" #: templates/xadmin/views/model_history.html:26 @@ -1055,7 +1171,9 @@ msgid "Diff Select Versions" msgstr "" #: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." msgstr "" #: templates/xadmin/views/model_list.html:29 @@ -1081,7 +1199,8 @@ msgid "Press the recover button below to recover this version of the object." msgstr "" #: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." +msgid "" +"Choose a date from the list below to recover a deleted version of an object." msgstr "" #: templates/xadmin/views/recover_list.html:39 @@ -1140,127 +1259,152 @@ msgstr "" msgid "Quick Add" msgstr "" -#: templates/xadmin/widgets/base.html:30 +#: templates/xadmin/widgets/base.html:31 msgid "Widget Options" msgstr "" -#: templates/xadmin/widgets/base.html:41 +#: templates/xadmin/widgets/base.html:42 msgid "Save changes" msgstr "" -#: views/base.py:430 +#: views/base.py:315 msgid "Django Xadmin" msgstr "" -#: views/dashboard.py:185 -msgid "Widget ID" +#: views/base.py:316 +msgid "my-company.inc" msgstr "" #: views/dashboard.py:186 +msgid "Widget ID" +msgstr "" + +#: views/dashboard.py:187 msgid "Widget Title" msgstr "" -#: views/dashboard.py:248 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." msgstr "" -#: views/dashboard.py:251 +#: views/dashboard.py:255 msgid "Html Content" msgstr "" -#: views/dashboard.py:314 +#: views/dashboard.py:318 msgid "Target Model" msgstr "" -#: views/dashboard.py:365 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." msgstr "" -#: views/dashboard.py:367 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "" -#: views/dashboard.py:408 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "" -#: views/dashboard.py:447 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "" -#: views/dashboard.py:481 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "" -#: views/dashboard.py:622 +#: views/dashboard.py:633 #, python-format msgid "%s Dashboard" msgstr "" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "" -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, python-format +msgid "Changed %s." +msgstr "" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "" -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "" -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "" -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "" -#: views/form.py:164 +#: views/form.py:165 #, python-format msgid "The %s was changed successfully." msgstr "" -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "" -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "" #: views/website.py:16 msgid "Main Dashboard" msgstr "" + +#: widgets.py:48 +msgid "Now" +msgstr "" diff --git a/xadmin/locale/pl/LC_MESSAGES/django.mo b/xadmin/locale/pl/LC_MESSAGES/django.mo index 58b9c1459..c9b8381d4 100644 Binary files a/xadmin/locale/pl/LC_MESSAGES/django.mo and b/xadmin/locale/pl/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/pl/LC_MESSAGES/django.po b/xadmin/locale/pl/LC_MESSAGES/django.po index bc62d634f..5f5751b98 100644 --- a/xadmin/locale/pl/LC_MESSAGES/django.po +++ b/xadmin/locale/pl/LC_MESSAGES/django.po @@ -7,59 +7,67 @@ msgid "" msgstr "" "Project-Id-Version: django-xadmin\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-08-12 11:11+0200\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: 2014-08-12 21:08+0100\n" "Last-Translator: Michał Szpadzik \n" "Language-Team: Polish translators \n" +"Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" "X-Generator: Poedit 1.5.4\n" -"Language: pl\n" -#: filters.py:158 filters.py:190 filters.py:402 filters.py:488 filters.py:526 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "Wszystko" -#: filters.py:159 plugins/export.py:162 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "Tak" -#: filters.py:160 plugins/export.py:162 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "Nie" -#: filters.py:174 +#: filters.py:175 msgid "Unknown" msgstr "Nieznany" -#: filters.py:266 +#: filters.py:267 msgid "Any date" msgstr "Dowolna data" -#: filters.py:267 +#: filters.py:268 msgid "Has date" msgstr "Ma datę" -#: filters.py:270 +#: filters.py:271 msgid "Has no date" msgstr "Nie ma daty" -#: filters.py:273 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "Dzisiaj" -#: filters.py:277 +#: filters.py:278 msgid "Past 7 days" msgstr "Ostatnie 7 dni" -#: filters.py:281 +#: filters.py:282 msgid "This month" msgstr "Ten miesiąc" -#: filters.py:285 +#: filters.py:286 msgid "This year" msgstr "Ten rok" @@ -82,94 +90,156 @@ msgstr "" "Twój adres e-mail nie jest Twoją nazwą użytkownika. Zamiast tego spróbuj " "'%s'." -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "Tytuł" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "użytkownik" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "Nazwa Url" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "Tekst wyszukiwania" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "Jest współdzielony" -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:178 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "Zakładka" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "Zakładki" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "Klucz ustawień" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "Treść ustawień" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "Ustawienie użytkownika" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "Ustawienia użytkownika" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "Strona" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "Typ Widgetu" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "Parametry Widgetu" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "Widget użytkownika" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "Widgety użytkownika" -#: widgets.py:48 -msgid "Now" -msgstr "Teraz" +#: models.py:142 +#, fuzzy +#| msgid "Date/time" +msgid "action time" +msgstr "Data/czas" + +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" -#: plugins/actions.py:54 +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +#, fuzzy +#| msgid "Change %s" +msgid "change message" +msgstr "Zmień %s" + +#: models.py:164 +#, fuzzy +#| msgid "log in" +msgid "log entry" +msgstr "zaloguj się" + +#: models.py:165 +msgid "log entries" +msgstr "" + +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, fuzzy, python-format +#| msgid "Change one %(objects_name)s" +#| msgid_plural "Batch change %(counter)s %(objects_name)s" +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "Zmień %(objects_name)s" + +#: models.py:180 +#, fuzzy, python-format +#| msgid "Related Objects" +msgid "Deleted \"%(object)s.\"" +msgstr "Powiązane obiekty" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "Usuń zaznaczone %(verbose_name_plural)s" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, fuzzy, python-format +#| msgid "Successfully deleted %(count)d %(items)s." +msgid "Batch delete %(count)d %(items)s." +msgstr "Z powodzieniem usunięto %(count)d %(items)s." + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "Z powodzieniem usunięto %(count)d %(items)s." -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "Nie można usunąć %(name)s" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "Jesteś pewny ?" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" @@ -177,12 +247,12 @@ msgstr[0] "%(total_count)s zaznaczony" msgstr[1] "%(total_count)s zaznaczone" msgstr[2] "%(total_count)s zaznaczonych" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "0 z %(cnt)s zaznaczonych" -#: plugins/actions.py:168 plugins/actions.py:178 +#: plugins/actions.py:179 plugins/actions.py:189 msgid "" "Items must be selected in order to perform actions on them. No items have " "been changed." @@ -255,20 +325,20 @@ msgstr "Status" msgid "Permission Name" msgstr "Nazwa uprawnienia" -#: plugins/auth.py:161 +#: plugins/auth.py:167 msgid "Change Password" msgstr "Zmień hasło" -#: plugins/auth.py:191 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "Zmień hasło: %s" -#: plugins/auth.py:216 plugins/auth.py:248 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "Zmiana hasła zakończona powodzieniem" -#: plugins/auth.py:235 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -283,29 +353,29 @@ msgstr "Zmień to pole" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "Zmiana grupowa wybrana %(verbose_name_plural)s" -#: plugins/batch.py:88 +#: plugins/batch.py:89 #, python-format msgid "Successfully change %(count)d %(items)s." msgstr "Z powodzeniem zmieniono %(count)d %(items)s." -#: plugins/batch.py:136 +#: plugins/batch.py:138 #, python-format msgid "Batch change %s" msgstr "Zmiana grupowa %s" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 msgid "bookmark" msgstr "zakładka" -#: plugins/bookmark.py:174 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." msgstr "Widget zakładek, pozwala pokazać dane dla zakładki w widgecie." -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "Pokaż prosty wykres dla modelu." -#: plugins/chart.py:50 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "%s Wykresy" @@ -355,7 +425,7 @@ msgstr[0] "1 komentarz został z powodzeniem %(action)s." msgstr[1] "%(count)s komentarze zostało z powodzeniem %(action)s." msgstr[2] "%(count)s komentarzy zostało z powodzeniem %(action)s." -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "Szczegóły %s" @@ -365,17 +435,17 @@ msgstr "Szczegóły %s" msgid "Enter %s" msgstr "Wejdz w %s" -#: plugins/editable.py:73 views/dashboard.py:645 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "Obiekt %(name)s z kluczem głównym %(key)r nie istnieje." -#: plugins/export.py:95 plugins/export.py:132 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "Arkusz" -#: plugins/filters.py:132 plugins/quickfilter.py:140 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "Błąd filtracji: %s" @@ -400,11 +470,11 @@ msgstr "Ściągnij" msgid "Change:" msgstr "Zmień:" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "Tabela" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "Miniaturki" @@ -412,12 +482,12 @@ msgstr "Miniaturki" msgid "Forgotten your password or username?" msgstr "Zapomniałeś swojego hasła lub loginu ?" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "Utwórz nowy %s" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "Powiązane obiekty" @@ -426,6 +496,12 @@ msgstr "Powiązane obiekty" msgid "Search %s" msgstr "Szukaj %s" +#: plugins/relfield.py:67 +#, fuzzy, python-format +#| msgid "Select Date" +msgid "Select %s" +msgstr "Wybierz datę" + #: plugins/themes.py:47 msgid "Default" msgstr "Domyślny" @@ -442,73 +518,73 @@ msgstr "Bootstrap2" msgid "Bootstrap 2.x theme" msgstr "Tematy Bootstrap 2.x" -#: plugins/topnav.py:63 views/dashboard.py:462 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "Dodaj %s" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "Wersja startowa." -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "Zmień wersję." -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "Przywróć wersję." -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "Odzyskaj wersję." -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "Usunięte %(verbose_name)s." -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "Odzyskaj" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "Historia" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "Odzyskaj usunięte %(name)s" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "Zmień historię: %s" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "Musisz wybrać dwie wersje." -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "Proszę, wybierz dwie różne wersje." -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "Obecny: %s" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "Przywróć %s" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format msgid "" "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " @@ -517,12 +593,12 @@ msgstr "" "%(model)s \"%(name)s\" został przywrócony z powodzeniem. Możesz edytować go " "ponownie poniżej." -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "Odzyskaj %s" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format msgid "" "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " @@ -531,7 +607,7 @@ msgstr "" "%(model)s \"%(name)s\" został z powodzeniem odzyskany. Możesz edytować go " "ponownie poniżej." -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "Strona nie została odnaleziona" @@ -539,9 +615,10 @@ msgstr "Strona nie została odnaleziona" msgid "We're sorry, but the requested page could not be found." msgstr "Przepraszamy, ale żądana strona nie została odnaleziona." -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:54 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -552,7 +629,7 @@ msgstr "Przepraszamy, ale żądana strona nie została odnaleziona." #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:462 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "Home" @@ -577,18 +654,6 @@ msgstr "" "wkrótce powienien zostać naprawiony. Dziękujemy za wyrozumiałość i " "cierpliwość." -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "Witaj, " - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "Wyloguj" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." -msgstr "Nie masz uprawnień by edytować cokolwiek." - #: templates/xadmin/auth/password_reset/complete.html:11 #: templates/xadmin/auth/password_reset/done.html:11 msgid "Password reset successful" @@ -716,19 +781,32 @@ msgstr "Wpisz Twoje nowe hasło." msgid "Enter a new password for the user %(username)s." msgstr "Wpisz nowe hasło dla użytkownika %(username)s." +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "Witaj, " + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "Wyloguj" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "Nie masz uprawnień by edytować cokolwiek." + #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "Tematy" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "Szukaj" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "Dodaj" @@ -746,7 +824,7 @@ msgstr "Następny krok" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "Zapisz" @@ -792,8 +870,8 @@ msgstr "Kliknij tutaj, aby wybrać wszystkie obiekty na wszystkich stronach" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" -msgstr "Wybierz wszystkie %(total_count)s %(module_name)s" +msgid "Select all %(total_count)s %(model_name)s" +msgstr "Wybierz wszystkie %(total_count)s %(model_name)s" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 msgid "Clear selection" @@ -843,8 +921,12 @@ msgstr "Wyczyść odświeżanie" msgid "Every %(t)s seconds" msgstr "Co każde %(t)s sekund" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "Null" @@ -882,7 +964,7 @@ msgstr "dzień" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "Zatwierdź" @@ -903,7 +985,13 @@ msgstr "Od" msgid "To" msgstr "Do" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +#, fuzzy +#| msgid "Select Date" +msgid "Select" +msgstr "Wybierz datę" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "Wyczyść" @@ -958,7 +1046,7 @@ msgstr "Pokaż wszystkie" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "Zapisuję.." @@ -975,7 +1063,7 @@ msgid "Save and continue editing" msgstr "Zapisz i kontynuuj edycję" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "Usuń" @@ -1247,123 +1335,147 @@ msgstr "Opcje widgetów" msgid "Save changes" msgstr "Zapisz zmiany" -#: views/base.py:443 +#: views/base.py:315 msgid "Django Xadmin" msgstr "Django Xadmin" -#: views/base.py:444 -msgid "my-company.inc 2013" +#: views/base.py:316 +#, fuzzy +#| msgid "my-company.inc 2013" +msgid "my-company.inc" msgstr "moja-firma.inc 2013" -#: views/dashboard.py:185 +#: views/dashboard.py:186 msgid "Widget ID" msgstr "ID widgetu" -#: views/dashboard.py:186 +#: views/dashboard.py:187 msgid "Widget Title" msgstr "Tytuł widgetu" -#: views/dashboard.py:249 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." msgstr "Widget treści HTML, możesz wpisać dowolną treść HTMLową w ten widget." -#: views/dashboard.py:252 +#: views/dashboard.py:255 msgid "Html Content" msgstr "Treść HTML" -#: views/dashboard.py:315 +#: views/dashboard.py:318 msgid "Target Model" msgstr "Model docelowy" -#: views/dashboard.py:366 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." msgstr "Widget szybkich przycisków, pozwala szybko otworzyć dowolna stronę." -#: views/dashboard.py:368 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "Szybkie przyciski" -#: views/dashboard.py:413 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "Dowolny widget listy obiektów." -#: views/dashboard.py:453 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "Dodaj dowolny widget modelu obiektu." -#: views/dashboard.py:488 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "Dashboard" -#: views/dashboard.py:629 +#: views/dashboard.py:633 #, python-format msgid "%s Dashboard" msgstr "%s Dashboard" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "%(name)s \"%(obj)s\" został usunięty z powodzeniem." -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "Inne pola" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "Szczegóły %s" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, fuzzy, python-format +#| msgid "Change %s" +msgid "Changed %s." +msgstr "Zmień %s" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "%(name)s \"%(obj)s\" został dodany z sukcesem." -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "Możesz edytować to powtórnie poniżej." -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "Możesz dodać kolejny %s poniżej." -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "Zmień %s" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "%(name)s \"%(obj)s\" został zmieniony z powodzeniem." -#: views/form.py:164 +#: views/form.py:165 #, python-format msgid "The %s was changed successfully." msgstr "%s został z sukcesem zmieniony." -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "Błąd bazy danych" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "Lista %s" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "Sortuj ASC" -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "Sortuj DESC" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "Anuluj sortowanie" #: views/website.py:16 msgid "Main Dashboard" msgstr "Główny Dashboard" + +#: widgets.py:48 +msgid "Now" +msgstr "Teraz" diff --git a/xadmin/locale/pt_BR/LC_MESSAGES/django.mo b/xadmin/locale/pt_BR/LC_MESSAGES/django.mo index 890ff8c36..0187836e1 100644 Binary files a/xadmin/locale/pt_BR/LC_MESSAGES/django.mo and b/xadmin/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/pt_BR/LC_MESSAGES/django.po b/xadmin/locale/pt_BR/LC_MESSAGES/django.po index e07295cdd..31d6ed00c 100644 --- a/xadmin/locale/pt_BR/LC_MESSAGES/django.po +++ b/xadmin/locale/pt_BR/LC_MESSAGES/django.po @@ -11,63 +11,76 @@ msgid "" msgstr "" "Project-Id-Version: xadmin-core\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-10 10:31+0800\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: 2013-11-20 10:21+0000\n" "Last-Translator: gladson \n" -"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/xadmin/language/pt_BR/)\n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/" +"xadmin/language/pt_BR/)\n" "Language: pt_BR\n" "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" -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "Tudo" -#: filters.py:158 plugins/export.py:117 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "Sim" -#: filters.py:159 plugins/export.py:117 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "Não" -#: filters.py:173 +#: filters.py:175 msgid "Unknown" msgstr "Desconhecido" -#: filters.py:265 +#: filters.py:267 msgid "Any date" msgstr "Qualquer data" -#: filters.py:266 +#: filters.py:268 msgid "Has date" msgstr "Tem data" -#: filters.py:269 +#: filters.py:271 msgid "Has no date" msgstr "Não tem data" -#: filters.py:272 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "Hoje" -#: filters.py:276 +#: filters.py:278 msgid "Past 7 days" msgstr "Passados 7 dias" -#: filters.py:280 +#: filters.py:282 msgid "This month" msgstr "Este mês" -#: filters.py:284 +#: filters.py:286 msgid "This year" msgstr "Este ano" #: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." -msgstr "Por favor, insira o nome de usuário e a senha corretamente para sua conta pessoal. Perceba que ambos os campos são case-sensitive." +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." +msgstr "" +"Por favor, insira o nome de usuário e a senha corretamente para sua conta " +"pessoal. Perceba que ambos os campos são case-sensitive." #: forms.py:21 msgid "Please log in again, because your session has expired." @@ -76,110 +89,177 @@ msgstr "Por favor faça login novamente, porque a sua sessão expirou." #: forms.py:41 #, python-format msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "O seu endereço de e-mail não é seu nome de usuário. Tente '% s' em seu lugar." +msgstr "" +"O seu endereço de e-mail não é seu nome de usuário. Tente '% s' em seu lugar." -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "Título" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "Usuário" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "Nome da Url" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "String de Consulta" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "É Compartilhada" -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "Favorito" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "Favoritos" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "Configuração da chave" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "Configurações de conteúdo" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "Configuração de usuário" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "Configurações do Usuário" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "Página" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "Tipo de Widget" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "Parâmetros do Widget" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "Widget do Usuário" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "Widgets do Usuário" -#: widgets.py:48 -msgid "Now" -msgstr "Agora" +#: models.py:142 +#, fuzzy +#| msgid "Date/time" +msgid "action time" +msgstr "Data/Hora" + +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" + +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +#, fuzzy +#| msgid "Change %s" +msgid "change message" +msgstr "Alterar %s" + +#: models.py:164 +#, fuzzy +#| msgid "log in" +msgid "log entry" +msgstr "Entrar" + +#: models.py:165 +msgid "log entries" +msgstr "" -#: plugins/actions.py:54 +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, fuzzy, python-format +#| msgid "Change one %(objects_name)s" +#| msgid_plural "Batch change %(counter)s %(objects_name)s" +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "Alterar um %(objects_name)s" + +#: models.py:180 +#, fuzzy, python-format +#| msgid "Related Objects" +msgid "Deleted \"%(object)s.\"" +msgstr "Objetos Relacionados" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "Excluir selecionado %(verbose_name_plural)s" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, fuzzy, python-format +#| msgid "Successfully deleted %(count)d %(items)s." +msgid "Batch delete %(count)d %(items)s." +msgstr "Excluído com sucesso %(count)d %(items)s." + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "Excluído com sucesso %(count)d %(items)s." -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "Não é possível excluir %(name)s" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "Você tem certeza?" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" msgstr[0] "Todos %(total_count)s selecionados" msgstr[1] "Todos %(total_count)s selecionados" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "0 de %(cnt)s selecionados" -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." -msgstr "Os itens devem ser selecionados, a fim de executar ações sobre eles. Não há itens alterados." +#: plugins/actions.py:179 plugins/actions.py:189 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Os itens devem ser selecionados, a fim de executar ações sobre eles. Não há " +"itens alterados." #: plugins/aggregation.py:14 msgid "Min" @@ -247,20 +327,20 @@ msgstr "Status" msgid "Permission Name" msgstr "Permissões" -#: plugins/auth.py:159 +#: plugins/auth.py:167 msgid "Change Password" msgstr "Alterar Senha" -#: plugins/auth.py:189 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "Alterar senha: %s" -#: plugins/auth.py:214 plugins/auth.py:246 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "Senha alterada com sucesso." -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -275,7 +355,7 @@ msgstr "Alterar este campo" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "Alterar lote selecionado %(verbose_name_plural)s" -#: plugins/batch.py:90 +#: plugins/batch.py:89 #, python-format msgid "Successfully change %(count)d %(items)s." msgstr "Alterado com sucesso %(count)d %(items)s." @@ -285,19 +365,20 @@ msgstr "Alterado com sucesso %(count)d %(items)s." msgid "Batch change %s" msgstr "Lote alterado %s" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 msgid "bookmark" msgstr "Favorito" -#: plugins/bookmark.py:173 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." -msgstr "Widget de Marcador, pode mostrar a lista de marcadores do usuário no widget" +msgstr "" +"Widget de Marcador, pode mostrar a lista de marcadores do usuário no widget" -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "Mostrar modelos gráfico simples." -#: plugins/chart.py:49 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "%s Gráficos" @@ -345,27 +426,27 @@ msgid_plural "%(count)s comments were successfully %(action)s." msgstr[0] "" msgstr[1] "" -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "Detalhes de %s" -#: plugins/editable.py:47 +#: plugins/editable.py:46 #, python-format msgid "Enter %s" msgstr "Entrar %s" -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "%(name)s objeto com chave primária %(key)r não existe." -#: plugins/export.py:87 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "Planilha" -#: plugins/filters.py:125 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "Filtrar erro: %s" @@ -390,11 +471,11 @@ msgstr "Baixar" msgid "Change:" msgstr "Alterar:" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "Tabela" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "Miniaturas" @@ -402,20 +483,26 @@ msgstr "Miniaturas" msgid "Forgotten your password or username?" msgstr "Esqueceu seu nome de usuário ou senha?" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "Criar novo %s" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "Objetos Relacionados" -#: plugins/relfield.py:29 plugins/topnav.py:35 +#: plugins/relfield.py:29 plugins/topnav.py:38 #, python-format msgid "Search %s" msgstr "Pesquisar %s" +#: plugins/relfield.py:67 +#, fuzzy, python-format +#| msgid "Select Date" +msgid "Select %s" +msgstr "Selecionar Data" + #: plugins/themes.py:47 msgid "Default" msgstr "Padrão" @@ -432,88 +519,96 @@ msgstr "Bootstrap2" msgid "Bootstrap 2.x theme" msgstr "Tema Bootstrap 2.x" -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "Adicionar %s" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "Versão inicial." -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "Alterar versão." -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "Reverter versão." -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "Recuperar versão." -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "Excluídos %(verbose_name)s." -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "Recuperar" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "Histórico" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "Recuperar deletado %(name)s" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "Alterar histórico: %s" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "É necessário selecionar 2 versões" -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "Por favor selecione duas versões diferentes." -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "Atual: %s" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "Revertido: %s" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." -msgstr "%(model)s \"%(name)s\" foi revertido(a) com sucesso. Você pode editá-lo(a) novamente abaixo." +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." +msgstr "" +"%(model)s \"%(name)s\" foi revertido(a) com sucesso. Você pode editá-lo(a) " +"novamente abaixo." -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "Recuperar %s" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." -msgstr "%(model)s \"%(name)s\" foi recuperado(a) com sucesso. Você pode editá-lo(a) novamente abaixo." +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." +msgstr "" +"%(model)s \"%(name)s\" foi recuperado(a) com sucesso. Você pode editá-lo(a) " +"novamente abaixo." -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "Página não encontrada" @@ -521,9 +616,10 @@ msgstr "Página não encontrada" msgid "We're sorry, but the requested page could not be found." msgstr "Pedimos desculpas, mas a página solicitada não foi encontrada." -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -534,7 +630,7 @@ msgstr "Pedimos desculpas, mas a página solicitada não foi encontrada." #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "Início" @@ -551,20 +647,12 @@ msgid "Server Error (500)" msgstr "Erro do Servidor (500)" #: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "Ocorreu um erro. E foi relatado aos administradores do site via e-mail e deve ser corrigido em breve. Obrigado por sua paciência." - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "Bem-Vindo," - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "Sair" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." -msgstr "Você não tem permissão para editar nada." +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." +msgstr "" +"Ocorreu um erro. E foi relatado aos administradores do site via e-mail e " +"deve ser corrigido em breve. Obrigado por sua paciência." #: templates/xadmin/auth/password_reset/complete.html:11 #: templates/xadmin/auth/password_reset/done.html:11 @@ -584,8 +672,12 @@ msgid "Enter new password" msgstr "Digite a nova senha" #: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." -msgstr "Por favor forneça sua nova senha 2 vezes para que possamos verificar se a mesma foi digitada corretamente." +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." +msgstr "" +"Por favor forneça sua nova senha 2 vezes para que possamos verificar se a " +"mesma foi digitada corretamente." #: templates/xadmin/auth/password_reset/confirm.html:19 msgid "Change my password" @@ -596,17 +688,29 @@ msgid "Password reset unsuccessful" msgstr "A senha foi redefinida com sucesso" #: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." -msgstr "O link de redefinição de senha era inválida, possivelmente porque ele já foi usado. Por favor, solicite uma nova redefinição de senha." +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." +msgstr "" +"O link de redefinição de senha era inválida, possivelmente porque ele já foi " +"usado. Por favor, solicite uma nova redefinição de senha." #: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." -msgstr "Nós enviamos um e-mail com instruções para configurar sua senha para o endereço de e-mail que você solicitou. Você deve recebê-lo em breve." +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." +msgstr "" +"Nós enviamos um e-mail com instruções para configurar sua senha para o " +"endereço de e-mail que você solicitou. Você deve recebê-lo em breve." #: templates/xadmin/auth/password_reset/email.html:2 #, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." -msgstr "Você está recebendo este e-mail porque você pediu uma redefinição de senha para sua conta de usuário em %(site_name)s." +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." +msgstr "" +"Você está recebendo este e-mail porque você pediu uma redefinição de senha " +"para sua conta de usuário em %(site_name)s." #: templates/xadmin/auth/password_reset/email.html:4 msgid "Please go to the following page and choose a new password:" @@ -630,8 +734,12 @@ msgid "Password reset" msgstr "Redefinição de senha" #: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." -msgstr "Esqueceu sua senha? Forneça seu endereço de e-mail abaixo, e nós lhe enviaremos instruções para definir uma nova." +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." +msgstr "" +"Esqueceu sua senha? Forneça seu endereço de e-mail abaixo, e nós lhe " +"enviaremos instruções para definir uma nova." #: templates/xadmin/auth/password_reset/form.html:25 msgid "E-mail address:" @@ -642,8 +750,12 @@ msgid "Reset my password" msgstr "Redefinir minha senha" #: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." -msgstr "Primeiro, insira um nome de usuário e senha. Então, você vai ser capaz de editar mais opções do usuário." +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." +msgstr "" +"Primeiro, insira um nome de usuário e senha. Então, você vai ser capaz de " +"editar mais opções do usuário." #: templates/xadmin/auth/user/add_form.html:8 msgid "Enter a username and password." @@ -667,19 +779,32 @@ msgstr "Digite sua nova senha." msgid "Enter a new password for the user %(username)s." msgstr "Digite uma nova senha para o usuário %(username)s." +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "Bem-Vindo," + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "Sair" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "Você não tem permissão para editar nada." + #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "Temas" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "Pesquisar" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "Adicionar" @@ -697,7 +822,7 @@ msgstr "Próximo passo" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "Gravar" @@ -743,8 +868,8 @@ msgstr "Clique aqui para selecionar os objetos através de todas as páginas" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" -msgstr "Selecionar todos %(total_count)s %(module_name)s" +msgid "Select all %(total_count)s %(model_name)s" +msgstr "Selecionar todos %(total_count)s %(model_name)s" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 msgid "Clear selection" @@ -757,26 +882,27 @@ msgstr "Gráficos" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:47 msgid "Export" msgstr "Exportar" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 msgid "Export with table header." msgstr "Exportar com cabeçalho da tabela" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:38 msgid "Export with format." msgstr "Exportar com o formato." -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:42 msgid "Export all data." msgstr "Exportar todos os dados." -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:46 +#: templates/xadmin/widgets/base.html:41 msgid "Close" msgstr "Fechar" @@ -793,8 +919,12 @@ msgstr "Atualização Limpa" msgid "Every %(t)s seconds" msgstr "A cada %(t)s segundos" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "Nulo" @@ -832,7 +962,7 @@ msgstr "dia" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "Aplicar" @@ -853,7 +983,13 @@ msgstr "De" msgid "To" msgstr "Para" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +#, fuzzy +#| msgid "Select Date" +msgid "Select" +msgstr "Selecionar Data" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "Limpar" @@ -886,7 +1022,7 @@ msgid "Choose" msgstr "Escolher" #: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 +#: templates/xadmin/widgets/base.html:40 msgid "Remove" msgstr "Remover" @@ -908,7 +1044,7 @@ msgstr "Mostrar Tudo" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "Salvando..." @@ -925,7 +1061,7 @@ msgid "Save and continue editing" msgstr "Gravar e continuar editando" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "Excluir" @@ -956,8 +1092,14 @@ msgid "Add Widget" msgstr "Adicionar Widget" #: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." -msgstr "Algo está errado com a instalação do banco de dados. Certifique-se que as tabelas foram criadas apropriadamente, e certifique-se que o banco de dados pode ser lido pelo usuário apropriado." +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." +msgstr "" +"Algo está errado com a instalação do banco de dados. Certifique-se que as " +"tabelas foram criadas apropriadamente, e certifique-se que o banco de dados " +"pode ser lido pelo usuário apropriado." #: templates/xadmin/views/logged_out.html:16 msgid "Logout Success" @@ -998,18 +1140,32 @@ msgstr "Editar" #: templates/xadmin/views/model_delete_confirm.html:11 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" -msgstr "Excluir o %(verbose_name)s '%(escaped_object)s' resultaria na exclusão dos objetos relacionados, mas a sua conta não tem permissão para excluir os seguintes tipos de objetos:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" +msgstr "" +"Excluir o %(verbose_name)s '%(escaped_object)s' resultaria na exclusão dos " +"objetos relacionados, mas a sua conta não tem permissão para excluir os " +"seguintes tipos de objetos:" #: templates/xadmin/views/model_delete_confirm.html:19 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" -msgstr "Excluir o %(verbose_name)s '%(escaped_object)s' exigiria exclusão dos seguintes objetos protegidos relacionados:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" +msgstr "" +"Excluir o %(verbose_name)s '%(escaped_object)s' exigiria exclusão dos " +"seguintes objetos protegidos relacionados:" #: templates/xadmin/views/model_delete_confirm.html:27 #, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" -msgstr "Tem certeza de que deseja excluir %(verbose_name)s \"%(escaped_object)s\"? Todos os seguintes itens relacionados serão excluídos:" +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" +msgstr "" +"Tem certeza de que deseja excluir %(verbose_name)s \"%(escaped_object)s\"? " +"Todos os seguintes itens relacionados serão excluídos:" #: templates/xadmin/views/model_delete_confirm.html:34 #: templates/xadmin/views/model_delete_selected_confirm.html:49 @@ -1027,18 +1183,32 @@ msgstr "Excluir múltiplos objetos" #: templates/xadmin/views/model_delete_selected_confirm.html:18 #, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" -msgstr "Excluir o %(objects_name)s selecionado resultaria na exclusão de objetos relacionados, mas a sua conta não tem permissão para excluir os seguintes tipos de objetos:" +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"Excluir o %(objects_name)s selecionado resultaria na exclusão de objetos " +"relacionados, mas a sua conta não tem permissão para excluir os seguintes " +"tipos de objetos:" #: templates/xadmin/views/model_delete_selected_confirm.html:26 #, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" -msgstr "Excluir o %(objects_name)s selecionado exigiria eliminar os seguintes objetos protegidos relacionados:" +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" +msgstr "" +"Excluir o %(objects_name)s selecionado exigiria eliminar os seguintes " +"objetos protegidos relacionados:" #: templates/xadmin/views/model_delete_selected_confirm.html:34 #, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" -msgstr "Tem certeza de que deseja excluir o %(objects_name)s selecionado? Todos os seguintes objetos e seus itens relacionados serão excluídos:" +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" +msgstr "" +"Tem certeza de que deseja excluir o %(objects_name)s selecionado? Todos os " +"seguintes objetos e seus itens relacionados serão excluídos:" #: templates/xadmin/views/model_history.html:26 msgid "Diff" @@ -1062,8 +1232,12 @@ msgid "Diff Select Versions" msgstr "Comparar Versões Selecionadas" #: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." -msgstr "Este objeto não possui um histórico de mudança. Provavelmente não foi adicionado pelo site de administração." +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." +msgstr "" +"Este objeto não possui um histórico de mudança. Provavelmente não foi " +"adicionado pelo site de administração." #: templates/xadmin/views/model_list.html:29 #, python-format @@ -1089,8 +1263,11 @@ msgid "Press the recover button below to recover this version of the object." msgstr "Clique no botão recuperar abaixo para recuperar esta versão do objeto." #: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." -msgstr "Escolha a data a partir da lista abaixo para recuperar a versão excluída do objeto." +msgid "" +"Choose a date from the list below to recover a deleted version of an object." +msgstr "" +"Escolha a data a partir da lista abaixo para recuperar a versão excluída do " +"objeto." #: templates/xadmin/views/recover_list.html:39 msgid "There are no deleted objects to recover." @@ -1130,7 +1307,8 @@ msgstr "Reverter %(verbose_name)s" #: templates/xadmin/views/revision_form.html:21 msgid "Press the revert button below to revert to this version of the object." -msgstr "Clique no botão reverter abaixo para reverter para esta versão do objeto." +msgstr "" +"Clique no botão reverter abaixo para reverter para esta versão do objeto." #: templates/xadmin/views/revision_form.html:27 msgid "Revert this revision" @@ -1148,127 +1326,154 @@ msgstr "Sucesso na adição, clique editar para editar." msgid "Quick Add" msgstr "Adição Rápida" -#: templates/xadmin/widgets/base.html:30 +#: templates/xadmin/widgets/base.html:31 msgid "Widget Options" msgstr "Opções do Widget" -#: templates/xadmin/widgets/base.html:41 +#: templates/xadmin/widgets/base.html:42 msgid "Save changes" msgstr "Gravar alterações" -#: views/base.py:430 +#: views/base.py:315 msgid "Django Xadmin" msgstr "Django Xadmin" -#: views/dashboard.py:185 +#: views/base.py:316 +msgid "my-company.inc" +msgstr "" + +#: views/dashboard.py:186 msgid "Widget ID" msgstr "ID do Widget" -#: views/dashboard.py:186 +#: views/dashboard.py:187 msgid "Widget Title" msgstr "Título do Widget" -#: views/dashboard.py:248 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." -msgstr "Widget de Conteúdo HTML, pode-se escrever qualquer conteúdo html no widget." +msgstr "" +"Widget de Conteúdo HTML, pode-se escrever qualquer conteúdo html no widget." -#: views/dashboard.py:251 +#: views/dashboard.py:255 msgid "Html Content" msgstr "Conteúdo HTML" -#: views/dashboard.py:314 +#: views/dashboard.py:318 msgid "Target Model" msgstr "Modelo Alvo" -#: views/dashboard.py:365 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." msgstr "Widget de Botão Rápido, abre rapidamente qualquer página." -#: views/dashboard.py:367 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "Botões Rápidos" -#: views/dashboard.py:408 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "Widget de listagem de Qualquer Objeto" -#: views/dashboard.py:447 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "Widget de adição de qualquer objeto." -#: views/dashboard.py:481 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "Painel" -#: views/dashboard.py:622 +#: views/dashboard.py:633 #, python-format msgid "%s Dashboard" msgstr "%s Painel" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "%(name)s \"%(obj)s\" excluído(a) com sucesso." -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "Outros Campos" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "%s Detalhes" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, fuzzy, python-format +#| msgid "Change %s" +msgid "Changed %s." +msgstr "Alterar %s" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "%(name)s \"%(obj)s\" adicionado(a) com sucesso." -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "Você pode editar novamente abaixo." -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "Você pode adicionar outro(a) %s abaixo." -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "Alterar %s" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "%(name)s \"%(obj)s\" alterado(a) com sucesso." -#: views/form.py:164 +#: views/form.py:165 #, fuzzy, python-format msgid "The %s was changed successfully." msgstr "%(name)s \"%(obj)s\" alterado(a) com sucesso." -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "Erro da base de dados" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "Lista %s" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "Classificação Ascendente" -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "Classificação Descendente" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "Cancelar Classificação" #: views/website.py:16 msgid "Main Dashboard" msgstr "Painel Principal" + +#: widgets.py:48 +msgid "Now" +msgstr "Agora" diff --git a/xadmin/locale/ru_RU/LC_MESSAGES/django.mo b/xadmin/locale/ru_RU/LC_MESSAGES/django.mo index a7f41863b..58d8e7159 100644 Binary files a/xadmin/locale/ru_RU/LC_MESSAGES/django.mo and b/xadmin/locale/ru_RU/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/ru_RU/LC_MESSAGES/django.po b/xadmin/locale/ru_RU/LC_MESSAGES/django.po index 44584cb25..6bdc7947b 100644 --- a/xadmin/locale/ru_RU/LC_MESSAGES/django.po +++ b/xadmin/locale/ru_RU/LC_MESSAGES/django.po @@ -8,63 +8,77 @@ msgid "" msgstr "" "Project-Id-Version: xadmin-core\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-10 10:31+0800\n" +"POT-Creation-Date: 2016-07-20 13:28+0800\n" "PO-Revision-Date: 2013-12-28 19:36+0000\n" "Last-Translator: crazyzubr \n" -"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/xadmin/language/ru_RU/)\n" +"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/xadmin/" +"language/ru_RU/)\n" "Language: ru_RU\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\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" +"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" -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 +#: adminx.py:19 +msgid "Admin Object" +msgstr "" + +#: apps.py:11 +msgid "Administration" +msgstr "" + +#: filters.py:159 filters.py:191 filters.py:407 filters.py:493 filters.py:531 msgid "All" msgstr "Все" -#: filters.py:158 plugins/export.py:117 +#: filters.py:160 plugins/export.py:165 msgid "Yes" msgstr "Да" -#: filters.py:159 plugins/export.py:117 +#: filters.py:161 plugins/export.py:165 msgid "No" msgstr "Нет" -#: filters.py:173 +#: filters.py:175 msgid "Unknown" msgstr "Неизвестно" -#: filters.py:265 +#: filters.py:267 msgid "Any date" msgstr "Любая дата" -#: filters.py:266 +#: filters.py:268 msgid "Has date" msgstr "" -#: filters.py:269 +#: filters.py:271 msgid "Has no date" msgstr "" -#: filters.py:272 widgets.py:30 +#: filters.py:274 widgets.py:30 msgid "Today" msgstr "Сегодня" -#: filters.py:276 +#: filters.py:278 msgid "Past 7 days" msgstr "За последние 7 дней" -#: filters.py:280 +#: filters.py:282 msgid "This month" msgstr "В этом месяце" -#: filters.py:284 +#: filters.py:286 msgid "This year" msgstr "В этом году" #: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." -msgstr "Пожалуйста, введите корректные имя пользователя и пароль для аккаунта. Оба поля могут быть чувствительны к регистру." +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." +msgstr "" +"Пожалуйста, введите корректные имя пользователя и пароль для аккаунта. Оба " +"поля могут быть чувствительны к регистру." #: forms.py:21 msgid "Please log in again, because your session has expired." @@ -75,94 +89,150 @@ msgstr "Пожалуйста, войдите снова, поскольку ва msgid "Your e-mail address is not your username. Try '%s' instead." msgstr "" -#: models.py:47 +#: models.py:48 msgid "Title" msgstr "Заголовок" -#: models.py:48 models.py:87 models.py:106 +#: models.py:49 models.py:88 models.py:107 models.py:149 msgid "user" msgstr "" -#: models.py:49 +#: models.py:50 msgid "Url Name" msgstr "" -#: models.py:51 +#: models.py:52 msgid "Query String" msgstr "Строка запроса" -#: models.py:52 +#: models.py:53 msgid "Is Shared" msgstr "" -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 +#: models.py:66 plugins/bookmark.py:50 plugins/bookmark.py:180 msgid "Bookmark" msgstr "Закладка" -#: models.py:66 +#: models.py:67 msgid "Bookmarks" msgstr "Закладки" -#: models.py:88 +#: models.py:89 msgid "Settings Key" msgstr "" -#: models.py:89 +#: models.py:90 msgid "Settings Content" msgstr "" -#: models.py:101 +#: models.py:102 msgid "User Setting" msgstr "" -#: models.py:102 +#: models.py:103 msgid "User Settings" msgstr "" -#: models.py:107 +#: models.py:108 msgid "Page" msgstr "Страница" -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 +#: models.py:109 views/dashboard.py:82 views/dashboard.py:92 msgid "Widget Type" msgstr "Тип виджета" -#: models.py:109 views/dashboard.py:82 +#: models.py:110 views/dashboard.py:83 msgid "Widget Params" msgstr "Параметры виджета" -#: models.py:136 +#: models.py:137 msgid "User Widget" msgstr "" -#: models.py:137 +#: models.py:138 msgid "User Widgets" msgstr "" -#: widgets.py:48 -msgid "Now" -msgstr "Сейчас" +#: models.py:142 +msgid "action time" +msgstr "" + +#: models.py:151 +msgid "action ip" +msgstr "" + +#: models.py:155 +msgid "content type" +msgstr "" + +#: models.py:158 +msgid "object id" +msgstr "" + +#: models.py:159 +msgid "object repr" +msgstr "" + +#: models.py:160 +msgid "action flag" +msgstr "" + +#: models.py:161 +#, fuzzy +#| msgid "Change %s" +msgid "change message" +msgstr "Изменить %s" + +#: models.py:164 +msgid "log entry" +msgstr "" -#: plugins/actions.py:54 +#: models.py:165 +msgid "log entries" +msgstr "" + +#: models.py:173 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "" + +#: models.py:175 +#, python-format +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "" + +#: models.py:180 +#, fuzzy, python-format +#| msgid "Related Objects" +msgid "Deleted \"%(object)s.\"" +msgstr "Связанные объекты" + +#: plugins/actions.py:57 #, python-format msgid "Delete selected %(verbose_name_plural)s" msgstr "Удалить выбранные %(verbose_name_plural)s" -#: plugins/actions.py:67 +#: plugins/actions.py:72 +#, fuzzy, python-format +#| msgid "Successfully deleted %(count)d %(items)s." +msgid "Batch delete %(count)d %(items)s." +msgstr "Успешно удалены %(count)d %(items)s." + +#: plugins/actions.py:78 #, python-format msgid "Successfully deleted %(count)d %(items)s." msgstr "Успешно удалены %(count)d %(items)s." -#: plugins/actions.py:99 views/delete.py:68 +#: plugins/actions.py:110 views/delete.py:70 #, python-format msgid "Cannot delete %(name)s" msgstr "Не удается удалить %(name)s" -#: plugins/actions.py:101 views/delete.py:71 +#: plugins/actions.py:112 views/delete.py:73 msgid "Are you sure?" msgstr "Вы уверены?" -#: plugins/actions.py:147 +#: plugins/actions.py:158 #, python-format msgid "%(total_count)s selected" msgid_plural "All %(total_count)s selected" @@ -170,14 +240,18 @@ msgstr[0] "Выбран %(total_count)s" msgstr[1] "Выбраны все %(total_count)s" msgstr[2] "Выбраны все %(total_count)s" -#: plugins/actions.py:151 +#: plugins/actions.py:162 #, python-format msgid "0 of %(cnt)s selected" msgstr "Выбрано 0 объектов из %(cnt)s " -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." -msgstr "Чтобы произвести действия над объектами, необходимо их выбрать. Объекты не были изменены." +#: plugins/actions.py:179 plugins/actions.py:189 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "" +"Чтобы произвести действия над объектами, необходимо их выбрать. Объекты не " +"были изменены." #: plugins/aggregation.py:14 msgid "Min" @@ -245,20 +319,20 @@ msgstr "Статус" msgid "Permission Name" msgstr "Права" -#: plugins/auth.py:159 +#: plugins/auth.py:167 msgid "Change Password" msgstr "Изменить пароль" -#: plugins/auth.py:189 +#: plugins/auth.py:198 #, python-format msgid "Change password: %s" msgstr "Изменить пароль: %s" -#: plugins/auth.py:214 plugins/auth.py:246 +#: plugins/auth.py:223 plugins/auth.py:255 msgid "Password changed successfully." msgstr "Пароль успешно изменен" -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 +#: plugins/auth.py:242 templates/xadmin/auth/user/change_password.html:11 #: templates/xadmin/auth/user/change_password.html:22 #: templates/xadmin/auth/user/change_password.html:55 msgid "Change password" @@ -273,7 +347,7 @@ msgstr "" msgid "Batch Change selected %(verbose_name_plural)s" msgstr "" -#: plugins/batch.py:90 +#: plugins/batch.py:89 #, python-format msgid "Successfully change %(count)d %(items)s." msgstr "" @@ -283,19 +357,19 @@ msgstr "" msgid "Batch change %s" msgstr "" -#: plugins/bookmark.py:171 +#: plugins/bookmark.py:173 msgid "bookmark" msgstr "" -#: plugins/bookmark.py:173 +#: plugins/bookmark.py:176 msgid "Bookmark Widget, can show user's bookmark list data in widget." msgstr "" -#: plugins/chart.py:24 +#: plugins/chart.py:25 msgid "Show models simple chart." msgstr "" -#: plugins/chart.py:49 +#: plugins/chart.py:51 #, python-format msgid "%s Charts" msgstr "" @@ -345,27 +419,27 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" -#: plugins/details.py:52 views/list.py:576 +#: plugins/details.py:52 views/list.py:578 #, python-format msgid "Details of %s" msgstr "Детали %s" -#: plugins/editable.py:47 +#: plugins/editable.py:46 #, python-format msgid "Enter %s" msgstr "" -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 +#: plugins/editable.py:73 views/dashboard.py:649 views/delete.py:27 +#: views/detail.py:145 views/edit.py:454 #, python-format msgid "%(name)s object with primary key %(key)r does not exist." msgstr "" -#: plugins/export.py:87 +#: plugins/export.py:98 plugins/export.py:135 msgid "Sheet" msgstr "Лист" -#: plugins/filters.py:125 +#: plugins/filters.py:133 plugins/quickfilter.py:141 #, python-format msgid "Filtering error: %s" msgstr "" @@ -390,11 +464,11 @@ msgstr "Загрузить" msgid "Change:" msgstr "Изменить:" -#: plugins/layout.py:15 +#: plugins/layout.py:16 msgid "Table" msgstr "" -#: plugins/layout.py:21 +#: plugins/layout.py:22 msgid "Thumbnails" msgstr "" @@ -402,20 +476,25 @@ msgstr "" msgid "Forgotten your password or username?" msgstr "" -#: plugins/quickform.py:77 +#: plugins/quickform.py:79 #, python-format msgid "Create New %s" msgstr "" -#: plugins/relate.py:73 +#: plugins/relate.py:104 msgid "Related Objects" msgstr "Связанные объекты" -#: plugins/relfield.py:29 plugins/topnav.py:35 +#: plugins/relfield.py:29 plugins/topnav.py:38 #, python-format msgid "Search %s" msgstr "Поиск %s" +#: plugins/relfield.py:67 +#, python-format +msgid "Select %s" +msgstr "" + #: plugins/themes.py:47 msgid "Default" msgstr "" @@ -432,88 +511,92 @@ msgstr "" msgid "Bootstrap 2.x theme" msgstr "" -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 +#: plugins/topnav.py:62 views/dashboard.py:465 views/edit.py:387 +#: views/edit.py:396 #, python-format msgid "Add %s" msgstr "Добавить %s" -#: plugins/xversion.py:130 +#: plugins/xversion.py:106 msgid "Initial version." msgstr "" -#: plugins/xversion.py:132 +#: plugins/xversion.py:108 msgid "Change version." msgstr "" -#: plugins/xversion.py:134 +#: plugins/xversion.py:110 msgid "Revert version." msgstr "" -#: plugins/xversion.py:136 +#: plugins/xversion.py:112 msgid "Rercover version." msgstr "" -#: plugins/xversion.py:138 +#: plugins/xversion.py:114 #, python-format msgid "Deleted %(verbose_name)s." msgstr "" -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 +#: plugins/xversion.py:127 templates/xadmin/views/recover_form.html:26 msgid "Recover" msgstr "" -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 +#: plugins/xversion.py:143 templates/xadmin/views/model_history.html:11 #: templates/xadmin/views/revision_diff.html:11 #: templates/xadmin/views/revision_form.html:15 msgid "History" msgstr "История" -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 +#: plugins/xversion.py:194 templates/xadmin/views/recover_form.html:14 #: templates/xadmin/views/recover_list.html:10 #, python-format msgid "Recover deleted %(name)s" msgstr "" -#: plugins/xversion.py:263 +#: plugins/xversion.py:238 #, python-format msgid "Change history: %s" msgstr "" -#: plugins/xversion.py:313 +#: plugins/xversion.py:288 msgid "Must select two versions." msgstr "Необходимо выбрать две версии." -#: plugins/xversion.py:321 +#: plugins/xversion.py:296 msgid "Please select two different versions." msgstr "Пожалуйста, выберите две различные версии." -#: plugins/xversion.py:408 plugins/xversion.py:516 +#: plugins/xversion.py:383 plugins/xversion.py:500 #, python-format msgid "Current: %s" msgstr "" -#: plugins/xversion.py:440 +#: plugins/xversion.py:424 #, python-format msgid "Revert %s" msgstr "" -#: plugins/xversion.py:456 +#: plugins/xversion.py:440 #, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." msgstr "" -#: plugins/xversion.py:477 +#: plugins/xversion.py:461 #, python-format msgid "Recover %s" msgstr "" -#: plugins/xversion.py:493 +#: plugins/xversion.py:477 #, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." msgstr "" -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 +#: templates/xadmin/404.html:4 templates/xadmin/404.html:8 msgid "Page not found" msgstr "Страница не найдена" @@ -521,9 +604,10 @@ msgstr "Страница не найдена" msgid "We're sorry, but the requested page could not be found." msgstr "" -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 +#: templates/xadmin/500.html:7 #: templates/xadmin/auth/user/change_password.html:10 #: templates/xadmin/auth/user/change_password.html:15 +#: templates/xadmin/base_site.html:53 #: templates/xadmin/includes/sitemenu_default.html:7 #: templates/xadmin/views/app_index.html:9 #: templates/xadmin/views/batch_change_form.html:9 @@ -534,7 +618,7 @@ msgstr "" #: templates/xadmin/views/recover_form.html:8 #: templates/xadmin/views/recover_list.html:8 #: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 +#: templates/xadmin/views/revision_form.html:8 views/base.py:473 msgid "Home" msgstr "Главная" @@ -551,19 +635,9 @@ msgid "Server Error (500)" msgstr "" #: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "" - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "" - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "Выйти" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." msgstr "" #: templates/xadmin/auth/password_reset/complete.html:11 @@ -584,8 +658,12 @@ msgid "Enter new password" msgstr "Введите новый пароль:" #: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." -msgstr "Пожалуйста, введите новый пароль дважды, чтобы мы могли убедиться в правильности написания." +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." +msgstr "" +"Пожалуйста, введите новый пароль дважды, чтобы мы могли убедиться в " +"правильности написания." #: templates/xadmin/auth/password_reset/confirm.html:19 msgid "Change my password" @@ -596,17 +674,30 @@ msgid "Password reset unsuccessful" msgstr "Ошибка восстановления пароля" #: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." -msgstr "Неверная ссылка для восстановления пароля. Возможно, ей уже воспользовались. Пожалуйста, попробуйте восстановить пароль еще раз." +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." +msgstr "" +"Неверная ссылка для восстановления пароля. Возможно, ей уже воспользовались. " +"Пожалуйста, попробуйте восстановить пароль еще раз." #: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." -msgstr "Мы отправили инструкцию по восстановлению пароля на указанный вами адрес электронной почты. Вы должны её вскоре получить." +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." +msgstr "" +"Мы отправили инструкцию по восстановлению пароля на указанный вами адрес " +"электронной почты. Вы должны её вскоре получить." #: templates/xadmin/auth/password_reset/email.html:2 #, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." -msgstr "Вы получили это письмо, потому что вы (или кто-то другой) запросили восстановление пароля от учётной записи на сайте %(site_name)s, которая связана с этим адресом электронной почты." +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." +msgstr "" +"Вы получили это письмо, потому что вы (или кто-то другой) запросили " +"восстановление пароля от учётной записи на сайте %(site_name)s, которая " +"связана с этим адресом электронной почты." #: templates/xadmin/auth/password_reset/email.html:4 msgid "Please go to the following page and choose a new password:" @@ -630,7 +721,9 @@ msgid "Password reset" msgstr "Восстановление пароля" #: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." msgstr "" #: templates/xadmin/auth/password_reset/form.html:25 @@ -642,7 +735,9 @@ msgid "Reset my password" msgstr "" #: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." msgstr "" #: templates/xadmin/auth/user/add_form.html:8 @@ -668,19 +763,32 @@ msgstr "" msgid "Enter a new password for the user %(username)s." msgstr "" +#: templates/xadmin/base_site.html:18 +msgid "Welcome," +msgstr "" + +#: templates/xadmin/base_site.html:24 +msgid "Log out" +msgstr "Выйти" + +#: templates/xadmin/base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "" + #: templates/xadmin/blocks/comm.top.theme.html:4 msgid "Themes" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:8 +#: templates/xadmin/blocks/comm.top.topnav.html:9 +#: templates/xadmin/blocks/model_list.nav_form.search_form.html:8 #: templates/xadmin/filters/char.html:7 #: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 +#: templates/xadmin/filters/fk_search.html:16 #: templates/xadmin/filters/number.html:7 msgid "Search" msgstr "" -#: templates/xadmin/blocks/comm.top.topnav.html:22 +#: templates/xadmin/blocks/comm.top.topnav.html:23 msgid "Add" msgstr "" @@ -698,7 +806,7 @@ msgstr "" #: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Save" msgstr "" @@ -744,7 +852,7 @@ msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 #, python-format -msgid "Select all %(total_count)s %(module_name)s" +msgid "Select all %(total_count)s %(model_name)s" msgstr "" #: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 @@ -758,26 +866,27 @@ msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:47 msgid "Export" msgstr "" #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 msgid "Export with table header." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 #: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:38 msgid "Export with format." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:42 msgid "Export all data." msgstr "" -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 +#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:46 +#: templates/xadmin/widgets/base.html:41 msgid "Close" msgstr "" @@ -794,8 +903,12 @@ msgstr "" msgid "Every %(t)s seconds" msgstr "" -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 +#: templates/xadmin/blocks/model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "" + +#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:23 +#: views/edit.py:102 views/list.py:29 msgid "Null" msgstr "" @@ -833,7 +946,7 @@ msgstr "" #: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 #: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 +#: templates/xadmin/filters/fk_search.html:24 #: templates/xadmin/filters/number.html:37 msgid "Apply" msgstr "" @@ -854,7 +967,11 @@ msgstr "" msgid "To" msgstr "" -#: templates/xadmin/filters/fk_search.html:18 +#: templates/xadmin/filters/fk_search.html:14 +msgid "Select" +msgstr "" + +#: templates/xadmin/filters/fk_search.html:26 #: templates/xadmin/filters/number.html:39 msgid "Clean" msgstr "" @@ -887,7 +1004,7 @@ msgid "Choose" msgstr "" #: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 +#: templates/xadmin/widgets/base.html:40 msgid "Remove" msgstr "" @@ -909,7 +1026,7 @@ msgstr "" #: templates/xadmin/includes/submit_line.html:10 #: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 +#: templates/xadmin/views/form.html:30 templates/xadmin/views/form.html:31 msgid "Saving.." msgstr "" @@ -926,7 +1043,7 @@ msgid "Save and continue editing" msgstr "" #: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 +#: templates/xadmin/views/model_detail.html:28 views/delete.py:93 msgid "Delete" msgstr "" @@ -958,7 +1075,10 @@ msgid "Add Widget" msgstr "" #: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." msgstr "" #: templates/xadmin/views/logged_out.html:16 @@ -1000,17 +1120,24 @@ msgstr "" #: templates/xadmin/views/model_delete_confirm.html:11 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:19 #, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:27 #, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" msgstr "" #: templates/xadmin/views/model_delete_confirm.html:34 @@ -1029,17 +1156,24 @@ msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:18 #, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:26 #, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" msgstr "" #: templates/xadmin/views/model_delete_selected_confirm.html:34 #, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" msgstr "" #: templates/xadmin/views/model_history.html:26 @@ -1064,7 +1198,9 @@ msgid "Diff Select Versions" msgstr "" #: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." msgstr "" #: templates/xadmin/views/model_list.html:29 @@ -1090,7 +1226,8 @@ msgid "Press the recover button below to recover this version of the object." msgstr "" #: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." +msgid "" +"Choose a date from the list below to recover a deleted version of an object." msgstr "" #: templates/xadmin/views/recover_list.html:39 @@ -1149,127 +1286,153 @@ msgstr "" msgid "Quick Add" msgstr "" -#: templates/xadmin/widgets/base.html:30 +#: templates/xadmin/widgets/base.html:31 msgid "Widget Options" msgstr "" -#: templates/xadmin/widgets/base.html:41 +#: templates/xadmin/widgets/base.html:42 msgid "Save changes" msgstr "" -#: views/base.py:430 +#: views/base.py:315 msgid "Django Xadmin" msgstr "" -#: views/dashboard.py:185 -msgid "Widget ID" +#: views/base.py:316 +msgid "my-company.inc" msgstr "" #: views/dashboard.py:186 +msgid "Widget ID" +msgstr "" + +#: views/dashboard.py:187 msgid "Widget Title" msgstr "" -#: views/dashboard.py:248 +#: views/dashboard.py:252 msgid "Html Content Widget, can write any html content in widget." msgstr "" -#: views/dashboard.py:251 +#: views/dashboard.py:255 msgid "Html Content" msgstr "" -#: views/dashboard.py:314 +#: views/dashboard.py:318 msgid "Target Model" msgstr "" -#: views/dashboard.py:365 +#: views/dashboard.py:369 msgid "Quick button Widget, quickly open any page." msgstr "" -#: views/dashboard.py:367 +#: views/dashboard.py:371 msgid "Quick Buttons" msgstr "" -#: views/dashboard.py:408 +#: views/dashboard.py:416 msgid "Any Objects list Widget." msgstr "" -#: views/dashboard.py:447 +#: views/dashboard.py:456 msgid "Add any model object Widget." msgstr "" -#: views/dashboard.py:481 +#: views/dashboard.py:492 msgid "Dashboard" msgstr "" -#: views/dashboard.py:622 +#: views/dashboard.py:633 #, python-format msgid "%s Dashboard" msgstr "" -#: views/delete.py:101 +#: views/delete.py:103 #, python-format msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgstr "" -#: views/detail.py:172 views/edit.py:199 views/form.py:72 +#: views/detail.py:173 views/edit.py:211 views/form.py:72 msgid "Other Fields" msgstr "" -#: views/detail.py:233 +#: views/detail.py:235 #, python-format msgid "%s Detail" msgstr "" -#: views/edit.py:394 +#: views/edit.py:253 +msgid "Added." +msgstr "" + +#: views/edit.py:255 +#, fuzzy, python-format +#| msgid "Change %s" +msgid "Changed %s." +msgstr "Изменить %s" + +#: views/edit.py:255 +msgid "and" +msgstr "" + +#: views/edit.py:258 +msgid "No fields changed." +msgstr "" + +#: views/edit.py:420 #, python-format msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "" -#: views/edit.py:399 views/edit.py:494 +#: views/edit.py:425 views/edit.py:520 msgid "You may edit it again below." msgstr "" -#: views/edit.py:403 views/edit.py:497 +#: views/edit.py:429 views/edit.py:523 #, python-format msgid "You may add another %s below." msgstr "" -#: views/edit.py:445 +#: views/edit.py:471 #, python-format msgid "Change %s" msgstr "Изменить %s" -#: views/edit.py:490 +#: views/edit.py:516 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." msgstr "" -#: views/form.py:164 +#: views/form.py:165 #, fuzzy, python-format msgid "The %s was changed successfully." msgstr "Пароль успешно изменен" -#: views/list.py:198 +#: views/list.py:199 msgid "Database error" msgstr "" -#: views/list.py:372 +#: views/list.py:373 #, python-format msgid "%s List" msgstr "" -#: views/list.py:500 +#: views/list.py:499 msgid "Sort ASC" msgstr "" -#: views/list.py:501 +#: views/list.py:500 msgid "Sort DESC" msgstr "" -#: views/list.py:505 +#: views/list.py:504 msgid "Cancel Sort" msgstr "" #: views/website.py:16 msgid "Main Dashboard" msgstr "" + +#: widgets.py:48 +msgid "Now" +msgstr "Сейчас" diff --git a/xadmin/locale/zh_CN/LC_MESSAGES/django.mo b/xadmin/locale/zh_CN/LC_MESSAGES/django.mo deleted file mode 100644 index ea9ad2235..000000000 Binary files a/xadmin/locale/zh_CN/LC_MESSAGES/django.mo and /dev/null differ diff --git a/xadmin/locale/zh_CN/LC_MESSAGES/django.po b/xadmin/locale/zh_CN/LC_MESSAGES/django.po deleted file mode 100644 index 404dbddb6..000000000 --- a/xadmin/locale/zh_CN/LC_MESSAGES/django.po +++ /dev/null @@ -1,1265 +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. -# -# Translators: -# sshwsfc , 2013 -# sshwsfc , 2013 -msgid "" -msgstr "" -"Project-Id-Version: xadmin-core\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-10 10:31+0800\n" -"PO-Revision-Date: 2013-11-20 10:21+0000\n" -"Last-Translator: sshwsfc \n" -"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/xadmin/language/zh_CN/)\n" -"Language: zh_CN\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: filters.py:157 filters.py:189 filters.py:401 filters.py:451 -msgid "All" -msgstr "全部" - -#: filters.py:158 plugins/export.py:117 -msgid "Yes" -msgstr "是" - -#: filters.py:159 plugins/export.py:117 -msgid "No" -msgstr "否" - -#: filters.py:173 -msgid "Unknown" -msgstr "未知" - -#: filters.py:265 -msgid "Any date" -msgstr "任意日期" - -#: filters.py:266 -msgid "Has date" -msgstr "有日期" - -#: filters.py:269 -msgid "Has no date" -msgstr "无日期" - -#: filters.py:272 widgets.py:30 -msgid "Today" -msgstr "今天" - -#: filters.py:276 -msgid "Past 7 days" -msgstr "过去7天" - -#: filters.py:280 -msgid "This month" -msgstr "本月" - -#: filters.py:284 -msgid "This year" -msgstr "今年" - -#: forms.py:10 -msgid "Please enter the correct username and password for a staff account. Note that both fields are case-sensitive." -msgstr "请输入正确的用户名和密码来登陆您的管理账户。请注意用户名和密码均为大小写相关。" - -#: forms.py:21 -msgid "Please log in again, because your session has expired." -msgstr "请重新登录,因为你的会话已经过期。" - -#: forms.py:41 -#, python-format -msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "你的 e-mail 地址不是你的用户名。换 '%s' 试试。" - -#: models.py:47 -msgid "Title" -msgstr "标题" - -#: models.py:48 models.py:87 models.py:106 -msgid "user" -msgstr "用户" - -#: models.py:49 -msgid "Url Name" -msgstr "URL名字" - -#: models.py:51 -msgid "Query String" -msgstr "Query参数" - -#: models.py:52 -msgid "Is Shared" -msgstr "是否共享" - -#: models.py:65 plugins/bookmark.py:49 plugins/bookmark.py:177 -msgid "Bookmark" -msgstr "书签" - -#: models.py:66 -msgid "Bookmarks" -msgstr "书签" - -#: models.py:88 -msgid "Settings Key" -msgstr "设置KEY" - -#: models.py:89 -msgid "Settings Content" -msgstr "设置内容" - -#: models.py:101 -msgid "User Setting" -msgstr "用户设置" - -#: models.py:102 -msgid "User Settings" -msgstr "用户设置" - -#: models.py:107 -msgid "Page" -msgstr "页面" - -#: models.py:108 views/dashboard.py:81 views/dashboard.py:91 -msgid "Widget Type" -msgstr "Widget类型" - -#: models.py:109 views/dashboard.py:82 -msgid "Widget Params" -msgstr "Widget参数" - -#: models.py:136 -msgid "User Widget" -msgstr "用户小组件" - -#: models.py:137 -msgid "User Widgets" -msgstr "用户小组件" - -#: widgets.py:48 -msgid "Now" -msgstr "现在" - -#: plugins/actions.py:54 -#, python-format -msgid "Delete selected %(verbose_name_plural)s" -msgstr "删除所选的 %(verbose_name_plural)s" - -#: plugins/actions.py:67 -#, python-format -msgid "Successfully deleted %(count)d %(items)s." -msgstr "成功删除了 %(count)d 个 %(items)s" - -#: plugins/actions.py:99 views/delete.py:68 -#, python-format -msgid "Cannot delete %(name)s" -msgstr "无法删除 %(name)s" - -#: plugins/actions.py:101 views/delete.py:71 -msgid "Are you sure?" -msgstr "你确定吗?" - -#: plugins/actions.py:147 -#, python-format -msgid "%(total_count)s selected" -msgid_plural "All %(total_count)s selected" -msgstr[0] "选中了 %(total_count)s 个" - -#: plugins/actions.py:151 -#, python-format -msgid "0 of %(cnt)s selected" -msgstr "%(cnt)s 个中 0 个被选" - -#: plugins/actions.py:168 plugins/actions.py:178 -msgid "Items must be selected in order to perform actions on them. No items have been changed." -msgstr "条目必须选中以对其进行操作。没有任何条目被更改。" - -#: plugins/aggregation.py:14 -msgid "Min" -msgstr "最小" - -#: plugins/aggregation.py:14 -msgid "Max" -msgstr "最大" - -#: plugins/aggregation.py:14 -msgid "Avg" -msgstr "平均" - -#: plugins/aggregation.py:14 -msgid "Sum" -msgstr "总和" - -#: plugins/aggregation.py:14 -msgid "Count" -msgstr "总数" - -#: plugins/auth.py:21 -#, fuzzy, python-format -msgid "Can add %s" -msgstr "可查看%s" - -#: plugins/auth.py:22 -#, fuzzy, python-format -msgid "Can change %s" -msgstr "修改 %s" - -#: plugins/auth.py:23 -#, fuzzy, python-format -msgid "Can edit %s" -msgstr "可查看%s" - -#: plugins/auth.py:24 -#, fuzzy, python-format -msgid "Can delete %s" -msgstr "无法删除 %(name)s" - -#: plugins/auth.py:25 -#, python-format -msgid "Can view %s" -msgstr "可查看%s" - -#: plugins/auth.py:87 -msgid "Personal info" -msgstr "个人信息" - -#: plugins/auth.py:91 -msgid "Permissions" -msgstr "权限" - -#: plugins/auth.py:94 -msgid "Important dates" -msgstr "重要日期" - -#: plugins/auth.py:99 -msgid "Status" -msgstr "状态" - -#: plugins/auth.py:111 -#, fuzzy -msgid "Permission Name" -msgstr "权限" - -#: plugins/auth.py:159 -msgid "Change Password" -msgstr "更改密码" - -#: plugins/auth.py:189 -#, python-format -msgid "Change password: %s" -msgstr "更改密码:%s" - -#: plugins/auth.py:214 plugins/auth.py:246 -msgid "Password changed successfully." -msgstr "密码更改成功" - -#: plugins/auth.py:233 templates/xadmin/auth/user/change_password.html:11 -#: templates/xadmin/auth/user/change_password.html:22 -#: templates/xadmin/auth/user/change_password.html:55 -msgid "Change password" -msgstr "修改密码" - -#: plugins/batch.py:44 -msgid "Change this field" -msgstr "修改该字段" - -#: plugins/batch.py:65 -#, python-format -msgid "Batch Change selected %(verbose_name_plural)s" -msgstr "批量修改选择的%(verbose_name_plural)s" - -#: plugins/batch.py:90 -#, python-format -msgid "Successfully change %(count)d %(items)s." -msgstr "成功修改了 %(count)d 个 %(items)s" - -#: plugins/batch.py:138 -#, python-format -msgid "Batch change %s" -msgstr "批量修改 %s" - -#: plugins/bookmark.py:171 -msgid "bookmark" -msgstr "书签" - -#: plugins/bookmark.py:173 -msgid "Bookmark Widget, can show user's bookmark list data in widget." -msgstr "书签组件,展示用户书签页内容。" - -#: plugins/chart.py:24 -msgid "Show models simple chart." -msgstr "展示简单数据图表" - -#: plugins/chart.py:49 -#, python-format -msgid "%s Charts" -msgstr "%s图表" - -#: plugins/comments.py:33 -msgid "Metadata" -msgstr "" - -#: plugins/comments.py:60 -msgid "flagged" -msgid_plural "flagged" -msgstr[0] "" - -#: plugins/comments.py:61 -msgid "Flag selected comments" -msgstr "" - -#: plugins/comments.py:66 -msgid "approved" -msgid_plural "approved" -msgstr[0] "" - -#: plugins/comments.py:67 -msgid "Approve selected comments" -msgstr "" - -#: plugins/comments.py:72 -#, fuzzy -msgid "removed" -msgid_plural "removed" -msgstr[0] "删除" - -#: plugins/comments.py:73 -#, fuzzy -msgid "Remove selected comments" -msgstr "恢复删除的%(name)s" - -#: plugins/comments.py:86 -#, python-format -msgid "1 comment was successfully %(action)s." -msgid_plural "%(count)s comments were successfully %(action)s." -msgstr[0] "" - -#: plugins/details.py:52 views/list.py:576 -#, python-format -msgid "Details of %s" -msgstr "%s详情" - -#: plugins/editable.py:47 -#, python-format -msgid "Enter %s" -msgstr "输入%s" - -#: plugins/editable.py:74 views/dashboard.py:638 views/delete.py:26 -#: views/detail.py:144 views/edit.py:428 -#, python-format -msgid "%(name)s object with primary key %(key)r does not exist." -msgstr "具有主键 %(key)r 的对象 %(name)s 不存在。" - -#: plugins/export.py:87 -msgid "Sheet" -msgstr "表" - -#: plugins/filters.py:125 -#, python-format -msgid "Filtering error: %s" -msgstr "过滤器错误: %s" - -#: plugins/images.py:29 -msgid "Previous" -msgstr "上一个" - -#: plugins/images.py:29 -msgid "Next" -msgstr "下一个" - -#: plugins/images.py:29 -msgid "Slideshow" -msgstr "幻灯片" - -#: plugins/images.py:29 -msgid "Download" -msgstr "下载" - -#: plugins/images.py:50 -msgid "Change:" -msgstr "修改:" - -#: plugins/layout.py:15 -msgid "Table" -msgstr "表格" - -#: plugins/layout.py:21 -msgid "Thumbnails" -msgstr "图标" - -#: plugins/passwords.py:64 -msgid "Forgotten your password or username?" -msgstr "忘记了您的密码或用户名?" - -#: plugins/quickform.py:77 -#, python-format -msgid "Create New %s" -msgstr "创建新的 %s" - -#: plugins/relate.py:73 -msgid "Related Objects" -msgstr "关联数据" - -#: plugins/relfield.py:29 plugins/topnav.py:35 -#, python-format -msgid "Search %s" -msgstr "搜索%s" - -#: plugins/themes.py:47 -msgid "Default" -msgstr "默认" - -#: plugins/themes.py:48 -msgid "Default bootstrap theme" -msgstr "默认Bootstrap主题" - -#: plugins/themes.py:49 -msgid "Bootstrap2" -msgstr "Bootstrap2" - -#: plugins/themes.py:49 -msgid "Bootstrap 2.x theme" -msgstr "Bootstrap2主题" - -#: plugins/topnav.py:58 views/dashboard.py:455 views/edit.py:361 -#: views/edit.py:370 -#, python-format -msgid "Add %s" -msgstr "增加 %s" - -#: plugins/xversion.py:130 -msgid "Initial version." -msgstr "初始化版本" - -#: plugins/xversion.py:132 -msgid "Change version." -msgstr "修改版本" - -#: plugins/xversion.py:134 -msgid "Revert version." -msgstr "还原版本" - -#: plugins/xversion.py:136 -msgid "Rercover version." -msgstr "恢复版本" - -#: plugins/xversion.py:138 -#, python-format -msgid "Deleted %(verbose_name)s." -msgstr "删除%(verbose_name)s。" - -#: plugins/xversion.py:166 templates/xadmin/views/recover_form.html:26 -msgid "Recover" -msgstr "还原" - -#: plugins/xversion.py:182 templates/xadmin/views/model_history.html:11 -#: templates/xadmin/views/revision_diff.html:11 -#: templates/xadmin/views/revision_form.html:15 -msgid "History" -msgstr "历史" - -#: plugins/xversion.py:225 templates/xadmin/views/recover_form.html:14 -#: templates/xadmin/views/recover_list.html:10 -#, python-format -msgid "Recover deleted %(name)s" -msgstr "恢复删除的%(name)s" - -#: plugins/xversion.py:263 -#, python-format -msgid "Change history: %s" -msgstr "变更历史: %s" - -#: plugins/xversion.py:313 -msgid "Must select two versions." -msgstr "必须选择两个版本。" - -#: plugins/xversion.py:321 -msgid "Please select two different versions." -msgstr "请选择两个不同的版本。" - -#: plugins/xversion.py:408 plugins/xversion.py:516 -#, python-format -msgid "Current: %s" -msgstr "当前:%s" - -#: plugins/xversion.py:440 -#, python-format -msgid "Revert %s" -msgstr "还原%s" - -#: plugins/xversion.py:456 -#, python-format -msgid "The %(model)s \"%(name)s\" was reverted successfully. You may edit it again below." -msgstr "%(model)s “%(name)s”成功还原,您可以继续编辑。" - -#: plugins/xversion.py:477 -#, python-format -msgid "Recover %s" -msgstr "恢复%s" - -#: plugins/xversion.py:493 -#, python-format -msgid "The %(model)s \"%(name)s\" was recovered successfully. You may edit it again below." -msgstr "%(model)s “%(name)s”成功恢复,您可以继续编辑。" - -#: templates/xadmin/404.html:4 templates/xadmin/404.html.py:8 -msgid "Page not found" -msgstr "页面没有找到" - -#: templates/xadmin/404.html:10 -msgid "We're sorry, but the requested page could not be found." -msgstr "很报歉,请求页面无法找到。" - -#: templates/xadmin/500.html:7 templates/xadmin/base_site.html:53 -#: templates/xadmin/auth/user/change_password.html:10 -#: templates/xadmin/auth/user/change_password.html:15 -#: templates/xadmin/includes/sitemenu_default.html:7 -#: templates/xadmin/views/app_index.html:9 -#: templates/xadmin/views/batch_change_form.html:9 -#: templates/xadmin/views/invalid_setup.html:7 -#: templates/xadmin/views/model_dashboard.html:7 -#: templates/xadmin/views/model_delete_selected_confirm.html:8 -#: templates/xadmin/views/model_history.html:8 -#: templates/xadmin/views/recover_form.html:8 -#: templates/xadmin/views/recover_list.html:8 -#: templates/xadmin/views/revision_diff.html:8 -#: templates/xadmin/views/revision_form.html:8 views/base.py:448 -msgid "Home" -msgstr "首页" - -#: templates/xadmin/500.html:8 -msgid "Server error" -msgstr "服务器错误" - -#: templates/xadmin/500.html:12 -msgid "Server error (500)" -msgstr "服务器错误(500)" - -#: templates/xadmin/500.html:15 -msgid "Server Error (500)" -msgstr "服务器错误 (500)" - -#: templates/xadmin/500.html:16 -msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." -msgstr "发生了一个错误。系统已将错误通过电子邮件报告给了站点管理员,相信问题应该会很快得到解决。感谢您的耐心。" - -#: templates/xadmin/base_site.html:19 -msgid "Welcome," -msgstr "欢迎," - -#: templates/xadmin/base_site.html:25 -msgid "Log out" -msgstr "注销" - -#: templates/xadmin/base_site.html:37 -msgid "You don't have permission to edit anything." -msgstr "你无权修改任何东西。" - -#: templates/xadmin/auth/password_reset/complete.html:11 -#: templates/xadmin/auth/password_reset/done.html:11 -msgid "Password reset successful" -msgstr "密码重设成功" - -#: templates/xadmin/auth/password_reset/complete.html:14 -msgid "Your password has been set. You may go ahead and log in now." -msgstr "你的口令己经设置。现在你可以继续进行登录。" - -#: templates/xadmin/auth/password_reset/complete.html:15 -msgid "Log in" -msgstr "登录" - -#: templates/xadmin/auth/password_reset/confirm.html:12 -msgid "Enter new password" -msgstr "输入新密码" - -#: templates/xadmin/auth/password_reset/confirm.html:17 -msgid "Please enter your new password twice so we can verify you typed it in correctly." -msgstr "请输入两遍新密码,以便我们校验你输入的是否正确。" - -#: templates/xadmin/auth/password_reset/confirm.html:19 -msgid "Change my password" -msgstr "修改我的密码" - -#: templates/xadmin/auth/password_reset/confirm.html:24 -msgid "Password reset unsuccessful" -msgstr "密码重设失败" - -#: templates/xadmin/auth/password_reset/confirm.html:27 -msgid "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." -msgstr "密码重置链接无效,可能是因为它已使用。可以请求一次新的密码重置。" - -#: templates/xadmin/auth/password_reset/done.html:14 -msgid "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." -msgstr "我们已经按你所提交的电子邮箱地址发送了密码设置说明。你应该很快就能收到这封邮件。" - -#: templates/xadmin/auth/password_reset/email.html:2 -#, python-format -msgid "You're receiving this e-mail because you requested a password reset for your user account at %(site_name)s." -msgstr "因为你要求重置 %(site_name)s 上的账户密码, 所以收到了这封邮件." - -#: templates/xadmin/auth/password_reset/email.html:4 -msgid "Please go to the following page and choose a new password:" -msgstr "请访问该页面并选择一个新密码:" - -#: templates/xadmin/auth/password_reset/email.html:8 -msgid "Your username, in case you've forgotten:" -msgstr "你的用户名,如果已忘记的话:" - -#: templates/xadmin/auth/password_reset/email.html:10 -msgid "Thanks for using our site!" -msgstr "感谢使用我们的站点!" - -#: templates/xadmin/auth/password_reset/email.html:12 -#, python-format -msgid "The %(site_name)s team" -msgstr "%(site_name)s 团队" - -#: templates/xadmin/auth/password_reset/form.html:13 -msgid "Password reset" -msgstr "密码重设" - -#: templates/xadmin/auth/password_reset/form.html:17 -msgid "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." -msgstr "忘记了你的密码?请在下面输入你的 e-mail 地址,我们将把新密码设置说明通过邮件发送给你。" - -#: templates/xadmin/auth/password_reset/form.html:25 -msgid "E-mail address:" -msgstr "E-mail 地址:" - -#: templates/xadmin/auth/password_reset/form.html:33 -msgid "Reset my password" -msgstr "重设我的密码" - -#: templates/xadmin/auth/user/add_form.html:6 -msgid "First, enter a username and password. Then, you'll be able to edit more user options." -msgstr "首先,输入一个用户名和密码。然后,你就可以编辑更多的用户选项。" - -#: templates/xadmin/auth/user/add_form.html:8 -msgid "Enter a username and password." -msgstr "输入用户名和" - -#: templates/xadmin/auth/user/change_password.html:31 -#: templates/xadmin/views/batch_change_form.html:24 -#: templates/xadmin/views/form.html:18 -#: templates/xadmin/views/model_form.html:20 -msgid "Please correct the error below." -msgid_plural "Please correct the errors below." -msgstr[0] "请修正下面的错误。" - -#: templates/xadmin/auth/user/change_password.html:38 -msgid "Enter your new password." -msgstr "输入你的新密码" - -#: templates/xadmin/auth/user/change_password.html:40 -#, python-format -msgid "Enter a new password for the user %(username)s." -msgstr "为用户 %(username)s 输入一个新的密码。" - -#: templates/xadmin/blocks/comm.top.theme.html:4 -msgid "Themes" -msgstr "主题" - -#: templates/xadmin/blocks/comm.top.topnav.html:8 -#: templates/xadmin/filters/char.html:7 -#: templates/xadmin/filters/fk_search.html:7 -#: templates/xadmin/filters/fk_search.html:14 -#: templates/xadmin/filters/number.html:7 -msgid "Search" -msgstr "搜索" - -#: templates/xadmin/blocks/comm.top.topnav.html:22 -msgid "Add" -msgstr "增加" - -#: templates/xadmin/blocks/model_form.submit_line.wizard.html:9 -#: templates/xadmin/blocks/model_form.submit_line.wizard.html:26 -msgid "Prev step" -msgstr "上一步" - -#: templates/xadmin/blocks/model_form.submit_line.wizard.html:13 -#: templates/xadmin/blocks/model_form.submit_line.wizard.html:29 -msgid "Next step" -msgstr "下一步" - -#: templates/xadmin/blocks/model_form.submit_line.wizard.html:15 -#: templates/xadmin/blocks/model_form.submit_line.wizard.html:31 -#: templates/xadmin/includes/submit_line.html:10 -#: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 -msgid "Save" -msgstr "保存" - -#: templates/xadmin/blocks/model_list.nav_menu.bookmarks.html:7 -msgid "Clean Bookmarks" -msgstr "清除书签" - -#: templates/xadmin/blocks/model_list.nav_menu.bookmarks.html:18 -msgid "No Bookmarks" -msgstr "没有书签" - -#: templates/xadmin/blocks/model_list.nav_menu.bookmarks.html:22 -msgid "New Bookmark" -msgstr "新建书签" - -#: templates/xadmin/blocks/model_list.nav_menu.bookmarks.html:26 -msgid "Save current page as Bookmark" -msgstr "将当前页面保存为书签" - -#: templates/xadmin/blocks/model_list.nav_menu.bookmarks.html:32 -msgid "Enter bookmark title" -msgstr "输入书签标题" - -#: templates/xadmin/blocks/model_list.nav_menu.bookmarks.html:33 -msgid "Waiting" -msgstr "请稍侯" - -#: templates/xadmin/blocks/model_list.nav_menu.bookmarks.html:33 -msgid "Save Bookmark" -msgstr "保存书签" - -#: templates/xadmin/blocks/model_list.nav_menu.filters.html:4 -msgid "Filters" -msgstr "过滤器" - -#: templates/xadmin/blocks/model_list.nav_menu.filters.html:8 -msgid "Clean Filters" -msgstr "清除过滤器" - -#: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 -msgid "Click here to select the objects across all pages" -msgstr "点击此处选择所有页面中包含的对象。" - -#: templates/xadmin/blocks/model_list.results_bottom.actions.html:19 -#, python-format -msgid "Select all %(total_count)s %(module_name)s" -msgstr "选中所有的 %(total_count)s 个 %(module_name)s" - -#: templates/xadmin/blocks/model_list.results_bottom.actions.html:20 -msgid "Clear selection" -msgstr "清除选中" - -#: templates/xadmin/blocks/model_list.results_top.charts.html:4 -msgid "Charts" -msgstr "图表" - -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:4 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:8 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:19 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:44 -msgid "Export" -msgstr "导出" - -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:26 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:29 -msgid "Export with table header." -msgstr "导出表头" - -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:32 -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:35 -msgid "Export with format." -msgstr "导出格式" - -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:39 -msgid "Export all data." -msgstr "导出全部数据" - -#: templates/xadmin/blocks/model_list.top_toolbar.exports.html:43 -#: templates/xadmin/widgets/base.html:40 -msgid "Close" -msgstr "关闭" - -#: templates/xadmin/blocks/model_list.top_toolbar.layouts.html:4 -msgid "Layout" -msgstr "布局" - -#: templates/xadmin/blocks/model_list.top_toolbar.refresh.html:8 -msgid "Clean Refresh" -msgstr "清除自动刷新" - -#: templates/xadmin/blocks/model_list.top_toolbar.refresh.html:14 -#, python-format -msgid "Every %(t)s seconds" -msgstr "每 %(t)s 秒" - -#: templates/xadmin/edit_inline/blank.html:5 views/detail.py:22 -#: views/edit.py:100 views/list.py:28 -msgid "Null" -msgstr "空" - -#: templates/xadmin/filters/char.html:13 -msgid "Enter" -msgstr "输入" - -#: templates/xadmin/filters/date.html:10 templates/xadmin/filters/date.html:13 -msgid "Choice Date" -msgstr "选择日期" - -#: templates/xadmin/filters/date.html:18 -msgid "YY" -msgstr "年" - -#: templates/xadmin/filters/date.html:19 -msgid "year" -msgstr "年" - -#: templates/xadmin/filters/date.html:22 -msgid "MM" -msgstr "月" - -#: templates/xadmin/filters/date.html:23 -msgid "month" -msgstr "月" - -#: templates/xadmin/filters/date.html:26 -msgid "DD" -msgstr "日" - -#: templates/xadmin/filters/date.html:27 -msgid "day" -msgstr "日" - -#: templates/xadmin/filters/date.html:29 templates/xadmin/filters/date.html:46 -#: templates/xadmin/filters/date.html:54 -#: templates/xadmin/filters/fk_search.html:16 -#: templates/xadmin/filters/number.html:37 -msgid "Apply" -msgstr "应用" - -#: templates/xadmin/filters/date.html:34 -msgid "Date Range" -msgstr "日期范围" - -#: templates/xadmin/filters/date.html:41 -msgid "Select Date" -msgstr "选择日期" - -#: templates/xadmin/filters/date.html:42 -msgid "From" -msgstr "从" - -#: templates/xadmin/filters/date.html:44 -msgid "To" -msgstr "到" - -#: templates/xadmin/filters/fk_search.html:18 -#: templates/xadmin/filters/number.html:39 -msgid "Clean" -msgstr "清除" - -#: templates/xadmin/filters/number.html:17 -#: templates/xadmin/filters/number.html:25 -#: templates/xadmin/filters/number.html:33 -msgid "Enter Number" -msgstr "输入数字" - -#: templates/xadmin/filters/rel.html:3 -#, python-format -msgid " By %(filter_title)s " -msgstr " 以 %(filter_title)s" - -#: templates/xadmin/forms/transfer.html:4 -msgid "Available" -msgstr "可用项" - -#: templates/xadmin/forms/transfer.html:12 -msgid "Click to choose all at once." -msgstr "点击一次性选择全部" - -#: templates/xadmin/forms/transfer.html:12 -msgid "Choose all" -msgstr "选择全部" - -#: templates/xadmin/forms/transfer.html:16 -msgid "Choose" -msgstr "选择" - -#: templates/xadmin/forms/transfer.html:19 -#: templates/xadmin/widgets/base.html:39 -msgid "Remove" -msgstr "删除" - -#: templates/xadmin/forms/transfer.html:23 -msgid "Chosen" -msgstr "已选项" - -#: templates/xadmin/forms/transfer.html:27 -msgid "Click to remove all chosen at once." -msgstr "点击一次性删除全部" - -#: templates/xadmin/forms/transfer.html:27 -msgid "Remove all" -msgstr "删除全部" - -#: templates/xadmin/includes/pagination.html:9 -msgid "Show all" -msgstr "显示全部" - -#: templates/xadmin/includes/submit_line.html:10 -#: templates/xadmin/includes/submit_line.html:13 -#: templates/xadmin/views/form.html:30 -msgid "Saving.." -msgstr "保存中.." - -#: templates/xadmin/includes/submit_line.html:17 -msgid "Save as new" -msgstr "保存为新的" - -#: templates/xadmin/includes/submit_line.html:18 -msgid "Save and add another" -msgstr "保存并增加另一个" - -#: templates/xadmin/includes/submit_line.html:19 -msgid "Save and continue editing" -msgstr "保存并继续编辑" - -#: templates/xadmin/includes/submit_line.html:24 -#: templates/xadmin/views/model_detail.html:28 views/delete.py:91 -msgid "Delete" -msgstr "删除" - -#: templates/xadmin/views/app_index.html:13 -#, python-format -msgid "%(name)s" -msgstr "%(name)s" - -#: templates/xadmin/views/batch_change_form.html:11 -msgid "Change multiple objects" -msgstr "修改多个数据" - -#: templates/xadmin/views/batch_change_form.html:16 -#, python-format -msgid "Change one %(objects_name)s" -msgid_plural "Batch change %(counter)s %(objects_name)s" -msgstr[0] "批量修改 %(counter)s 个 %(objects_name)s" - -#: templates/xadmin/views/batch_change_form.html:38 -msgid "Change Multiple" -msgstr "修改多个数据" - -#: templates/xadmin/views/dashboard.html:15 -#: templates/xadmin/views/dashboard.html:22 -#: templates/xadmin/views/dashboard.html:23 -msgid "Add Widget" -msgstr "添加小组件" - -#: templates/xadmin/views/invalid_setup.html:13 -msgid "Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user." -msgstr "你的数据库安装有误。确保已经创建了相应的数据库表,并确保数据库可被相关的用户读取。" - -#: templates/xadmin/views/logged_out.html:16 -msgid "Logout Success" -msgstr "成功退出" - -#: templates/xadmin/views/logged_out.html:17 -msgid "Thanks for spending some quality time with the Web site today." -msgstr "感谢您今天在本站花费了一些宝贵时间。" - -#: templates/xadmin/views/logged_out.html:19 -msgid "Close Window" -msgstr "关闭窗口" - -#: templates/xadmin/views/logged_out.html:20 -msgid "Log in again" -msgstr "重新登录" - -#: templates/xadmin/views/login.html:39 views/website.py:38 -msgid "Please Login" -msgstr "请登录" - -#: templates/xadmin/views/login.html:52 -msgid "Username" -msgstr "用户名" - -#: templates/xadmin/views/login.html:64 -msgid "Password" -msgstr "密码" - -#: templates/xadmin/views/login.html:75 -msgid "log in" -msgstr "登录" - -#: templates/xadmin/views/model_dashboard.html:26 -#: templates/xadmin/views/model_detail.html:25 -msgid "Edit" -msgstr "编辑" - -#: templates/xadmin/views/model_delete_confirm.html:11 -#, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" -msgstr "要删除所选的%(verbose_name)s '%(escaped_object)s' 结果会删除相关对象, 但你的账户没有权限删除这类对象:" - -#: templates/xadmin/views/model_delete_confirm.html:19 -#, python-format -msgid "Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting the following protected related objects:" -msgstr "要删除所选的%(verbose_name)s '%(escaped_object)s' 将要求删除以下受保护的相关对象:" - -#: templates/xadmin/views/model_delete_confirm.html:27 -#, python-format -msgid "Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? All of the following related items will be deleted:" -msgstr "请确认要删除选中的%(verbose_name)s \"%(escaped_object)s\"吗?以下所有对象和余它们相关的条目将都会被删除:" - -#: templates/xadmin/views/model_delete_confirm.html:34 -#: templates/xadmin/views/model_delete_selected_confirm.html:49 -msgid "Yes, I'm sure" -msgstr "是的,我确定" - -#: templates/xadmin/views/model_delete_confirm.html:35 -#: templates/xadmin/views/model_delete_selected_confirm.html:50 -msgid "Cancel" -msgstr "取消" - -#: templates/xadmin/views/model_delete_selected_confirm.html:10 -msgid "Delete multiple objects" -msgstr "删除多个对象" - -#: templates/xadmin/views/model_delete_selected_confirm.html:18 -#, python-format -msgid "Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" -msgstr "要删除所选的 %(objects_name)s 结果会删除相关对象, 但你的账户没有权限删除这类对象:" - -#: templates/xadmin/views/model_delete_selected_confirm.html:26 -#, python-format -msgid "Deleting the selected %(objects_name)s would require deleting the following protected related objects:" -msgstr "要删除所选的 %(objects_name)s, 将要求删除以下受保护的相关对象:" - -#: templates/xadmin/views/model_delete_selected_confirm.html:34 -#, python-format -msgid "Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:" -msgstr "请确认要删除选中的 %(objects_name)s 吗?以下所有对象和余它们相关的条目将都会被删除:" - -#: templates/xadmin/views/model_history.html:26 -msgid "Diff" -msgstr "不同" - -#: templates/xadmin/views/model_history.html:27 -#: templates/xadmin/views/recover_list.html:25 -msgid "Date/time" -msgstr "日期/时间" - -#: templates/xadmin/views/model_history.html:28 -msgid "User" -msgstr "用户" - -#: templates/xadmin/views/model_history.html:29 -msgid "Comment" -msgstr "注释" - -#: templates/xadmin/views/model_history.html:54 -msgid "Diff Select Versions" -msgstr "查看所选版本的不同" - -#: templates/xadmin/views/model_history.html:58 -msgid "This object doesn't have a change history. It probably wasn't added via this admin site." -msgstr "该对象没有变更历史记录。可能从未通过这个管理站点添加。" - -#: templates/xadmin/views/model_list.html:29 -#, python-format -msgid "Add %(name)s" -msgstr "增加 %(name)s" - -#: templates/xadmin/views/model_list.html:39 -#, fuzzy -msgid "Columns" -msgstr "列" - -#: templates/xadmin/views/model_list.html:42 -msgid "Restore Selected" -msgstr "恢复显示列" - -#: templates/xadmin/views/model_list.html:147 -#: templates/xadmin/widgets/list.html:33 -msgid "Empty list" -msgstr "空列表" - -#: templates/xadmin/views/recover_form.html:20 -msgid "Press the recover button below to recover this version of the object." -msgstr "点击下方的“还原”按钮还原到该版本。" - -#: templates/xadmin/views/recover_list.html:19 -msgid "Choose a date from the list below to recover a deleted version of an object." -msgstr "从以下列表中选择一个日期来恢复删除掉的数据。" - -#: templates/xadmin/views/recover_list.html:39 -msgid "There are no deleted objects to recover." -msgstr "没有已删除的数据。" - -#: templates/xadmin/views/revision_diff.html:12 -#: templates/xadmin/views/revision_diff.html:17 -#, python-format -msgid "Diff %(verbose_name)s" -msgstr "%(verbose_name)s的不同" - -#: templates/xadmin/views/revision_diff.html:25 -msgid "Field" -msgstr "字段" - -#: templates/xadmin/views/revision_diff.html:26 -msgid "Version A" -msgstr "版本A" - -#: templates/xadmin/views/revision_diff.html:27 -msgid "Version B" -msgstr "版本B" - -#: templates/xadmin/views/revision_diff.html:39 -msgid "Revert to" -msgstr "还原到" - -#: templates/xadmin/views/revision_diff.html:40 -#: templates/xadmin/views/revision_diff.html:41 -msgid "Revert" -msgstr "还原" - -#: templates/xadmin/views/revision_form.html:16 -#, python-format -msgid "Revert %(verbose_name)s" -msgstr "还原%(verbose_name)s" - -#: templates/xadmin/views/revision_form.html:21 -msgid "Press the revert button below to revert to this version of the object." -msgstr "点击下方的“还原”按钮还原数据到该版本。" - -#: templates/xadmin/views/revision_form.html:27 -msgid "Revert this revision" -msgstr "还原该版本" - -#: templates/xadmin/widgets/addform.html:14 -msgid "Success" -msgstr "成功" - -#: templates/xadmin/widgets/addform.html:14 -msgid "Add success, click edit to edit." -msgstr "添加成功,点击 编辑 可以继续修改该数据。" - -#: templates/xadmin/widgets/addform.html:17 -msgid "Quick Add" -msgstr "快速添加" - -#: templates/xadmin/widgets/base.html:30 -msgid "Widget Options" -msgstr "小组件设置项" - -#: templates/xadmin/widgets/base.html:41 -msgid "Save changes" -msgstr "保存变更" - -#: views/base.py:430 -msgid "Django Xadmin" -msgstr "Django Xadmin" - -#: views/dashboard.py:185 -msgid "Widget ID" -msgstr "小组件ID" - -#: views/dashboard.py:186 -msgid "Widget Title" -msgstr "小组件标题" - -#: views/dashboard.py:248 -msgid "Html Content Widget, can write any html content in widget." -msgstr "HTML内容小组件,可以编写任意HTML内容。" - -#: views/dashboard.py:251 -msgid "Html Content" -msgstr "HTML内容" - -#: views/dashboard.py:314 -msgid "Target Model" -msgstr "目标数据" - -#: views/dashboard.py:365 -msgid "Quick button Widget, quickly open any page." -msgstr "快捷按钮小组件,可以快速打开任意页面。" - -#: views/dashboard.py:367 -msgid "Quick Buttons" -msgstr "快速按钮" - -#: views/dashboard.py:408 -msgid "Any Objects list Widget." -msgstr "数据列表小组件" - -#: views/dashboard.py:447 -msgid "Add any model object Widget." -msgstr "添加任意数据的小组件" - -#: views/dashboard.py:481 -msgid "Dashboard" -msgstr "仪表盘" - -#: views/dashboard.py:622 -#, python-format -msgid "%s Dashboard" -msgstr "%s 主页" - -#: views/delete.py:101 -#, python-format -msgid "The %(name)s \"%(obj)s\" was deleted successfully." -msgstr "%(name)s \"%(obj)s\" 删除成功。" - -#: views/detail.py:172 views/edit.py:199 views/form.py:72 -msgid "Other Fields" -msgstr "其它字段" - -#: views/detail.py:233 -#, python-format -msgid "%s Detail" -msgstr "%s详情" - -#: views/edit.py:394 -#, python-format -msgid "The %(name)s \"%(obj)s\" was added successfully." -msgstr "%(name)s \"%(obj)s\" 添加成功。" - -#: views/edit.py:399 views/edit.py:494 -msgid "You may edit it again below." -msgstr "你可以在下面再次编辑它。" - -#: views/edit.py:403 views/edit.py:497 -#, python-format -msgid "You may add another %s below." -msgstr "你可以在下面增加另一个 %s 。" - -#: views/edit.py:445 -#, python-format -msgid "Change %s" -msgstr "修改 %s" - -#: views/edit.py:490 -#, python-format -msgid "The %(name)s \"%(obj)s\" was changed successfully." -msgstr "%(name)s \"%(obj)s\" 修改成功。" - -#: views/form.py:164 -#, fuzzy, python-format -msgid "The %s was changed successfully." -msgstr "%(name)s \"%(obj)s\" 修改成功。" - -#: views/list.py:198 -msgid "Database error" -msgstr "数据库错误" - -#: views/list.py:372 -#, python-format -msgid "%s List" -msgstr "%s列表" - -#: views/list.py:500 -msgid "Sort ASC" -msgstr "正序" - -#: views/list.py:501 -msgid "Sort DESC" -msgstr "倒序" - -#: views/list.py:505 -msgid "Cancel Sort" -msgstr "取消排序" - -#: views/website.py:16 -msgid "Main Dashboard" -msgstr "主页面" diff --git a/xadmin/locale/zh_CN/LC_MESSAGES/djangojs.mo b/xadmin/locale/zh_CN/LC_MESSAGES/djangojs.mo deleted file mode 100644 index 9612a41eb..000000000 Binary files a/xadmin/locale/zh_CN/LC_MESSAGES/djangojs.mo and /dev/null differ diff --git a/xadmin/locale/zh_Hans/LC_MESSAGES/django.mo b/xadmin/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 000000000..2107c5b29 Binary files /dev/null and b/xadmin/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/xadmin/locale/zh_Hans/LC_MESSAGES/django.po b/xadmin/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 000000000..cd41423f6 --- /dev/null +++ b/xadmin/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,1528 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# sshwsfc , 2013 +# sshwsfc , 2013 +msgid "" +msgstr "" +"Project-Id-Version: xadmin-core\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-04 15:12+0800\n" +"PO-Revision-Date: 2013-11-20 10:21+0000\n" +"Last-Translator: sshwsfc \n" +"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/xadmin/" +"language/zh_CN/)\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: .\adminx.py:20 +msgid "Admin Object" +msgstr "管理对象" + +#: .\apps.py:11 +msgid "Administration" +msgstr "管理" + +#: .\filters.py:169 .\filters.py:207 .\filters.py:427 .\filters.py:513 +#: .\filters.py:551 +msgid "All" +msgstr "全部" + +#: .\filters.py:170 .\plugins\export.py:167 +msgid "Yes" +msgstr "是" + +#: .\filters.py:171 .\plugins\export.py:167 +msgid "No" +msgstr "否" + +#: .\filters.py:191 +msgid "Unknown" +msgstr "未知" + +#: .\filters.py:287 +msgid "Any date" +msgstr "任意日期" + +#: .\filters.py:288 +msgid "Has date" +msgstr "有日期" + +#: .\filters.py:291 +msgid "Has no date" +msgstr "无日期" + +#: .\filters.py:294 .\widgets.py:35 .\widgets.py:81 +msgid "Today" +msgstr "今天" + +#: .\filters.py:298 +msgid "Past 7 days" +msgstr "过去7天" + +#: .\filters.py:302 +msgid "This month" +msgstr "本月" + +#: .\filters.py:306 +msgid "This year" +msgstr "今年" + +#: .\forms.py:10 +msgid "" +"Please enter the correct username and password for a staff account. Note " +"that both fields are case-sensitive." +msgstr "" +"请输入正确的用户名和密码来登陆您的管理账户。请注意用户名和密码均为大小写相" +"关。" + +#: .\forms.py:21 +msgid "Please log in again, because your session has expired." +msgstr "请重新登录,因为你的会话已经过期。" + +#: .\forms.py:42 +#, python-format +msgid "Your e-mail address is not your username. Try '%s' instead." +msgstr "你的 e-mail 地址不是你的用户名。换 '%s' 试试。" + +#: .\models.py:46 +msgid "Title" +msgstr "标题" + +#: .\models.py:47 .\models.py:87 .\models.py:107 .\models.py:151 +msgid "user" +msgstr "用户" + +#: .\models.py:48 +msgid "Url Name" +msgstr "URL名字" + +#: .\models.py:50 +msgid "Query String" +msgstr "Query参数" + +#: .\models.py:51 +msgid "Is Shared" +msgstr "是否共享" + +#: .\models.py:64 .\plugins\bookmark.py:59 .\plugins\bookmark.py:194 +msgid "Bookmark" +msgstr "书签" + +#: .\models.py:65 +msgid "Bookmarks" +msgstr "书签" + +#: .\models.py:88 +msgid "Settings Key" +msgstr "设置KEY" + +#: .\models.py:89 +msgid "Settings Content" +msgstr "设置内容" + +#: .\models.py:101 +msgid "User Setting" +msgstr "用户设置" + +#: .\models.py:102 +msgid "User Settings" +msgstr "用户设置" + +#: .\models.py:108 +msgid "Page" +msgstr "页面" + +#: .\models.py:109 .\views\dashboard.py:85 .\views\dashboard.py:95 +msgid "Widget Type" +msgstr "Widget类型" + +#: .\models.py:110 .\views\dashboard.py:86 +msgid "Widget Params" +msgstr "Widget参数" + +#: .\models.py:137 +msgid "User Widget" +msgstr "用户小组件" + +#: .\models.py:138 +msgid "User Widgets" +msgstr "用户小组件" + +#: .\models.py:144 +msgid "action time" +msgstr "记录时间" + +#: .\models.py:153 +msgid "action ip" +msgstr "操作IP" + +#: .\models.py:157 +msgid "content type" +msgstr "数据类型" + +#: .\models.py:160 +msgid "object id" +msgstr "数据ID" + +#: .\models.py:161 +msgid "object repr" +msgstr "数据描述" + +#: .\models.py:162 +msgid "action flag" +msgstr "操作标示" + +#: .\models.py:163 +msgid "change message" +msgstr "修改信息" + +#: .\models.py:166 +msgid "log entry" +msgstr "日志" + +#: .\models.py:167 +msgid "log entries" +msgstr "日志" + +#: .\models.py:175 +#, python-format +msgid "Added \"%(object)s\"." +msgstr "添加 \"%(object)s\"。" + +#: .\models.py:177 +#, python-format +msgid "Changed \"%(object)s\" - %(changes)s" +msgstr "修改 \"%(object)s\" - %(changes)s" + +#: .\models.py:182 +#, python-format +msgid "Deleted \"%(object)s.\"" +msgstr "删除 \"%(object)s.\"" + +#: .\plugins\actions.py:58 +#, python-format +msgid "Delete selected %(verbose_name_plural)s" +msgstr "删除所选的 %(verbose_name_plural)s" + +#: .\plugins\actions.py:73 +#, python-format +msgid "Batch delete %(count)d %(items)s." +msgstr "批量删除 %(count)d 个 %(items)s" + +#: .\plugins\actions.py:79 +#, python-format +msgid "Successfully deleted %(count)d %(items)s." +msgstr "成功删除了 %(count)d 个 %(items)s" + +#: .\plugins\actions.py:111 .\views\delete.py:71 +#, python-format +msgid "Cannot delete %(name)s" +msgstr "无法删除 %(name)s" + +#: .\plugins\actions.py:113 .\views\delete.py:74 +msgid "Are you sure?" +msgstr "你确定吗?" + +#: .\plugins\actions.py:159 +#, python-format +msgid "%(total_count)s selected" +msgid_plural "All %(total_count)s selected" +msgstr[0] "选中了 %(total_count)s 个" + +#: .\plugins\actions.py:163 +#, python-format +msgid "0 of %(cnt)s selected" +msgstr "%(cnt)s 个中 0 个被选" + +#: .\plugins\actions.py:180 .\plugins\actions.py:190 +msgid "" +"Items must be selected in order to perform actions on them. No items have " +"been changed." +msgstr "条目必须选中以对其进行操作。没有任何条目被更改。" + +#: .\plugins\aggregation.py:14 +msgid "Min" +msgstr "最小" + +#: .\plugins\aggregation.py:14 +msgid "Max" +msgstr "最大" + +#: .\plugins\aggregation.py:14 +msgid "Avg" +msgstr "平均" + +#: .\plugins\aggregation.py:14 +msgid "Sum" +msgstr "总和" + +#: .\plugins\aggregation.py:14 +msgid "Count" +msgstr "总数" + +#: .\plugins\auth.py:25 +#, python-format +msgid "Can add %s" +msgstr "添加:%s" + +#: .\plugins\auth.py:26 +#, python-format +msgid "Can change %s" +msgstr "修改:%s" + +#: .\plugins\auth.py:27 +#, python-format +msgid "Can edit %s" +msgstr "编辑:%s" + +#: .\plugins\auth.py:28 +#, python-format +msgid "Can delete %s" +msgstr "删除:%s" + +#: .\plugins\auth.py:29 +#, python-format +msgid "Can view %s" +msgstr "查看:%s" + +#: .\plugins\auth.py:91 +msgid "Personal info" +msgstr "个人信息" + +#: .\plugins\auth.py:95 +msgid "Permissions" +msgstr "权限" + +#: .\plugins\auth.py:98 +msgid "Important dates" +msgstr "重要日期" + +#: .\plugins\auth.py:103 +msgid "Status" +msgstr "状态" + +#: .\plugins\auth.py:115 +msgid "Permission Name" +msgstr "权限" + +#: .\plugins\auth.py:171 +msgid "Change Password" +msgstr "更改密码" + +#: .\plugins\auth.py:202 +#, python-format +msgid "Change password: %s" +msgstr "更改密码:%s" + +#: .\plugins\auth.py:227 .\plugins\auth.py:259 +msgid "Password changed successfully." +msgstr "密码更改成功" + +#: .\plugins\auth.py:246 .\templates\xadmin\auth\user\change_password.html:11 +#: .\templates\xadmin\auth\user\change_password.html:22 +#: .\templates\xadmin\auth\user\change_password.html:55 +msgid "Change password" +msgstr "修改密码" + +#: .\plugins\batch.py:44 +msgid "Change this field" +msgstr "修改该字段" + +#: .\plugins\batch.py:65 +#, python-format +msgid "Batch Change selected %(verbose_name_plural)s" +msgstr "批量修改选择的%(verbose_name_plural)s" + +#: .\plugins\batch.py:89 +#, python-format +msgid "Successfully change %(count)d %(items)s." +msgstr "成功修改了 %(count)d 个 %(items)s" + +#: .\plugins\batch.py:138 +#, python-format +msgid "Batch change %s" +msgstr "批量修改 %s" + +#: .\plugins\bookmark.py:187 +msgid "bookmark" +msgstr "书签" + +#: .\plugins\bookmark.py:190 +msgid "Bookmark Widget, can show user's bookmark list data in widget." +msgstr "书签组件,展示用户书签页内容。" + +#: .\plugins\chart.py:24 +msgid "Show models simple chart." +msgstr "展示简单数据图表" + +#: .\plugins\chart.py:50 +#, python-format +msgid "%s Charts" +msgstr "%s图表" + +#: .\plugins\comments.py:33 +msgid "Metadata" +msgstr "" + +#: .\plugins\comments.py:60 +msgid "flagged" +msgid_plural "flagged" +msgstr[0] "" + +#: .\plugins\comments.py:61 +msgid "Flag selected comments" +msgstr "" + +#: .\plugins\comments.py:66 +msgid "approved" +msgid_plural "approved" +msgstr[0] "" + +#: .\plugins\comments.py:67 +msgid "Approve selected comments" +msgstr "" + +#: .\plugins\comments.py:72 +msgid "removed" +msgid_plural "removed" +msgstr[0] "删除" + +#: .\plugins\comments.py:73 +msgid "Remove selected comments" +msgstr "恢复删除的%(name)s" + +#: .\plugins\comments.py:86 +#, python-format +msgid "1 comment was successfully %(action)s." +msgid_plural "%(count)s comments were successfully %(action)s." +msgstr[0] "" + +#: .\plugins\details.py:52 .\views\list.py:577 +#, python-format +msgid "Details of %s" +msgstr "%s详情" + +#: .\plugins\editable.py:46 +#, python-format +msgid "Enter %s" +msgstr "输入%s" + +#: .\plugins\editable.py:73 .\views\dashboard.py:652 .\views\delete.py:28 +#: .\views\detail.py:145 .\views\edit.py:460 +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "具有主键 %(key)r 的对象 %(name)s 不存在。" + +#: .\plugins\export.py:100 .\plugins\export.py:137 +msgid "Sheet" +msgstr "表" + +#: .\plugins\filters.py:137 .\plugins\quickfilter.py:143 +#, python-format +msgid "Filtering error: %s" +msgstr "过滤器错误: %s" + +#: .\plugins\images.py:29 +msgid "Previous" +msgstr "上一个" + +#: .\plugins\images.py:29 +msgid "Next" +msgstr "下一个" + +#: .\plugins\images.py:29 +msgid "Slideshow" +msgstr "幻灯片" + +#: .\plugins\images.py:29 +msgid "Download" +msgstr "下载" + +#: .\plugins\images.py:50 +msgid "Change:" +msgstr "修改:" + +#: .\plugins\importexport.py:174 .\plugins\importexport.py:244 +#: .\templates\xadmin\blocks\model_list.top_toolbar.importexport.import.html:4 +#: .\templates\xadmin\import_export\import.html:6 +#: .\templates\xadmin\import_export\import.html:13 +#, fuzzy +#| msgid "Export" +msgid "Import" +msgstr "导出" + +#: .\plugins\importexport.py:227 +#, python-format +msgid "

Imported file has a wrong encoding: %s

" +msgstr "

导入文件编码错误: %s

" + +#: .\plugins\importexport.py:229 +#, python-format +msgid "

%s encountered while trying to read file: %s

" +msgstr "

%s读取文件是发生错误: %s

" + +#: .\plugins\importexport.py:300 +msgid "Import finished" +msgstr "导入完成" + +#: .\plugins\importexport.py:300 +#: .\templates\xadmin\blocks\comm.top.topnav.html:23 +msgid "Add" +msgstr "增加" + +#: .\plugins\importexport.py:301 +#: .\templates\xadmin\import_export\import.html:109 +msgid "Update" +msgstr "更新" + +#: .\plugins\importexport.py:435 +msgid "You must select an export format." +msgstr "必须选择一种导入格式" + +#: .\plugins\layout.py:16 +msgid "Table" +msgstr "表格" + +#: .\plugins\layout.py:22 +msgid "Thumbnails" +msgstr "图标" + +#: .\plugins\passwords.py:62 +msgid "Forgotten your password or username?" +msgstr "忘记了您的密码或用户名?" + +#: .\plugins\quickform.py:80 +#, python-format +msgid "Create New %s" +msgstr "创建新的 %s" + +#: .\plugins\relate.py:105 +msgid "Related Objects" +msgstr "关联数据" + +#: .\plugins\relfield.py:29 .\plugins\topnav.py:38 +#, python-format +msgid "Search %s" +msgstr "搜索%s" + +#: .\plugins\relfield.py:77 +#, python-format +msgid "Select %s" +msgstr "选择%s" + +#: .\plugins\themes.py:59 +msgid "Default" +msgstr "默认" + +#: .\plugins\themes.py:59 +msgid "Default bootstrap theme" +msgstr "默认Bootstrap主题" + +#: .\plugins\themes.py:60 +msgid "Bootstrap2" +msgstr "Bootstrap2" + +#: .\plugins\themes.py:60 +msgid "Bootstrap 2.x theme" +msgstr "Bootstrap2主题" + +#: .\plugins\topnav.py:62 .\views\dashboard.py:468 .\views\edit.py:393 +#: .\views\edit.py:402 +#, python-format +msgid "Add %s" +msgstr "增加 %s" + +#: .\plugins\xversion.py:107 +msgid "Initial version." +msgstr "初始化版本" + +#: .\plugins\xversion.py:109 +msgid "Change version." +msgstr "修改版本" + +#: .\plugins\xversion.py:111 +msgid "Revert version." +msgstr "还原版本" + +#: .\plugins\xversion.py:113 +msgid "Rercover version." +msgstr "恢复版本" + +#: .\plugins\xversion.py:115 +#, python-format +msgid "Deleted %(verbose_name)s." +msgstr "删除%(verbose_name)s。" + +#: .\plugins\xversion.py:128 .\templates\xadmin\views\recover_form.html:26 +msgid "Recover" +msgstr "还原" + +#: .\plugins\xversion.py:144 .\templates\xadmin\views\model_history.html:11 +#: .\templates\xadmin\views\revision_diff.html:11 +#: .\templates\xadmin\views\revision_form.html:15 +msgid "History" +msgstr "历史" + +#: .\plugins\xversion.py:195 .\templates\xadmin\views\recover_form.html:14 +#: .\templates\xadmin\views\recover_list.html:10 +#, python-format +msgid "Recover deleted %(name)s" +msgstr "恢复删除的%(name)s" + +#: .\plugins\xversion.py:239 +#, python-format +msgid "Change history: %s" +msgstr "变更历史: %s" + +#: .\plugins\xversion.py:289 +msgid "Must select two versions." +msgstr "必须选择两个版本。" + +#: .\plugins\xversion.py:297 +msgid "Please select two different versions." +msgstr "请选择两个不同的版本。" + +#: .\plugins\xversion.py:384 .\plugins\xversion.py:501 +#, python-format +msgid "Current: %s" +msgstr "当前:%s" + +#: .\plugins\xversion.py:425 +#, python-format +msgid "Revert %s" +msgstr "还原%s" + +#: .\plugins\xversion.py:441 +#, python-format +msgid "" +"The %(model)s \"%(name)s\" was reverted successfully. You may edit it again " +"below." +msgstr "%(model)s “%(name)s”成功还原,您可以继续编辑。" + +#: .\plugins\xversion.py:462 +#, python-format +msgid "Recover %s" +msgstr "恢复%s" + +#: .\plugins\xversion.py:478 +#, python-format +msgid "" +"The %(model)s \"%(name)s\" was recovered successfully. You may edit it again " +"below." +msgstr "%(model)s “%(name)s”成功恢复,您可以继续编辑。" + +#: .\templates\xadmin\404.html:4 .\templates\xadmin\404.html:8 +msgid "Page not found" +msgstr "页面没有找到" + +#: .\templates\xadmin\404.html:10 +msgid "We're sorry, but the requested page could not be found." +msgstr "很报歉,请求页面无法找到。" + +#: .\templates\xadmin\500.html:7 +#: .\templates\xadmin\auth\user\change_password.html:10 +#: .\templates\xadmin\auth\user\change_password.html:15 +#: .\templates\xadmin\base_site.html:53 +#: .\templates\xadmin\import_export\export_action.html:13 +#: .\templates\xadmin\import_export\import.html:11 +#: .\templates\xadmin\includes\sitemenu_default.html:7 +#: .\templates\xadmin\views\app_index.html:9 +#: .\templates\xadmin\views\batch_change_form.html:9 +#: .\templates\xadmin\views\invalid_setup.html:7 +#: .\templates\xadmin\views\model_dashboard.html:7 +#: .\templates\xadmin\views\model_delete_selected_confirm.html:8 +#: .\templates\xadmin\views\model_history.html:8 +#: .\templates\xadmin\views\recover_form.html:8 +#: .\templates\xadmin\views\recover_list.html:8 +#: .\templates\xadmin\views\revision_diff.html:8 +#: .\templates\xadmin\views\revision_form.html:8 .\views\base.py:478 +msgid "Home" +msgstr "首页" + +#: .\templates\xadmin\500.html:8 +msgid "Server error" +msgstr "服务器错误" + +#: .\templates\xadmin\500.html:12 +msgid "Server error (500)" +msgstr "服务器错误(500)" + +#: .\templates\xadmin\500.html:15 +msgid "Server Error (500)" +msgstr "服务器错误 (500)" + +#: .\templates\xadmin\500.html:16 +msgid "" +"There's been an error. It's been reported to the site administrators via e-" +"mail and should be fixed shortly. Thanks for your patience." +msgstr "" +"发生了一个错误。系统已将错误通过电子邮件报告给了站点管理员,相信问题应该会很" +"快得到解决。感谢您的耐心。" + +#: .\templates\xadmin\auth\password_reset\complete.html:11 +#: .\templates\xadmin\auth\password_reset\done.html:11 +msgid "Password reset successful" +msgstr "密码重设成功" + +#: .\templates\xadmin\auth\password_reset\complete.html:14 +msgid "Your password has been set. You may go ahead and log in now." +msgstr "你的口令己经设置。现在你可以继续进行登录。" + +#: .\templates\xadmin\auth\password_reset\complete.html:15 +msgid "Log in" +msgstr "登录" + +#: .\templates\xadmin\auth\password_reset\confirm.html:12 +msgid "Enter new password" +msgstr "输入新密码" + +#: .\templates\xadmin\auth\password_reset\confirm.html:17 +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." +msgstr "请输入两遍新密码,以便我们校验你输入的是否正确。" + +#: .\templates\xadmin\auth\password_reset\confirm.html:19 +msgid "Change my password" +msgstr "修改我的密码" + +#: .\templates\xadmin\auth\password_reset\confirm.html:24 +msgid "Password reset unsuccessful" +msgstr "密码重设失败" + +#: .\templates\xadmin\auth\password_reset\confirm.html:27 +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." +msgstr "密码重置链接无效,可能是因为它已使用。可以请求一次新的密码重置。" + +#: .\templates\xadmin\auth\password_reset\done.html:14 +msgid "" +"We've e-mailed you instructions for setting your password to the e-mail " +"address you submitted. You should be receiving it shortly." +msgstr "" +"我们已经按你所提交的电子邮箱地址发送了密码设置说明。你应该很快就能收到这封邮" +"件。" + +#: .\templates\xadmin\auth\password_reset\email.html:2 +#, python-format +msgid "" +"You're receiving this e-mail because you requested a password reset for your " +"user account at %(site_name)s." +msgstr "因为你要求重置 %(site_name)s 上的账户密码, 所以收到了这封邮件." + +#: .\templates\xadmin\auth\password_reset\email.html:4 +msgid "Please go to the following page and choose a new password:" +msgstr "请访问该页面并选择一个新密码:" + +#: .\templates\xadmin\auth\password_reset\email.html:8 +msgid "Your username, in case you've forgotten:" +msgstr "你的用户名,如果已忘记的话:" + +#: .\templates\xadmin\auth\password_reset\email.html:10 +msgid "Thanks for using our site!" +msgstr "感谢使用我们的站点!" + +#: .\templates\xadmin\auth\password_reset\email.html:12 +#, python-format +msgid "The %(site_name)s team" +msgstr "%(site_name)s 团队" + +#: .\templates\xadmin\auth\password_reset\form.html:13 +msgid "Password reset" +msgstr "密码重设" + +#: .\templates\xadmin\auth\password_reset\form.html:17 +msgid "" +"Forgotten your password? Enter your e-mail address below, and we'll e-mail " +"instructions for setting a new one." +msgstr "" +"忘记了你的密码?请在下面输入你的 e-mail 地址,我们将把新密码设置说明通过邮件" +"发送给你。" + +#: .\templates\xadmin\auth\password_reset\form.html:25 +msgid "E-mail address:" +msgstr "E-mail 地址:" + +#: .\templates\xadmin\auth\password_reset\form.html:33 +msgid "Reset my password" +msgstr "重设我的密码" + +#: .\templates\xadmin\auth\user\add_form.html:6 +msgid "" +"First, enter a username and password. Then, you'll be able to edit more user " +"options." +msgstr "首先,输入一个用户名和密码。然后,你就可以编辑更多的用户选项。" + +#: .\templates\xadmin\auth\user\add_form.html:8 +msgid "Enter a username and password." +msgstr "输入用户名和" + +#: .\templates\xadmin\auth\user\change_password.html:31 +#: .\templates\xadmin\views\batch_change_form.html:24 +#: .\templates\xadmin\views\form.html:18 +#: .\templates\xadmin\views\model_form.html:20 +msgid "Please correct the error below." +msgid_plural "Please correct the errors below." +msgstr[0] "请修正下面的错误。" + +#: .\templates\xadmin\auth\user\change_password.html:38 +msgid "Enter your new password." +msgstr "输入你的新密码" + +#: .\templates\xadmin\auth\user\change_password.html:40 +#, python-format +msgid "Enter a new password for the user %(username)s." +msgstr "为用户 %(username)s 输入一个新的密码。" + +#: .\templates\xadmin\base_site.html:18 +msgid "Welcome," +msgstr "欢迎," + +#: .\templates\xadmin\base_site.html:24 +msgid "Log out" +msgstr "注销" + +#: .\templates\xadmin\base_site.html:36 +msgid "You don't have permission to edit anything." +msgstr "你无权修改任何东西。" + +#: .\templates\xadmin\blocks\comm.top.theme.html:4 +msgid "Themes" +msgstr "主题" + +#: .\templates\xadmin\blocks\comm.top.topnav.html:9 +#: .\templates\xadmin\blocks\model_list.nav_form.search_form.html:8 +#: .\templates\xadmin\filters\char.html:7 +#: .\templates\xadmin\filters\fk_search.html:7 +#: .\templates\xadmin\filters\fk_search.html:16 +#: .\templates\xadmin\filters\number.html:7 +msgid "Search" +msgstr "搜索" + +#: .\templates\xadmin\blocks\model_form.submit_line.wizard.html:9 +#: .\templates\xadmin\blocks\model_form.submit_line.wizard.html:26 +msgid "Prev step" +msgstr "上一步" + +#: .\templates\xadmin\blocks\model_form.submit_line.wizard.html:13 +#: .\templates\xadmin\blocks\model_form.submit_line.wizard.html:29 +msgid "Next step" +msgstr "下一步" + +#: .\templates\xadmin\blocks\model_form.submit_line.wizard.html:15 +#: .\templates\xadmin\blocks\model_form.submit_line.wizard.html:31 +#: .\templates\xadmin\includes\submit_line.html:10 +#: .\templates\xadmin\includes\submit_line.html:13 +#: .\templates\xadmin\views\form.html:30 .\templates\xadmin\views\form.html:31 +msgid "Save" +msgstr "保存" + +#: .\templates\xadmin\blocks\model_list.nav_menu.bookmarks.html:7 +msgid "Clean Bookmarks" +msgstr "清除书签" + +#: .\templates\xadmin\blocks\model_list.nav_menu.bookmarks.html:18 +msgid "No Bookmarks" +msgstr "没有书签" + +#: .\templates\xadmin\blocks\model_list.nav_menu.bookmarks.html:22 +msgid "New Bookmark" +msgstr "新建书签" + +#: .\templates\xadmin\blocks\model_list.nav_menu.bookmarks.html:26 +msgid "Save current page as Bookmark" +msgstr "将当前页面保存为书签" + +#: .\templates\xadmin\blocks\model_list.nav_menu.bookmarks.html:32 +msgid "Enter bookmark title" +msgstr "输入书签标题" + +#: .\templates\xadmin\blocks\model_list.nav_menu.bookmarks.html:33 +msgid "Waiting" +msgstr "请稍侯" + +#: .\templates\xadmin\blocks\model_list.nav_menu.bookmarks.html:33 +msgid "Save Bookmark" +msgstr "保存书签" + +#: .\templates\xadmin\blocks\model_list.nav_menu.filters.html:4 +msgid "Filters" +msgstr "过滤器" + +#: .\templates\xadmin\blocks\model_list.nav_menu.filters.html:8 +msgid "Clean Filters" +msgstr "清除过滤器" + +#: .\templates\xadmin\blocks\model_list.results_bottom.actions.html:19 +msgid "Click here to select the objects across all pages" +msgstr "点击此处选择所有页面中包含的对象。" + +#: .\templates\xadmin\blocks\model_list.results_bottom.actions.html:19 +#, python-format +msgid "Select all %(total_count)s %(model_name)s" +msgstr "选中所有的 %(total_count)s 个 %(model_name)s" + +#: .\templates\xadmin\blocks\model_list.results_bottom.actions.html:20 +msgid "Clear selection" +msgstr "清除选中" + +#: .\templates\xadmin\blocks\model_list.results_top.charts.html:4 +msgid "Charts" +msgstr "图表" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:4 +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:8 +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:19 +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:47 +#: .\templates\xadmin\blocks\model_list.top_toolbar.importexport.export.html:4 +#: .\templates\xadmin\blocks\model_list.top_toolbar.importexport.export.html:12 +#: .\templates\xadmin\blocks\model_list.top_toolbar.importexport.export.html:41 +#: .\templates\xadmin\import_export\export_action.html:7 +#: .\templates\xadmin\import_export\export_action.html:15 +msgid "Export" +msgstr "导出" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:26 +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:29 +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:32 +msgid "Export with table header." +msgstr "导出表头" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:35 +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:38 +msgid "Export with format." +msgstr "导出格式" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:42 +#: .\templates\xadmin\blocks\model_list.top_toolbar.importexport.export.html:35 +msgid "Export all data." +msgstr "导出全部数据" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.exports.html:46 +#: .\templates\xadmin\blocks\model_list.top_toolbar.importexport.export.html:39 +#: .\templates\xadmin\widgets\base.html:41 +msgid "Close" +msgstr "关闭" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.importexport.export.html:33 +msgid "Export current page data." +msgstr "导出当前页数据" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.importexport.export.html:34 +msgid "Export selected data." +msgstr "导出所选择数据" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.importexport.export.html:36 +msgid "Export header only." +msgstr "仅导出表头" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.layouts.html:4 +msgid "Layout" +msgstr "布局" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.refresh.html:8 +msgid "Clean Refresh" +msgstr "清除自动刷新" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.refresh.html:14 +#, python-format +msgid "Every %(t)s seconds" +msgstr "每 %(t)s 秒" + +#: .\templates\xadmin\blocks\model_list.top_toolbar.saveorder.html:4 +msgid "Save Order" +msgstr "保存排序" + +#: .\templates\xadmin\edit_inline\blank.html:5 .\views\detail.py:25 +#: .\views\edit.py:104 .\views\list.py:31 +msgid "Null" +msgstr "空" + +#: .\templates\xadmin\filters\char.html:13 +msgid "Enter" +msgstr "输入" + +#: .\templates\xadmin\filters\date.html:10 +#: .\templates\xadmin\filters\date.html:13 +msgid "Choice Date" +msgstr "选择日期" + +#: .\templates\xadmin\filters\date.html:18 +msgid "YY" +msgstr "年" + +#: .\templates\xadmin\filters\date.html:19 +msgid "year" +msgstr "年" + +#: .\templates\xadmin\filters\date.html:22 +msgid "MM" +msgstr "月" + +#: .\templates\xadmin\filters\date.html:23 +msgid "month" +msgstr "月" + +#: .\templates\xadmin\filters\date.html:26 +msgid "DD" +msgstr "日" + +#: .\templates\xadmin\filters\date.html:27 +msgid "day" +msgstr "日" + +#: .\templates\xadmin\filters\date.html:29 +#: .\templates\xadmin\filters\date.html:46 +#: .\templates\xadmin\filters\date.html:54 +#: .\templates\xadmin\filters\fk_search.html:24 +#: .\templates\xadmin\filters\number.html:37 +msgid "Apply" +msgstr "应用" + +#: .\templates\xadmin\filters\date.html:34 +msgid "Date Range" +msgstr "日期范围" + +#: .\templates\xadmin\filters\date.html:41 +msgid "Select Date" +msgstr "选择日期" + +#: .\templates\xadmin\filters\date.html:42 +msgid "From" +msgstr "从" + +#: .\templates\xadmin\filters\date.html:44 +msgid "To" +msgstr "到" + +#: .\templates\xadmin\filters\fk_search.html:14 +msgid "Select" +msgstr "选择" + +#: .\templates\xadmin\filters\fk_search.html:26 +#: .\templates\xadmin\filters\number.html:39 +msgid "Clean" +msgstr "清除" + +#: .\templates\xadmin\filters\number.html:17 +#: .\templates\xadmin\filters\number.html:25 +#: .\templates\xadmin\filters\number.html:33 +msgid "Enter Number" +msgstr "输入数字" + +#: .\templates\xadmin\filters\rel.html:3 +#, python-format +msgid " By %(filter_title)s " +msgstr " 以 %(filter_title)s" + +#: .\templates\xadmin\forms\transfer.html:4 +msgid "Available" +msgstr "可用项" + +#: .\templates\xadmin\forms\transfer.html:12 +msgid "Click to choose all at once." +msgstr "点击一次性选择全部" + +#: .\templates\xadmin\forms\transfer.html:12 +msgid "Choose all" +msgstr "选择全部" + +#: .\templates\xadmin\forms\transfer.html:16 +msgid "Choose" +msgstr "选择" + +#: .\templates\xadmin\forms\transfer.html:19 +#: .\templates\xadmin\widgets\base.html:40 +msgid "Remove" +msgstr "删除" + +#: .\templates\xadmin\forms\transfer.html:23 +msgid "Chosen" +msgstr "已选项" + +#: .\templates\xadmin\forms\transfer.html:27 +msgid "Click to remove all chosen at once." +msgstr "点击一次性删除全部" + +#: .\templates\xadmin\forms\transfer.html:27 +msgid "Remove all" +msgstr "删除全部" + +#: .\templates\xadmin\import_export\export_action.html:43 +#: .\templates\xadmin\import_export\import.html:59 +msgid "Submit" +msgstr "" + +#: .\templates\xadmin\import_export\import.html:26 +msgid "" +"Below is a preview of data to be imported. If you are satisfied with the " +"results, click 'Confirm import'" +msgstr "" + +#: .\templates\xadmin\import_export\import.html:29 +msgid "Confirm import" +msgstr "" + +#: .\templates\xadmin\import_export\import.html:38 +msgid "This importer will import the following fields: " +msgstr "" + +#: .\templates\xadmin\import_export\import.html:67 +msgid "Errors" +msgstr "" + +#: .\templates\xadmin\import_export\import.html:78 +#, fuzzy +#| msgid "Enter Number" +msgid "Line number" +msgstr "输入数字" + +#: .\templates\xadmin\import_export\import.html:88 +#, fuzzy +#| msgid "Previous" +msgid "Preview" +msgstr "上一个" + +#: .\templates\xadmin\import_export\import.html:103 +#, fuzzy +#| msgid "Now" +msgid "New" +msgstr "现在" + +#: .\templates\xadmin\import_export\import.html:105 +msgid "Skipped" +msgstr "" + +#: .\templates\xadmin\import_export\import.html:107 +#: .\templates\xadmin\includes\submit_line.html:24 +#: .\templates\xadmin\views\model_detail.html:28 .\views\delete.py:94 +msgid "Delete" +msgstr "删除" + +#: .\templates\xadmin\includes\pagination.html:9 +msgid "Show all" +msgstr "显示全部" + +#: .\templates\xadmin\includes\submit_line.html:10 +#: .\templates\xadmin\includes\submit_line.html:13 +#: .\templates\xadmin\views\form.html:30 .\templates\xadmin\views\form.html:31 +msgid "Saving.." +msgstr "保存中.." + +#: .\templates\xadmin\includes\submit_line.html:17 +msgid "Save as new" +msgstr "保存为新的" + +#: .\templates\xadmin\includes\submit_line.html:18 +msgid "Save and add another" +msgstr "保存并增加另一个" + +#: .\templates\xadmin\includes\submit_line.html:19 +msgid "Save and continue editing" +msgstr "保存并继续编辑" + +#: .\templates\xadmin\views\app_index.html:13 +#, python-format +msgid "%(name)s" +msgstr "%(name)s" + +#: .\templates\xadmin\views\batch_change_form.html:11 +msgid "Change multiple objects" +msgstr "修改多个数据" + +#: .\templates\xadmin\views\batch_change_form.html:16 +#, python-format +msgid "Change one %(objects_name)s" +msgid_plural "Batch change %(counter)s %(objects_name)s" +msgstr[0] "批量修改 %(counter)s 个 %(objects_name)s" + +#: .\templates\xadmin\views\batch_change_form.html:38 +msgid "Change Multiple" +msgstr "修改多个数据" + +#: .\templates\xadmin\views\dashboard.html:15 +#: .\templates\xadmin\views\dashboard.html:22 +#: .\templates\xadmin\views\dashboard.html:23 +msgid "Add Widget" +msgstr "添加小组件" + +#: .\templates\xadmin\views\invalid_setup.html:13 +msgid "" +"Something's wrong with your database installation. Make sure the appropriate " +"database tables have been created, and make sure the database is readable by " +"the appropriate user." +msgstr "" +"你的数据库安装有误。确保已经创建了相应的数据库表,并确保数据库可被相关的用户" +"读取。" + +#: .\templates\xadmin\views\logged_out.html:16 +msgid "Logout Success" +msgstr "成功退出" + +#: .\templates\xadmin\views\logged_out.html:17 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "感谢您今天在本站花费了一些宝贵时间。" + +#: .\templates\xadmin\views\logged_out.html:19 +msgid "Close Window" +msgstr "关闭窗口" + +#: .\templates\xadmin\views\logged_out.html:20 +msgid "Log in again" +msgstr "重新登录" + +#: .\templates\xadmin\views\login.html:39 .\views\website.py:39 +msgid "Please Login" +msgstr "请登录" + +#: .\templates\xadmin\views\login.html:52 +msgid "Username" +msgstr "用户名" + +#: .\templates\xadmin\views\login.html:64 +msgid "Password" +msgstr "密码" + +#: .\templates\xadmin\views\login.html:75 +msgid "log in" +msgstr "登录" + +#: .\templates\xadmin\views\model_dashboard.html:26 +#: .\templates\xadmin\views\model_detail.html:25 +msgid "Edit" +msgstr "编辑" + +#: .\templates\xadmin\views\model_delete_confirm.html:11 +#, python-format +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would result in deleting " +"related objects, but your account doesn't have permission to delete the " +"following types of objects:" +msgstr "" +"要删除所选的%(verbose_name)s '%(escaped_object)s' 结果会删除相关对象, 但你的" +"账户没有权限删除这类对象:" + +#: .\templates\xadmin\views\model_delete_confirm.html:19 +#, python-format +msgid "" +"Deleting the %(verbose_name)s '%(escaped_object)s' would require deleting " +"the following protected related objects:" +msgstr "" +"要删除所选的%(verbose_name)s '%(escaped_object)s' 将要求删除以下受保护的相关" +"对象:" + +#: .\templates\xadmin\views\model_delete_confirm.html:27 +#, python-format +msgid "" +"Are you sure you want to delete the %(verbose_name)s \"%(escaped_object)s\"? " +"All of the following related items will be deleted:" +msgstr "" +"请确认要删除选中的%(verbose_name)s \"%(escaped_object)s\"吗?以下所有对象和余" +"它们相关的条目将都会被删除:" + +#: .\templates\xadmin\views\model_delete_confirm.html:34 +#: .\templates\xadmin\views\model_delete_selected_confirm.html:49 +msgid "Yes, I'm sure" +msgstr "是的,我确定" + +#: .\templates\xadmin\views\model_delete_confirm.html:35 +#: .\templates\xadmin\views\model_delete_selected_confirm.html:50 +msgid "Cancel" +msgstr "取消" + +#: .\templates\xadmin\views\model_delete_selected_confirm.html:10 +msgid "Delete multiple objects" +msgstr "删除多个对象" + +#: .\templates\xadmin\views\model_delete_selected_confirm.html:18 +#, python-format +msgid "" +"Deleting the selected %(objects_name)s would result in deleting related " +"objects, but your account doesn't have permission to delete the following " +"types of objects:" +msgstr "" +"要删除所选的 %(objects_name)s 结果会删除相关对象, 但你的账户没有权限删除这类" +"对象:" + +#: .\templates\xadmin\views\model_delete_selected_confirm.html:26 +#, python-format +msgid "" +"Deleting the selected %(objects_name)s would require deleting the following " +"protected related objects:" +msgstr "要删除所选的 %(objects_name)s, 将要求删除以下受保护的相关对象:" + +#: .\templates\xadmin\views\model_delete_selected_confirm.html:34 +#, python-format +msgid "" +"Are you sure you want to delete the selected %(objects_name)s? All of the " +"following objects and their related items will be deleted:" +msgstr "" +"请确认要删除选中的 %(objects_name)s 吗?以下所有对象和余它们相关的条目将都会" +"被删除:" + +#: .\templates\xadmin\views\model_history.html:26 +msgid "Diff" +msgstr "不同" + +#: .\templates\xadmin\views\model_history.html:27 +#: .\templates\xadmin\views\recover_list.html:25 +msgid "Date/time" +msgstr "日期/时间" + +#: .\templates\xadmin\views\model_history.html:28 +msgid "User" +msgstr "用户" + +#: .\templates\xadmin\views\model_history.html:29 +msgid "Comment" +msgstr "注释" + +#: .\templates\xadmin\views\model_history.html:54 +msgid "Diff Select Versions" +msgstr "查看所选版本的不同" + +#: .\templates\xadmin\views\model_history.html:58 +msgid "" +"This object doesn't have a change history. It probably wasn't added via this " +"admin site." +msgstr "该对象没有变更历史记录。可能从未通过这个管理站点添加。" + +#: .\templates\xadmin\views\model_list.html:29 +#, python-format +msgid "Add %(name)s" +msgstr "增加 %(name)s" + +#: .\templates\xadmin\views\model_list.html:39 +msgid "Columns" +msgstr "显示列" + +#: .\templates\xadmin\views\model_list.html:42 +msgid "Restore Selected" +msgstr "恢复显示列" + +#: .\templates\xadmin\views\model_list.html:147 +#: .\templates\xadmin\widgets\list.html:33 +msgid "Empty list" +msgstr "空列表" + +#: .\templates\xadmin\views\recover_form.html:20 +msgid "Press the recover button below to recover this version of the object." +msgstr "点击下方的“还原”按钮还原到该版本。" + +#: .\templates\xadmin\views\recover_list.html:19 +msgid "" +"Choose a date from the list below to recover a deleted version of an object." +msgstr "从以下列表中选择一个日期来恢复删除掉的数据。" + +#: .\templates\xadmin\views\recover_list.html:39 +msgid "There are no deleted objects to recover." +msgstr "没有已删除的数据。" + +#: .\templates\xadmin\views\revision_diff.html:12 +#: .\templates\xadmin\views\revision_diff.html:17 +#, python-format +msgid "Diff %(verbose_name)s" +msgstr "%(verbose_name)s的不同" + +#: .\templates\xadmin\views\revision_diff.html:25 +msgid "Field" +msgstr "字段" + +#: .\templates\xadmin\views\revision_diff.html:26 +msgid "Version A" +msgstr "版本A" + +#: .\templates\xadmin\views\revision_diff.html:27 +msgid "Version B" +msgstr "版本B" + +#: .\templates\xadmin\views\revision_diff.html:39 +msgid "Revert to" +msgstr "还原到" + +#: .\templates\xadmin\views\revision_diff.html:40 +#: .\templates\xadmin\views\revision_diff.html:41 +msgid "Revert" +msgstr "还原" + +#: .\templates\xadmin\views\revision_form.html:16 +#, python-format +msgid "Revert %(verbose_name)s" +msgstr "还原%(verbose_name)s" + +#: .\templates\xadmin\views\revision_form.html:21 +msgid "Press the revert button below to revert to this version of the object." +msgstr "点击下方的“还原”按钮还原数据到该版本。" + +#: .\templates\xadmin\views\revision_form.html:27 +msgid "Revert this revision" +msgstr "还原该版本" + +#: .\templates\xadmin\widgets\addform.html:14 +msgid "Success" +msgstr "成功" + +#: .\templates\xadmin\widgets\addform.html:14 +msgid "Add success, click edit to edit." +msgstr "添加成功,点击 编辑 可以继续修改该数据。" + +#: .\templates\xadmin\widgets\addform.html:17 +msgid "Quick Add" +msgstr "快速添加" + +#: .\templates\xadmin\widgets\base.html:31 +msgid "Widget Options" +msgstr "小组件设置项" + +#: .\templates\xadmin\widgets\base.html:42 +msgid "Save changes" +msgstr "保存变更" + +#: .\views\base.py:320 +msgid "Django Xadmin" +msgstr "Django Xadmin" + +#: .\views\base.py:321 +msgid "my-company.inc" +msgstr "我的公司" + +#: .\views\dashboard.py:189 +msgid "Widget ID" +msgstr "小组件ID" + +#: .\views\dashboard.py:190 +msgid "Widget Title" +msgstr "小组件标题" + +#: .\views\dashboard.py:255 +msgid "Html Content Widget, can write any html content in widget." +msgstr "HTML内容小组件,可以编写任意HTML内容。" + +#: .\views\dashboard.py:258 +msgid "Html Content" +msgstr "HTML内容" + +#: .\views\dashboard.py:321 +msgid "Target Model" +msgstr "目标数据" + +#: .\views\dashboard.py:372 +msgid "Quick button Widget, quickly open any page." +msgstr "快捷按钮小组件,可以快速打开任意页面。" + +#: .\views\dashboard.py:374 +msgid "Quick Buttons" +msgstr "快速按钮" + +#: .\views\dashboard.py:419 +msgid "Any Objects list Widget." +msgstr "数据列表小组件" + +#: .\views\dashboard.py:459 +msgid "Add any model object Widget." +msgstr "添加任意数据的小组件" + +#: .\views\dashboard.py:495 +msgid "Dashboard" +msgstr "仪表盘" + +#: .\views\dashboard.py:636 +#, python-format +msgid "%s Dashboard" +msgstr "%s 主页" + +#: .\views\delete.py:104 +#, python-format +msgid "The %(name)s \"%(obj)s\" was deleted successfully." +msgstr "%(name)s \"%(obj)s\" 删除成功。" + +#: .\views\detail.py:173 .\views\edit.py:216 .\views\form.py:74 +msgid "Other Fields" +msgstr "其它字段" + +#: .\views\detail.py:235 +#, python-format +msgid "%s Detail" +msgstr "%s详情" + +#: .\views\edit.py:258 +msgid "Added." +msgstr "已添加" + +#: .\views\edit.py:260 +#, python-format +msgid "Changed %s." +msgstr "修改 %s" + +#: .\views\edit.py:260 +msgid "and" +msgstr "和" + +#: .\views\edit.py:263 +msgid "No fields changed." +msgstr "没有数据变化" + +#: .\views\edit.py:426 +#, python-format +msgid "The %(name)s \"%(obj)s\" was added successfully." +msgstr "%(name)s \"%(obj)s\" 添加成功。" + +#: .\views\edit.py:431 .\views\edit.py:526 +msgid "You may edit it again below." +msgstr "你可以在下面再次编辑它。" + +#: .\views\edit.py:435 .\views\edit.py:529 +#, python-format +msgid "You may add another %s below." +msgstr "你可以在下面增加另一个 %s 。" + +#: .\views\edit.py:477 +#, python-format +msgid "Change %s" +msgstr "修改 %s" + +#: .\views\edit.py:522 +#, python-format +msgid "The %(name)s \"%(obj)s\" was changed successfully." +msgstr "%(name)s \"%(obj)s\" 修改成功。" + +#: .\views\form.py:168 +#, python-format +msgid "The %s was changed successfully." +msgstr "%s 修改成功。" + +#: .\views\list.py:192 +msgid "Database error" +msgstr "数据库错误" + +#: .\views\list.py:369 +#, python-format +msgid "%s List" +msgstr "%s列表" + +#: .\views\list.py:498 +msgid "Sort ASC" +msgstr "正序" + +#: .\views\list.py:499 +msgid "Sort DESC" +msgstr "倒序" + +#: .\views\list.py:503 +msgid "Cancel Sort" +msgstr "取消排序" + +#: .\views\website.py:17 +msgid "Main Dashboard" +msgstr "主页面" + +#: .\widgets.py:53 .\widgets.py:81 +msgid "Now" +msgstr "现在" diff --git a/xadmin/locale/zh_Hans/LC_MESSAGES/djangojs.mo b/xadmin/locale/zh_Hans/LC_MESSAGES/djangojs.mo new file mode 100644 index 000000000..dea023170 Binary files /dev/null and b/xadmin/locale/zh_Hans/LC_MESSAGES/djangojs.mo differ diff --git a/xadmin/locale/zh_CN/LC_MESSAGES/djangojs.po b/xadmin/locale/zh_Hans/LC_MESSAGES/djangojs.po similarity index 75% rename from xadmin/locale/zh_CN/LC_MESSAGES/djangojs.po rename to xadmin/locale/zh_Hans/LC_MESSAGES/djangojs.po index 0fc75bc68..65fb767de 100644 --- a/xadmin/locale/zh_CN/LC_MESSAGES/djangojs.po +++ b/xadmin/locale/zh_Hans/LC_MESSAGES/djangojs.po @@ -1,27 +1,46 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # sshwsfc , 2013 msgid "" msgstr "" "Project-Id-Version: xadmin-core\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-04-30 23:11+0800\n" +"POT-Creation-Date: 2015-05-22 16:02+0800\n" "PO-Revision-Date: 2013-11-20 12:41+0000\n" "Last-Translator: sshwsfc \n" "Language-Team: Chinese (China) (http://www.transifex.com/projects/p/xadmin/language/zh_CN/)\n" +"Language: 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" -#: static/xadmin/js/xadmin.plugin.actions.js:20 +#: static/xadmin/js/xadmin.page.dashboard.js:14 +#: static/xadmin/js/xadmin.plugin.details.js:24 +#: static/xadmin/js/xadmin.plugin.quick-form.js:172 +msgid "Close" +msgstr "关闭" + +#: static/xadmin/js/xadmin.page.dashboard.js:15 +msgid "Save changes" +msgstr "保存修改" + +#: static/xadmin/js/xadmin.plugin.actions.js:11 msgid "%(sel)s of %(cnt)s selected" msgid_plural "%(sel)s of %(cnt)s selected" msgstr[0] "选中了 %(cnt)s 个中的 %(sel)s 个" +msgstr[1] "选中了 %(cnt)s 个中的 %(sel)s 个" + +#: static/xadmin/js/xadmin.plugin.details.js:25 +msgid "Edit" +msgstr "编辑" + +#: static/xadmin/js/xadmin.plugin.quick-form.js:173 +msgid "Add" +msgstr "添加" #: static/xadmin/js/xadmin.plugin.revision.js:25 msgid "New Item" @@ -40,9 +59,7 @@ msgid "Su Mo Tu We Th Fr Sa Su" msgstr "日 一 二 三 四 五 六" #: static/xadmin/js/xadmin.widget.datetime.js:35 -msgid "" -"January February March April May June July August September October November" -" December" +msgid "January February March April May June July August September October November December" msgstr "一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月" #: static/xadmin/js/xadmin.widget.datetime.js:36 diff --git a/xadmin/migrations/0001_initial.py b/xadmin/migrations/0001_initial.py new file mode 100644 index 000000000..1eeee381a --- /dev/null +++ b/xadmin/migrations/0001_initial.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-03-20 13:46 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL) + ] + + operations = [ + migrations.CreateModel( + name='Bookmark', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=128, verbose_name='Title')), + ('url_name', models.CharField(max_length=64, verbose_name='Url Name')), + ('query', models.CharField(blank=True, max_length=1000, verbose_name='Query String')), + ('is_share', models.BooleanField(default=False, verbose_name='Is Shared')), + ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')), + ], + options={ + 'verbose_name': 'Bookmark', + 'verbose_name_plural': 'Bookmarks', + }, + ), + migrations.CreateModel( + name='UserSettings', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.CharField(max_length=256, verbose_name='Settings Key')), + ('value', models.TextField(verbose_name='Settings Content')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')), + ], + options={ + 'verbose_name': 'User Setting', + 'verbose_name_plural': 'User Settings', + }, + ), + migrations.CreateModel( + name='UserWidget', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('page_id', models.CharField(max_length=256, verbose_name='Page')), + ('widget_type', models.CharField(max_length=50, verbose_name='Widget Type')), + ('value', models.TextField(verbose_name='Widget Params')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')), + ], + options={ + 'verbose_name': 'User Widget', + 'verbose_name_plural': 'User Widgets', + }, + ), + ] diff --git a/xadmin/migrations/0002_log.py b/xadmin/migrations/0002_log.py new file mode 100644 index 000000000..3153bee7b --- /dev/null +++ b/xadmin/migrations/0002_log.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-15 05:50 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('xadmin', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Log', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('action_time', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='action time')), + ('ip_addr', models.GenericIPAddressField(blank=True, null=True, verbose_name='action ip')), + ('object_id', models.TextField(blank=True, null=True, verbose_name='object id')), + ('object_repr', models.CharField(max_length=200, verbose_name='object repr')), + ('action_flag', models.PositiveSmallIntegerField(verbose_name='action flag')), + ('message', models.TextField(blank=True, verbose_name='change message')), + ('content_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='contenttypes.ContentType', verbose_name='content type')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')), + ], + options={ + 'ordering': ('-action_time',), + 'verbose_name': 'log entry', + 'verbose_name_plural': 'log entries', + }, + ), + ] diff --git a/xadmin/migrations/0003_auto_20160715_0100.py b/xadmin/migrations/0003_auto_20160715_0100.py new file mode 100644 index 000000000..073f5b4b4 --- /dev/null +++ b/xadmin/migrations/0003_auto_20160715_0100.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-15 06:00 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('xadmin', '0002_log'), + ] + + operations = [ + migrations.AlterField( + model_name='log', + name='action_flag', + field=models.CharField(max_length=32, verbose_name='action flag'), + ), + ] diff --git a/xadmin/migrations/__init__.py b/xadmin/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/xadmin/models.py b/xadmin/models.py index 614f40490..da5145641 100644 --- a/xadmin/models.py +++ b/xadmin/models.py @@ -1,25 +1,23 @@ import json import django from django.db import models +from django.utils import timezone from django.conf import settings from django.contrib.contenttypes.models import ContentType -from django.utils.translation import ugettext_lazy as _ -from django.core.urlresolvers import reverse +from django.utils.translation import ugettext_lazy as _, ugettext +from django.core.urlresolvers import NoReverseMatch, reverse from django.core.serializers.json import DjangoJSONEncoder from django.db.models.base import ModelBase -from django.utils.encoding import smart_unicode +from django.utils.encoding import python_2_unicode_compatible, smart_text -from django.db.models.signals import post_syncdb +from django.db.models.signals import post_migrate from django.contrib.auth.models import Permission import datetime import decimal +from xadmin.util import quote -if 4 < django.VERSION[1] < 7: - AUTH_USER_MODEL = django.contrib.auth.get_user_model() -else: - AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User') - +AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User') def add_view_permissions(sender, **kwargs): """ @@ -40,9 +38,10 @@ def add_view_permissions(sender, **kwargs): #print "Added view permission for %s" % content_type.name # check for all our view permissions after a syncdb -post_syncdb.connect(add_view_permissions) +post_migrate.connect(add_view_permissions) +@python_2_unicode_compatible class Bookmark(models.Model): title = models.CharField(_(u'Title'), max_length=128) user = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_(u"user"), blank=True, null=True) @@ -58,7 +57,7 @@ def url(https://github.com/self): base_url = base_url + '?' + self.query return base_url - def __unicode__(self): + def __str__(self): return self.title class Meta: @@ -68,21 +67,22 @@ class Meta: class JSONEncoder(DjangoJSONEncoder): def default(self, o): - if isinstance(o, datetime.date): - return o.strftime('%Y-%m-%d') - elif isinstance(o, datetime.datetime): + if isinstance(o, datetime.datetime): return o.strftime('%Y-%m-%d %H:%M:%S') + elif isinstance(o, datetime.date): + return o.strftime('%Y-%m-%d') elif isinstance(o, decimal.Decimal): return str(o) elif isinstance(o, ModelBase): - return '%s.%s' % (o._meta.app_label, o._meta.module_name) + return '%s.%s' % (o._meta.app_label, o._meta.model_name) else: try: return super(JSONEncoder, self).default(o) except Exception: - return smart_unicode(o) + return smart_text(o) +@python_2_unicode_compatible class UserSettings(models.Model): user = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_(u"user")) key = models.CharField(_('Settings Key'), max_length=256) @@ -94,7 +94,7 @@ def json_value(self): def set_json(self, obj): self.value = json.dumps(obj, cls=JSONEncoder, ensure_ascii=False) - def __unicode__(self): + def __str__(self): return "%s %s" % (self.user, self.key) class Meta: @@ -102,6 +102,7 @@ class Meta: verbose_name_plural = _('User Settings') +@python_2_unicode_compatible class UserWidget(models.Model): user = models.ForeignKey(AUTH_USER_MODEL, verbose_name=_(u"user")) page_id = models.CharField(_(u"Page"), max_length=256) @@ -129,9 +130,60 @@ def save(self, *args, **kwargs): except Exception: pass - def __unicode__(self): + def __str__(self): return "%s %s widget" % (self.user, self.widget_type) class Meta: verbose_name = _(u'User Widget') verbose_name_plural = _('User Widgets') + + +@python_2_unicode_compatible +class Log(models.Model): + action_time = models.DateTimeField( + _('action time'), + default=timezone.now, + editable=False, + ) + user = models.ForeignKey( + AUTH_USER_MODEL, + models.CASCADE, + verbose_name=_('user'), + ) + ip_addr = models.GenericIPAddressField(_('action ip'), blank=True, null=True) + content_type = models.ForeignKey( + ContentType, + models.SET_NULL, + verbose_name=_('content type'), + blank=True, null=True, + ) + object_id = models.TextField(_('object id'), blank=True, null=True) + object_repr = models.CharField(_('object repr'), max_length=200) + action_flag = models.CharField(_('action flag'), max_length=32) + message = models.TextField(_('change message'), blank=True) + + class Meta: + verbose_name = _('log entry') + verbose_name_plural = _('log entries') + ordering = ('-action_time',) + + def __repr__(self): + return smart_text(self.action_time) + + def __str__(self): + if self.action_flag == 'create': + return ugettext('Added "%(object)s".') % {'object': self.object_repr} + elif self.action_flag == 'change': + return ugettext('Changed "%(object)s" - %(changes)s') % { + 'object': self.object_repr, + 'changes': self.message, + } + elif self.action_flag == 'delete' and self.object_repr: + return ugettext('Deleted "%(object)s."') % {'object': self.object_repr} + + return self.message + + def get_edited_object(self): + "Returns the edited object represented by this log entry" + return self.content_type.get_object_for_this_type(pk=self.object_id) + diff --git a/xadmin/plugins/__init__.py b/xadmin/plugins/__init__.py index d6c7b2840..e570dfe67 100644 --- a/xadmin/plugins/__init__.py +++ b/xadmin/plugins/__init__.py @@ -1,12 +1,39 @@ -PLUGINS = ('actions', 'filters', 'bookmark', 'export', 'layout', 'refresh', 'sortable', 'details', - 'editable', 'relate', 'chart', 'ajax', 'relfield', 'inline', 'topnav', 'portal', 'quickform', - 'wizard', 'images', 'auth', 'multiselect', 'themes', 'aggregation', 'mobile', 'passwords', - 'sitemenu', 'language', 'comments','quickfilter') +PLUGINS = ( + 'actions', + 'filters', + 'bookmark', + 'export', + 'layout', + 'refresh', + 'details', + 'editable', + 'relate', + 'chart', + 'ajax', + 'relfield', + 'inline', + 'topnav', + 'portal', + 'quickform', + 'wizard', + 'images', + 'auth', + 'multiselect', + 'themes', + 'aggregation', + 'mobile', + 'passwords', + 'sitemenu', + 'language', + 'quickfilter', + 'sortablelist', + 'importexport' +) def register_builtin_plugins(site): - from django.utils.importlib import import_module + from importlib import import_module from django.conf import settings exclude_plugins = getattr(settings, 'XADMIN_EXCLUDE_PLUGINS', []) diff --git a/xadmin/plugins/actions.py b/xadmin/plugins/actions.py index 6dbb4cfca..02085bf33 100644 --- a/xadmin/plugins/actions.py +++ b/xadmin/plugins/actions.py @@ -1,16 +1,21 @@ +from collections import OrderedDict from django import forms from django.core.exceptions import PermissionDenied from django.db import router from django.http import HttpResponse, HttpResponseRedirect from django.template import loader from django.template.response import TemplateResponse -from django.utils.datastructures import SortedDict -from django.utils.encoding import force_unicode +from django.utils import six +from django.utils.encoding import force_text from django.utils.safestring import mark_safe from django.utils.translation import ugettext as _, ungettext from django.utils.text import capfirst + +from django.contrib.admin.utils import get_deleted_objects + +from xadmin.plugins.utils import get_context_dict from xadmin.sites import site -from xadmin.util import model_format_dict, get_deleted_objects, model_ngettext +from xadmin.util import model_format_dict, model_ngettext from xadmin.views import BaseAdminPlugin, ListAdminView from xadmin.views.base import filter_hook, ModelAdminView @@ -20,14 +25,13 @@ def action_checkbox(obj): - return checkbox.render(ACTION_CHECKBOX_NAME, force_unicode(obj.pk)) + return checkbox.render(ACTION_CHECKBOX_NAME, force_text(obj.pk)) action_checkbox.short_description = mark_safe( '') action_checkbox.allow_tags = True action_checkbox.allow_export = False action_checkbox.is_column = False - class BaseActionView(ModelAdminView): action_name = None description = None @@ -56,6 +60,8 @@ class DeleteSelectedAction(BaseActionView): delete_confirmation_template = None delete_selected_confirmation_template = None + delete_models_batch = True + model_perm = 'delete' icon = 'fa fa-times' @@ -63,7 +69,13 @@ class DeleteSelectedAction(BaseActionView): def delete_models(self, queryset): n = queryset.count() if n: - queryset.delete() + if self.delete_models_batch: + self.log('delete', _('Batch delete %(count)d %(items)s.') % { "count": n, "items": model_ngettext(self.opts, n) }) + queryset.delete() + else: + for obj in queryset: + self.log('delete', '', obj) + obj.delete() self.message_user(_("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(self.opts, n) }, 'success') @@ -78,7 +90,7 @@ def do_action(self, queryset): # Populate deletable_objects, a data structure of all related objects that # will also be deleted. - deletable_objects, perms_needed, protected = get_deleted_objects( + deletable_objects, model_count, perms_needed, protected = get_deleted_objects( queryset, self.opts, self.user, self.admin_site, using) # The user has already confirmed the deletion. @@ -91,9 +103,9 @@ def do_action(self, queryset): return None if len(queryset) == 1: - objects_name = force_unicode(self.opts.verbose_name) + objects_name = force_text(self.opts.verbose_name) else: - objects_name = force_unicode(self.opts.verbose_name_plural) + objects_name = force_text(self.opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} @@ -115,7 +127,7 @@ def do_action(self, queryset): # Display the confirmation page return TemplateResponse(self.request, self.delete_selected_confirmation_template or - self.get_template_list('views/model_delete_selected_confirm.html'), context, current_app=self.admin_site.name) + self.get_template_list('views/model_delete_selected_confirm.html'), context) class ActionPlugin(BaseAdminPlugin): @@ -203,7 +215,7 @@ def response_action(self, ac, queryset): def get_actions(self): if self.actions is None: - return SortedDict() + return OrderedDict() actions = [self.get_action(action) for action in self.global_actions] @@ -216,9 +228,11 @@ def get_actions(self): # get_action might have returned None, so filter any of those out. actions = filter(None, actions) + if six.PY3: + actions = list(actions) - # Convert the actions into a SortedDict keyed by name. - actions = SortedDict([ + # Convert the actions into a OrderedDict keyed by name. + actions = OrderedDict([ (name, (ac, name, desc, icon)) for ac, name, desc, icon in actions ]) @@ -231,7 +245,7 @@ def get_action_choices(self): tuple (name, description). """ choices = [] - for ac, name, description, icon in self.actions.itervalues(): + for ac, name, description, icon in self.actions.values(): choice = (name, description % model_format_dict(self.opts), icon) choices.append(choice) return choices @@ -279,7 +293,8 @@ def get_media(self, media): # Block Views def block_results_bottom(self, context, nodes): if self.actions and self.admin_view.result_count: - nodes.append(loader.render_to_string('xadmin/blocks/model_list.results_bottom.actions.html', context_instance=context)) + nodes.append(loader.render_to_string('xadmin/blocks/model_list.results_bottom.actions.html', + context=get_context_dict(context))) site.register_plugin(ActionPlugin, ListAdminView) diff --git a/xadmin/plugins/ajax.py b/xadmin/plugins/ajax.py index aa5bb32eb..b09bea21b 100644 --- a/xadmin/plugins/ajax.py +++ b/xadmin/plugins/ajax.py @@ -1,7 +1,7 @@ -from django import forms -from django.utils.datastructures import SortedDict +from collections import OrderedDict +from django.forms.utils import ErrorDict from django.utils.html import escape -from django.utils.encoding import force_unicode +from django.utils.encoding import force_text from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ListAdminView, ModelFormAdminView, DetailAdminView @@ -12,7 +12,7 @@ class BaseAjaxPlugin(BaseAdminPlugin): def init_request(self, *args, **kwargs): - return bool(self.request.is_ajax() or self.request.REQUEST.get('_ajax')) + return bool(self.request.is_ajax() or self.request.GET.get('_ajax')) class AjaxListPlugin(BaseAjaxPlugin): @@ -27,7 +27,7 @@ def get_list_display(self,list_display): def get_result_list(self, response): av = self.admin_view base_fields = self.get_list_display(av.base_list_display) - headers = dict([(c.field_name, force_unicode(c.text)) for c in av.result_headers( + headers = dict([(c.field_name, force_text(c.text)) for c in av.result_headers( ).cells if c.field_name in base_fields]) objects = [dict([(o.field_name, escape(str(o.value))) for i, o in @@ -37,7 +37,7 @@ def get_result_list(self, response): return self.render_response({'headers': headers, 'objects': objects, 'total_count': av.result_count, 'has_more': av.has_more}) -class JsonErrorDict(forms.util.ErrorDict): +class JsonErrorDict(ErrorDict): def __init__(self, errors, form): super(JsonErrorDict, self).__init__(errors) @@ -92,7 +92,7 @@ def get_response(self, __): result = self.admin_view.get_field_result(f) results.append((result.label, result.val)) - return self.render_response(SortedDict(results)) + return self.render_response(OrderedDict(results)) site.register_plugin(AjaxListPlugin, ListAdminView) site.register_plugin(AjaxFormPlugin, ModelFormAdminView) diff --git a/xadmin/plugins/auth.py b/xadmin/plugins/auth.py index cd2dc3239..1ab6f6110 100644 --- a/xadmin/plugins/auth.py +++ b/xadmin/plugins/auth.py @@ -4,18 +4,22 @@ AdminPasswordChangeForm, PasswordChangeForm) from django.contrib.auth.models import Group, Permission from django.core.exceptions import PermissionDenied +from django.conf import settings from django.template.response import TemplateResponse from django.utils.decorators import method_decorator from django.http import HttpResponseRedirect from django.utils.html import escape +from django.utils.encoding import smart_text from django.utils.translation import ugettext as _ from django.views.decorators.debug import sensitive_post_parameters from django.forms import ModelMultipleChoiceField +from django.contrib.auth import get_user_model from xadmin.layout import Fieldset, Main, Side, Row, FormHelper from xadmin.sites import site -from xadmin.util import unquote, User +from xadmin.util import unquote from xadmin.views import BaseAdminPlugin, ModelFormAdminView, ModelAdminView, CommAdminView, csrf_protect_m +User = get_user_model() ACTION_NAME = { 'add': _('Can add %s'), @@ -151,6 +155,12 @@ def queryset(self, qs): qs = qs.filter(**filters) return qs + def get_list_display(self, list_display): + if self.user_can_access_owned_objects_only and \ + not self.user.is_superuser and \ + self.user_owned_objects_field in list_display: + list_display.remove(self.user_owned_objects_field) + return list_display site.register_plugin(ModelPermissionPlugin, ModelAdminView) @@ -186,9 +196,10 @@ def get_context(self): context = super(ChangePasswordView, self).get_context() helper = FormHelper() helper.form_tag = False + helper.include_media = False self.form.helper = helper context.update({ - 'title': _('Change password: %s') % escape(unicode(self.obj)), + 'title': _('Change password: %s') % escape(smart_text(self.obj)), 'form': self.form, 'has_delete_permission': False, 'has_change_permission': True, @@ -201,7 +212,7 @@ def get_response(self): return TemplateResponse(self.request, [ self.change_user_password_template or 'xadmin/auth/user/change_password.html' - ], self.get_context(), current_app=self.admin_site.name) + ], self.get_context()) @method_decorator(sensitive_post_parameters()) @csrf_protect_m @@ -250,7 +261,9 @@ def post(self, request): else: return self.get_response() -site.register_view(r'^auth/user/(.+)/update/password/$', + +user_model = settings.AUTH_USER_MODEL.lower().replace('.','/') +site.register_view(r'^%s/(.+)/password/$' % user_model, ChangePasswordView, name='user_change_password') site.register_view(r'^account/password/$', ChangeAccountPasswordView, name='account_password') diff --git a/xadmin/plugins/batch.py b/xadmin/plugins/batch.py index 24eadeeda..b322af98e 100644 --- a/xadmin/plugins/batch.py +++ b/xadmin/plugins/batch.py @@ -5,7 +5,7 @@ from django.core.exceptions import PermissionDenied from django.forms.models import modelform_factory from django.template.response import TemplateResponse -from django.utils.encoding import force_unicode +from django.utils.encoding import force_text from django.utils.safestring import mark_safe from django.utils.translation import ugettext as _, ugettext_lazy from xadmin.layout import FormHelper, Layout, Fieldset, Container, Col @@ -16,10 +16,10 @@ BATCH_CHECKBOX_NAME = '_batch_change_fields' + class ChangeFieldWidgetWrapper(forms.Widget): def __init__(self, widget): - self.is_hidden = widget.is_hidden self.needs_multipart_form = widget.needs_multipart_form self.attrs = widget.attrs self.widget = widget @@ -74,7 +74,8 @@ def change_models(self, queryset, cleaned_data): n = queryset.count() data = {} - for f in self.opts.fields: + fields = self.opts.fields + self.opts.many_to_many + for f in fields: if not f.editable or isinstance(f, models.AutoField) \ or not f.name in cleaned_data: continue @@ -121,15 +122,16 @@ def do_action(self, queryset): helper = FormHelper() helper.form_tag = False + helper.include_media = False helper.add_layout(Layout(Container(Col('full', Fieldset("", *self.form_obj.fields.keys(), css_class="unsort no_title"), horizontal=True, span=12) ))) self.form_obj.helper = helper count = len(queryset) if count == 1: - objects_name = force_unicode(self.opts.verbose_name) + objects_name = force_text(self.opts.verbose_name) else: - objects_name = force_unicode(self.opts.verbose_name_plural) + objects_name = force_text(self.opts.verbose_name_plural) context = self.get_context() context.update({ @@ -144,7 +146,7 @@ def do_action(self, queryset): }) return TemplateResponse(self.request, self.batch_change_form_template or - self.get_template_list('views/batch_change_form.html'), context, current_app=self.admin_site.name) + self.get_template_list('views/batch_change_form.html'), context) @filter_hook def get_media(self): diff --git a/xadmin/plugins/bookmark.py b/xadmin/plugins/bookmark.py index 7c7dcb610..3d612cec8 100644 --- a/xadmin/plugins/bookmark.py +++ b/xadmin/plugins/bookmark.py @@ -1,21 +1,23 @@ -from django.template import loader -from django.core.urlresolvers import reverse -from django.utils.translation import ugettext_lazy as _ -from django.utils.decorators import method_decorator -from django.views.decorators.csrf import csrf_protect from django.contrib.contenttypes.models import ContentType +from django.core.urlresolvers import reverse from django.db import transaction from django.db.models import Q from django.forms import ModelChoiceField from django.http import QueryDict +from django.template import loader +from django.utils.decorators import method_decorator +from django.utils.encoding import smart_text +from django.utils.translation import ugettext_lazy as _ +from django.views.decorators.csrf import csrf_protect +from xadmin.filters import FILTER_PREFIX, SEARCH_VAR +from xadmin.plugins.relate import RELATE_PREFIX +from xadmin.plugins.utils import get_context_dict from xadmin.sites import site from xadmin.views import ModelAdminView, BaseAdminPlugin, ListAdminView from xadmin.views.list import COL_LIST_VAR, ORDER_VAR from xadmin.views.dashboard import widget_manager, BaseWidget, PartialBaseWidget -from xadmin.filters import FILTER_PREFIX, SEARCH_VAR -from xadmin.plugins.relate import RELATE_PREFIX from xadmin.models import Bookmark @@ -40,11 +42,19 @@ def get_context(self, context): bookmarks = [] - current_qs = '&'.join(['%s=%s' % (k, v) for k, v in sorted( - filter(lambda i: bool(i[1] and (i[0] in (COL_LIST_VAR, ORDER_VAR, SEARCH_VAR) or i[0].startswith(FILTER_PREFIX) - or i[0].startswith(RELATE_PREFIX))), self.request.GET.items()))]) - - model_info = (self.opts.app_label, self.opts.module_name) + current_qs = '&'.join([ + '%s=%s' % (k, v) + for k, v in sorted(filter( + lambda i: bool(i[1] and ( + i[0] in (COL_LIST_VAR, ORDER_VAR, SEARCH_VAR) + or i[0].startswith(FILTER_PREFIX) + or i[0].startswith(RELATE_PREFIX) + )), + self.request.GET.items() + )) + ]) + + model_info = (self.opts.app_label, self.opts.model_name) has_selected = False menu_title = _(u"Bookmark") list_base_url = reverse('xadmin:%s_%s_changelist' % @@ -53,8 +63,10 @@ def get_context(self, context): # local bookmarks for bk in self.list_bookmarks: title = bk['title'] - params = dict( - [(FILTER_PREFIX + k, v) for (k, v) in bk['query'].items()]) + params = dict([ + (FILTER_PREFIX + k, v) + for (k, v) in bk['query'].items() + ]) if 'order' in bk: params[ORDER_VAR] = '.'.join(bk['order']) if 'cols' in bk: @@ -63,7 +75,10 @@ def get_context(self, context): params[SEARCH_VAR] = bk['search'] def check_item(i): return bool(i[1]) or i[1] == False - bk_qs = '&'.join(['%s=%s' % (k, v) for k, v in sorted(filter(check_item, params.items()))]) + bk_qs = '&'.join([ + '%s=%s' % (k, v) + for k, v in sorted(filter(check_item, params.items())) + ]) url = list_base_url + '?' + bk_qs selected = (current_qs == bk_qs) @@ -75,7 +90,7 @@ def check_item(i): has_selected = True content_type = ContentType.objects.get_for_model(self.model) - bk_model_info = (Bookmark._meta.app_label, Bookmark._meta.module_name) + bk_model_info = (Bookmark._meta.app_label, Bookmark._meta.model_name) bookmarks_queryset = Bookmark.objects.filter( content_type=content_type, url_name='xadmin:%s_%s_changelist' % model_info @@ -119,15 +134,16 @@ def get_media(self, media): # Block Views def block_nav_menu(self, context, nodes): if self.show_bookmarks: - nodes.insert(0, loader.render_to_string('xadmin/blocks/model_list.nav_menu.bookmarks.html', context_instance=context)) + nodes.insert(0, loader.render_to_string('xadmin/blocks/model_list.nav_menu.bookmarks.html', + context=get_context_dict(context))) class BookmarkView(ModelAdminView): @csrf_protect_m - @transaction.commit_on_success + @transaction.atomic def post(self, request): - model_info = (self.opts.app_label, self.opts.module_name) + model_info = (self.opts.app_label, self.opts.model_name) url_name = 'xadmin:%s_%s_changelist' % model_info bookmark = Bookmark( content_type=ContentType.objects.get_for_model(self.model), @@ -186,7 +202,7 @@ def setup(self): self.bookmark = bookmark if not self.title: - self.title = unicode(bookmark) + self.title = smart_text(bookmark) req = self.make_get_request("", data.items()) self.list_view = self.get_view_class( @@ -205,9 +221,13 @@ def context(self, context): context['result_headers'] = [c for c in list_view.result_headers( ).cells if c.field_name in base_fields] - context['results'] = [[o for i, o in - enumerate(filter(lambda c:c.field_name in base_fields, r.cells))] - for r in list_view.results()] + context['results'] = [ + [o for i, o in enumerate(filter( + lambda c: c.field_name in base_fields, + r.cells + ))] + for r in list_view.results() + ] context['result_count'] = list_view.result_count context['page_url'] = self.bookmark.url diff --git a/xadmin/plugins/chart.py b/xadmin/plugins/chart.py index e83ab8ca9..e2b0a649a 100644 --- a/xadmin/plugins/chart.py +++ b/xadmin/plugins/chart.py @@ -1,21 +1,21 @@ +import calendar import datetime import decimal -import calendar -from django.template import loader -from django.http import HttpResponseNotFound from django.core.serializers.json import DjangoJSONEncoder -from django.http import HttpResponse -from django.utils.encoding import smart_unicode from django.db import models +from django.http import HttpResponse, HttpResponseNotFound +from django.template import loader from django.utils.http import urlencode +from django.utils.encoding import force_text, smart_text from django.utils.translation import ugettext_lazy as _, ugettext +from xadmin.plugins.utils import get_context_dict from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ListAdminView from xadmin.views.dashboard import ModelBaseWidget, widget_manager -from xadmin.util import lookup_field, label_for_field, force_unicode, json +from xadmin.util import lookup_field, label_for_field, json @widget_manager.register @@ -76,7 +76,7 @@ def default(self, o): try: return super(JSONEncoder, self).default(o) except Exception: - return smart_unicode(o) + return smart_text(o) class ChartsPlugin(BaseAdminPlugin): @@ -98,7 +98,8 @@ def block_results_top(self, context, nodes): context.update({ 'charts': [{"name": name, "title": v['title'], 'url': self.get_chart_url(https://github.com/name,%20v)} for name, v in self.data_charts.items()], }) - nodes.append(loader.render_to_string('xadmin/blocks/model_list.results_top.charts.html', context_instance=context)) + nodes.append(loader.render_to_string('xadmin/blocks/model_list.results_top.charts.html', + context=get_context_dict(context))) class ChartsView(ListAdminView): @@ -122,7 +123,7 @@ def get(self, request, name): self.y_fields = ( y_fields,) if type(y_fields) not in (list, tuple) else y_fields - datas = [{"data":[], "label": force_unicode(label_for_field( + datas = [{"data":[], "label": force_text(label_for_field( i, self.model, model_admin=self))} for i in self.y_fields] self.make_result_list() diff --git a/xadmin/plugins/details.py b/xadmin/plugins/details.py index 2c37fe118..0b5ed919e 100644 --- a/xadmin/plugins/details.py +++ b/xadmin/plugins/details.py @@ -39,12 +39,12 @@ def result_item(self, item, obj, field_name, row): try: item_res_uri = reverse( '%s:%s_%s_detail' % (self.admin_site.app_name, - opts.app_label, opts.module_name), + opts.app_label, opts.model_name), args=(getattr(rel_obj, opts.pk.attname),)) if item_res_uri: if has_change_perm: edit_url = reverse( - '%s:%s_%s_change' % (self.admin_site.app_name, opts.app_label, opts.module_name), + '%s:%s_%s_change' % (self.admin_site.app_name, opts.app_label, opts.model_name), args=(getattr(rel_obj, opts.pk.attname),)) else: edit_url = '' diff --git a/xadmin/plugins/editable.py b/xadmin/plugins/editable.py index 6a20cc79c..1b49feb60 100644 --- a/xadmin/plugins/editable.py +++ b/xadmin/plugins/editable.py @@ -3,7 +3,7 @@ from django.db import models, transaction from django.forms.models import modelform_factory from django.http import Http404, HttpResponse -from django.utils.encoding import force_unicode, smart_unicode +from django.utils.encoding import force_text, smart_text from django.utils.html import escape, conditional_escape from django.utils.safestring import mark_safe from django.utils.translation import ugettext as _ @@ -71,7 +71,7 @@ def init_request(self, object_id, *args, **kwargs): if self.org_obj is None: raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % - {'name': force_unicode(self.opts.verbose_name), 'key': escape(object_id)}) + {'name': force_text(self.opts.verbose_name), 'key': escape(object_id)}) def get_new_field_html(self, f): result = self.result_item(self.org_obj, f, {'is_display_first': @@ -92,7 +92,7 @@ def _get_new_field_html(self, field_name): allow_tags = True text = boolean_icon(value) else: - text = smart_unicode(value) + text = smart_text(value) else: if isinstance(f.rel, models.ManyToOneRel): field_val = getattr(self.org_obj, f.name) @@ -118,6 +118,7 @@ def get(self, request, object_id): helper = FormHelper() helper.form_tag = False + helper.include_media = False form.helper = helper s = '{% load i18n crispy_forms_tags %}
{% crispy form %}' + \ @@ -129,7 +130,7 @@ def get(self, request, object_id): @filter_hook @csrf_protect_m - @transaction.commit_on_success + @transaction.atomic def post(self, request, object_id): model_fields = [f.name for f in self.opts.fields] fields = [f for f in request.POST.keys() if f in model_fields] diff --git a/xadmin/plugins/export.py b/xadmin/plugins/export.py index 06b75f0fa..8ccc0f4e8 100644 --- a/xadmin/plugins/export.py +++ b/xadmin/plugins/export.py @@ -1,14 +1,18 @@ -import StringIO +import io import datetime import sys +from future.utils import iteritems from django.http import HttpResponse from django.template import loader -from django.utils.encoding import force_unicode, smart_unicode +from django.utils import six +from django.utils.encoding import force_text, smart_text from django.utils.html import escape from django.utils.translation import ugettext as _ from django.utils.xmlutils import SimplerXMLGenerator from django.db.models import BooleanField, NullBooleanField + +from xadmin.plugins.utils import get_context_dict from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ListAdminView from xadmin.util import json @@ -45,7 +49,8 @@ def block_top_toolbar(self, context, nodes): 'form_params': self.admin_view.get_form_params({'_do_': 'export'}, ('export_type',)), 'export_types': [{'type': et, 'name': self.export_names[et]} for et in self.list_export], }) - nodes.append(loader.render_to_string('xadmin/blocks/model_list.top_toolbar.exports.html', context_instance=context)) + nodes.append(loader.render_to_string('xadmin/blocks/model_list.top_toolbar.exports.html', + context=get_context_dict(context))) class ExportPlugin(BaseAdminPlugin): @@ -72,7 +77,7 @@ def _get_objects(self, context): rows = context['results'] return [dict([ - (force_unicode(headers[i].text), self._format_value(o)) for i, o in + (force_text(headers[i].text), self._format_value(o)) for i, o in enumerate(filter(lambda c:getattr(c, 'export', False), r.cells))]) for r in rows] def _get_datas(self, context): @@ -80,19 +85,19 @@ def _get_datas(self, context): new_rows = [[self._format_value(o) for o in filter(lambda c:getattr(c, 'export', False), r.cells)] for r in rows] - new_rows.insert(0, [force_unicode(c.text) for c in context['result_headers'].cells if c.export]) + new_rows.insert(0, [force_text(c.text) for c in context['result_headers'].cells if c.export]) return new_rows def get_xlsx_export(self, context): datas = self._get_datas(context) - output = StringIO.StringIO() + output = io.BytesIO() export_header = ( self.request.GET.get('export_xlsx_header', 'off') == 'on') model_name = self.opts.verbose_name book = xlsxwriter.Workbook(output) sheet = book.add_worksheet( - u"%s %s" % (_(u'Sheet'), force_unicode(model_name))) + u"%s %s" % (_(u'Sheet'), force_text(model_name))) styles = {'datetime': book.add_format({'num_format': 'yyyy-mm-dd hh:mm:ss'}), 'date': book.add_format({'num_format': 'yyyy-mm-dd'}), 'time': book.add_format({'num_format': 'hh:mm:ss'}), @@ -122,14 +127,14 @@ def get_xlsx_export(self, context): def get_xls_export(self, context): datas = self._get_datas(context) - output = StringIO.StringIO() + output = io.BytesIO() export_header = ( self.request.GET.get('export_xls_header', 'off') == 'on') model_name = self.opts.verbose_name book = xlwt.Workbook(encoding='utf8') sheet = book.add_sheet( - u"%s %s" % (_(u'Sheet'), force_unicode(model_name))) + u"%s %s" % (_(u'Sheet'), force_text(model_name))) styles = {'datetime': xlwt.easyxf(num_format_str='yyyy-mm-dd hh:mm:ss'), 'date': xlwt.easyxf(num_format_str='yyyy-mm-dd'), 'time': xlwt.easyxf(num_format_str='hh:mm:ss'), @@ -161,7 +166,8 @@ def _format_csv_text(self, t): if isinstance(t, bool): return _('Yes') if t else _('No') t = t.replace('"', '""').replace(',', '\,') - if isinstance(t, basestring): + cls_str = str if six.PY3 else basestring + if isinstance(t, cls_str): t = '"%s"' % t return t @@ -184,17 +190,17 @@ def _to_xml(self, xml, data): self._to_xml(xml, item) xml.endElement("row") elif isinstance(data, dict): - for key, value in data.iteritems(): + for key, value in iteritems(data): key = key.replace(' ', '_') xml.startElement(key, {}) self._to_xml(xml, value) xml.endElement(key) else: - xml.characters(smart_unicode(data)) + xml.characters(smart_text(data)) def get_xml_export(self, context): results = self._get_objects(context) - stream = StringIO.StringIO() + stream = io.StringIO() xml = SimplerXMLGenerator(stream, "utf-8") xml.startDocument() @@ -215,7 +221,7 @@ def get_json_export(self, context): def get_response(self, response, context, *args, **kwargs): file_type = self.request.GET.get('export_type', 'csv') response = HttpResponse( - mimetype="%s; charset=UTF-8" % self.export_mimes[file_type]) + content_type="%s; charset=UTF-8" % self.export_mimes[file_type]) file_name = self.opts.verbose_name.replace(' ', '_') response['Content-Disposition'] = ('attachment; filename=%s.%s' % ( @@ -227,7 +233,7 @@ def get_response(self, response, context, *args, **kwargs): # View Methods def get_result_list(self, __): if self.request.GET.get('all', 'off') == 'on': - self.admin_view.list_per_page = sys.maxint + self.admin_view.list_per_page = sys.maxsize return __() def result_header(self, item, field_name, row): diff --git a/xadmin/plugins/filters.py b/xadmin/plugins/filters.py index c13dec0a1..dc7e171d8 100644 --- a/xadmin/plugins/filters.py +++ b/xadmin/plugins/filters.py @@ -1,19 +1,24 @@ import operator +from future.utils import iteritems from xadmin import widgets +from xadmin.plugins.utils import get_context_dict -from xadmin.util import get_fields_from_path, lookup_needs_distinct +from django.contrib.admin.utils import get_fields_from_path, lookup_needs_distinct from django.core.exceptions import SuspiciousOperation, ImproperlyConfigured, ValidationError from django.db import models from django.db.models.fields import FieldDoesNotExist -from django.db.models.related import RelatedObject from django.db.models.sql.query import LOOKUP_SEP, QUERY_TERMS from django.template import loader +from django.utils import six from django.utils.encoding import smart_str from django.utils.translation import ugettext as _ -from xadmin.filters import manager as filter_manager, FILTER_PREFIX, SEARCH_VAR, DateFieldListFilter, RelatedFieldSearchFilter +from xadmin.filters import manager as filter_manager, FILTER_PREFIX, SEARCH_VAR, DateFieldListFilter, \ + RelatedFieldSearchFilter from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ListAdminView +from xadmin.util import is_related_field +from functools import reduce class IncorrectLookupParameters(Exception): @@ -49,7 +54,7 @@ def lookup_allowed(self, lookup, value): rel_name = None for part in parts[:-1]: try: - field, _, _, _ = model._meta.get_field_by_name(part) + field = model._meta.get_field(part) except FieldDoesNotExist: # Lookups on non-existants fields are ok, since they're ignored # later. @@ -57,7 +62,7 @@ def lookup_allowed(self, lookup, value): if hasattr(field, 'rel'): model = field.rel.to rel_name = field.rel.get_related_field().name - elif isinstance(field, RelatedObject): + elif is_related_field(field): model = field.model rel_name = model._meta.pk.name else: @@ -73,15 +78,15 @@ def lookup_allowed(self, lookup, value): def get_list_queryset(self, queryset): lookup_params = dict([(smart_str(k)[len(FILTER_PREFIX):], v) for k, v in self.admin_view.params.items() if smart_str(k).startswith(FILTER_PREFIX) and v != '']) - for p_key, p_val in lookup_params.iteritems(): + for p_key, p_val in iteritems(lookup_params): if p_val == "False": lookup_params[p_key] = False use_distinct = False # for clean filters self.admin_view.has_query_param = bool(lookup_params) - self.admin_view.clean_query_url = self.admin_view.get_query_string(remove= - [k for k in self.request.GET.keys() if k.startswith(FILTER_PREFIX)]) + self.admin_view.clean_query_url = self.admin_view.get_query_string(remove=[k for k in self.request.GET.keys() if + k.startswith(FILTER_PREFIX)]) # Normalize the types of keys if not self.free_query_filter: @@ -117,9 +122,9 @@ def get_list_queryset(self, queryset): field, self.request, lookup_params, self.model, self.admin_view, field_path=field_path) - if len(field_parts)>1: + if len(field_parts) > 1: # Add related model name to title - spec.title = "%s %s"%(field_parts[-2].name,spec.title) + spec.title = "%s %s" % (field_parts[-2].name, spec.title) # Check if we need to use distinct() use_distinct = (use_distinct or @@ -127,7 +132,7 @@ def get_list_queryset(self, queryset): if spec and spec.has_output(): try: new_qs = spec.do_filte(queryset) - except ValidationError, e: + except ValidationError as e: new_qs = None self.admin_view.message_user(_("Filtering error: %s") % e.messages[0], 'error') if new_qs is not None: @@ -137,22 +142,36 @@ def get_list_queryset(self, queryset): self.has_filters = bool(self.filter_specs) self.admin_view.filter_specs = self.filter_specs - self.admin_view.used_filter_num = len( - filter(lambda f: f.is_used, self.filter_specs)) + obj = filter(lambda f: f.is_used, self.filter_specs) + if six.PY3: + obj = list(obj) + self.admin_view.used_filter_num = len(obj) try: for key, value in lookup_params.items(): use_distinct = ( use_distinct or lookup_needs_distinct(self.opts, key)) - except FieldDoesNotExist, e: + except FieldDoesNotExist as e: raise IncorrectLookupParameters(e) try: - queryset = queryset.filter(**lookup_params) + # fix a bug by david: In demo, quick filter by IDC Name() cannot be used. + if isinstance(queryset, models.query.QuerySet) and lookup_params: + new_lookup_parames = dict() + for k, v in lookup_params.iteritems(): + list_v = v.split(',') + if len(list_v) > 0: + new_lookup_parames.update({k: list_v}) + else: + new_lookup_parames.update({k: v}) + queryset = queryset.filter(**new_lookup_parames) except (SuspiciousOperation, ImproperlyConfigured): raise - except Exception, e: + except Exception as e: raise IncorrectLookupParameters(e) + else: + if not isinstance(queryset, models.query.QuerySet): + pass query = self.request.GET.get(SEARCH_VAR, '') @@ -188,10 +207,16 @@ def construct_search(field_name): # Media def get_media(self, media): - if bool(filter(lambda s: isinstance(s, DateFieldListFilter), self.filter_specs)): + arr = filter(lambda s: isinstance(s, DateFieldListFilter), self.filter_specs) + if six.PY3: + arr = list(arr) + if bool(arr): media = media + self.vendor('datepicker.css', 'datepicker.js', 'xadmin.widget.datetime.js') - if bool(filter(lambda s: isinstance(s, RelatedFieldSearchFilter), self.filter_specs)): + arr = filter(lambda s: isinstance(s, RelatedFieldSearchFilter), self.filter_specs) + if six.PY3: + arr = list(arr) + if bool(arr): media = media + self.vendor( 'select.js', 'select.css', 'xadmin.widget.select.js') return media + self.vendor('xadmin.plugin.filters.js') @@ -199,16 +224,22 @@ def get_media(self, media): # Block Views def block_nav_menu(self, context, nodes): if self.has_filters: - nodes.append(loader.render_to_string('xadmin/blocks/model_list.nav_menu.filters.html', context_instance=context)) + nodes.append(loader.render_to_string('xadmin/blocks/model_list.nav_menu.filters.html', + context=get_context_dict(context))) def block_nav_form(self, context, nodes): if self.search_fields: + context = get_context_dict(context or {}) # no error! + context.update({ + 'search_var': SEARCH_VAR, + 'remove_search_url': self.admin_view.get_query_string(remove=[SEARCH_VAR]), + 'search_form_params': self.admin_view.get_form_params(remove=[SEARCH_VAR]) + }) nodes.append( loader.render_to_string( 'xadmin/blocks/model_list.nav_form.search_form.html', - {'search_var': SEARCH_VAR, - 'remove_search_url': self.admin_view.get_query_string(remove=[SEARCH_VAR]), - 'search_form_params': self.admin_view.get_form_params(remove=[SEARCH_VAR])}, - context_instance=context)) + context=context) + ) + site.register_plugin(FilterPlugin, ListAdminView) diff --git a/xadmin/plugins/importexport.py b/xadmin/plugins/importexport.py new file mode 100644 index 000000000..90fe10c47 --- /dev/null +++ b/xadmin/plugins/importexport.py @@ -0,0 +1,460 @@ +#!/usr/bin/env python +# encoding=utf-8 +""" +Author:zcyuefan +Topic:django-import-export plugin for xadmin to help importing and exporting data using .csv/.xls/.../.json files + +Use: ++++ settings.py +++ +INSTALLED_APPS = ( + ... + 'import_export', +) + ++++ model.py +++ +from django.db import models + +class Foo(models.Model): + name = models.CharField(max_length=64) + description = models.TextField() + ++++ adminx.py +++ +import xadmin +from import_export import resources +from .models import Foo + +class FooResource(resources.ModelResource): + + class Meta: + model = Foo + # fields = ('name', 'description',) + # exclude = () + + +@xadmin.sites.register(Foo) +class FooAdmin(object): + import_export_args = {'import_resource_class': FooResource, 'export_resource_class': FooResource} + +++++++++++++++++ +More info about django-import-export please refer https://github.com/django-import-export/django-import-export +""" +from datetime import datetime +from django.template import loader +from xadmin.plugins.utils import get_context_dict +from xadmin.sites import site +from xadmin.views import BaseAdminPlugin, ListAdminView, ModelAdminView +from xadmin.views.base import csrf_protect_m, filter_hook +from django.db import transaction +from import_export.admin import DEFAULT_FORMATS, SKIP_ADMIN_LOG, TMP_STORAGE_CLASS +from import_export.resources import modelresource_factory +from import_export.forms import ( + ImportForm, + ConfirmImportForm, + ExportForm, +) +from import_export.results import RowResult +from import_export.signals import post_export, post_import +try: + from django.utils.encoding import force_text +except ImportError: + from django.utils.encoding import force_unicode as force_text +from django.utils.translation import ugettext_lazy as _ +from django.template.response import TemplateResponse +from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION +from django.contrib.contenttypes.models import ContentType +from django.contrib import messages +from django.core.urlresolvers import reverse +from django.core.exceptions import PermissionDenied +from django.http import HttpResponseRedirect, HttpResponse + + +class ImportMenuPlugin(BaseAdminPlugin): + import_export_args = {} + + def init_request(self, *args, **kwargs): + return bool(self.import_export_args.get('import_resource_class')) + + def block_top_toolbar(self, context, nodes): + has_change_perm = self.has_model_perm(self.model, 'change') + has_add_perm = self.has_model_perm(self.model, 'add') + if has_change_perm and has_add_perm: + model_info = (self.opts.app_label, self.opts.model_name) + import_url = reverse('xadmin:%s_%s_import' % model_info, current_app=self.admin_site.name) + context = get_context_dict(context or {}) # no error! + context.update({ + 'import_url': import_url, + }) + nodes.append(loader.render_to_string('xadmin/blocks/model_list.top_toolbar.importexport.import.html', + context=context)) + + +class ImportBaseView(ModelAdminView): + """ + """ + resource_class = None + import_export_args = {} + #: template for import view + import_template_name = 'xadmin/import_export/import.html' + #: resource class + #: available import formats + formats = DEFAULT_FORMATS + #: import data encoding + from_encoding = "utf-8" + skip_admin_log = None + # storage class for saving temporary files + tmp_storage_class = None + + def get_skip_admin_log(self): + if self.skip_admin_log is None: + return SKIP_ADMIN_LOG + else: + return self.skip_admin_log + + def get_tmp_storage_class(self): + if self.tmp_storage_class is None: + return TMP_STORAGE_CLASS + else: + return self.tmp_storage_class + + def get_resource_kwargs(self, request, *args, **kwargs): + return {} + + def get_import_resource_kwargs(self, request, *args, **kwargs): + return self.get_resource_kwargs(request, *args, **kwargs) + + def get_resource_class(self, usage): + if usage == 'import': + return self.import_export_args.get('import_resource_class') if self.import_export_args.get( + 'import_resource_class') else modelresource_factory(self.model) + elif usage == 'export': + return self.import_export_args.get('export_resource_class') if self.import_export_args.get( + 'export_resource_class') else modelresource_factory(self.model) + else: + return modelresource_factory(self.model) + + def get_import_resource_class(self): + """ + Returns ResourceClass to use for import. + """ + return self.process_import_resource(self.get_resource_class(usage='import')) + + def process_import_resource(self, resource): + """ + Returns processed ResourceClass to use for import. + Override to custom your own process + """ + return resource + + def get_import_formats(self): + """ + Returns available import formats. + """ + return [f for f in self.formats if f().can_import()] + + +class ImportView(ImportBaseView): + def get_media(self): + media = super(ImportView, self).get_media() + media = media + self.vendor('xadmin.plugin.importexport.css') + return media + + @filter_hook + def get(self, request, *args, **kwargs): + if not (self.has_change_permission() and self.has_add_permission()): + raise PermissionDenied + + resource = self.get_import_resource_class()(**self.get_import_resource_kwargs(request, *args, **kwargs)) + + context = super(ImportView, self).get_context() + + import_formats = self.get_import_formats() + form = ImportForm(import_formats, + request.POST or None, + request.FILES or None) + + context['title'] = _("Import") + ' ' + self.opts.verbose_name + context['form'] = form + context['opts'] = self.model._meta + context['fields'] = [f.column_name for f in resource.get_user_visible_fields()] + + request.current_app = self.admin_site.name + return TemplateResponse(request, [self.import_template_name], + context) + + @filter_hook + @csrf_protect_m + @transaction.atomic + def post(self, request, *args, **kwargs): + """ + Perform a dry_run of the import to make sure the import will not + result in errors. If there where no error, save the user + uploaded file to a local temp file that will be used by + 'process_import' for the actual import. + """ + if not (self.has_change_permission() and self.has_add_permission()): + raise PermissionDenied + + resource = self.get_import_resource_class()(**self.get_import_resource_kwargs(request, *args, **kwargs)) + + context = super(ImportView, self).get_context() + + import_formats = self.get_import_formats() + form = ImportForm(import_formats, + request.POST or None, + request.FILES or None) + + if request.POST and form.is_valid(): + input_format = import_formats[ + int(form.cleaned_data['input_format']) + ]() + import_file = form.cleaned_data['import_file'] + # first always write the uploaded file to disk as it may be a + # memory file or else based on settings upload handlers + tmp_storage = self.get_tmp_storage_class()() + data = bytes() + for chunk in import_file.chunks(): + data += chunk + + tmp_storage.save(data, input_format.get_read_mode()) + + # then read the file, using the proper format-specific mode + # warning, big files may exceed memory + try: + data = tmp_storage.read(input_format.get_read_mode()) + if not input_format.is_binary() and self.from_encoding: + data = force_text(data, self.from_encoding) + dataset = input_format.create_dataset(data) + except UnicodeDecodeError as e: + return HttpResponse(_(u"

Imported file has a wrong encoding: %s

" % e)) + except Exception as e: + return HttpResponse(_(u"

%s encountered while trying to read file: %s

" % (type(e).__name__, + import_file.name))) + result = resource.import_data(dataset, dry_run=True, + raise_errors=False, + file_name=import_file.name, + user=request.user) + + context['result'] = result + + if not result.has_errors(): + context['confirm_form'] = ConfirmImportForm(initial={ + 'import_file_name': tmp_storage.name, + 'original_file_name': import_file.name, + 'input_format': form.cleaned_data['input_format'], + }) + + context['title'] = _("Import") + ' ' + self.opts.verbose_name + context['form'] = form + context['opts'] = self.model._meta + context['fields'] = [f.column_name for f in resource.get_user_visible_fields()] + + request.current_app = self.admin_site.name + return TemplateResponse(request, [self.import_template_name], + context) + + +class ImportProcessView(ImportBaseView): + @filter_hook + @csrf_protect_m + @transaction.atomic + def post(self, request, *args, **kwargs): + """ + Perform the actual import action (after the user has confirmed he + wishes to import) + """ + resource = self.get_import_resource_class()(**self.get_import_resource_kwargs(request, *args, **kwargs)) + + confirm_form = ConfirmImportForm(request.POST) + if confirm_form.is_valid(): + import_formats = self.get_import_formats() + input_format = import_formats[ + int(confirm_form.cleaned_data['input_format']) + ]() + tmp_storage = self.get_tmp_storage_class()(name=confirm_form.cleaned_data['import_file_name']) + data = tmp_storage.read(input_format.get_read_mode()) + if not input_format.is_binary() and self.from_encoding: + data = force_text(data, self.from_encoding) + dataset = input_format.create_dataset(data) + + result = resource.import_data(dataset, dry_run=False, + raise_errors=True, + file_name=confirm_form.cleaned_data['original_file_name'], + user=request.user) + + if not self.get_skip_admin_log(): + # Add imported objects to LogEntry + logentry_map = { + RowResult.IMPORT_TYPE_NEW: ADDITION, + RowResult.IMPORT_TYPE_UPDATE: CHANGE, + RowResult.IMPORT_TYPE_DELETE: DELETION, + } + content_type_id = ContentType.objects.get_for_model(self.model).pk + for row in result: + if row.import_type != row.IMPORT_TYPE_ERROR and row.import_type != row.IMPORT_TYPE_SKIP: + LogEntry.objects.log_action( + user_id=request.user.pk, + content_type_id=content_type_id, + object_id=row.object_id, + object_repr=row.object_repr, + action_flag=logentry_map[row.import_type], + change_message="%s through import_export" % row.import_type, + ) + success_message = str(_(u'Import finished')) + ' , ' + str(_(u'Add')) + ' : %d' % result.totals[ + RowResult.IMPORT_TYPE_NEW] + ' , ' + str(_(u'Update')) + ' : %d' % result.totals[ + RowResult.IMPORT_TYPE_UPDATE] + + messages.success(request, success_message) + tmp_storage.remove() + + post_import.send(sender=None, model=self.model) + model_info = (self.opts.app_label, self.opts.model_name) + url = reverse('xadmin:%s_%s_changelist' % model_info, + current_app=self.admin_site.name) + return HttpResponseRedirect(url) + + +class ExportMixin(object): + #: resource class + resource_class = None + #: template for change_list view + change_list_template = None + import_export_args = {} + #: template for export view + # export_template_name = 'xadmin/import_export/export.html' + #: available export formats + formats = DEFAULT_FORMATS + #: export data encoding + to_encoding = "utf-8" + list_select_related = None + + def get_resource_kwargs(self, request, *args, **kwargs): + return {} + + def get_export_resource_kwargs(self, request, *args, **kwargs): + return self.get_resource_kwargs(request, *args, **kwargs) + + def get_resource_class(self, usage): + if usage == 'import': + return self.import_export_args.get('import_resource_class') if self.import_export_args.get( + 'import_resource_class') else modelresource_factory(self.model) + elif usage == 'export': + return self.import_export_args.get('export_resource_class') if self.import_export_args.get( + 'export_resource_class') else modelresource_factory(self.model) + else: + return modelresource_factory(self.model) + + def get_export_resource_class(self): + """ + Returns ResourceClass to use for export. + """ + return self.get_resource_class(usage='export') + + def get_export_formats(self): + """ + Returns available export formats. + """ + return [f for f in self.formats if f().can_export()] + + def get_export_filename(self, file_format): + date_str = datetime.now().strftime('%Y-%m-%d-%H%M%S') + filename = "%s-%s.%s" % (self.opts.verbose_name.encode('utf-8'), + date_str, + file_format.get_extension()) + return filename + + def get_export_queryset(self, request, context): + """ + Returns export queryset. + + Default implementation respects applied search and filters. + """ + # scope = self.request.POST.get('_select_across', False) == '1' + scope = request.GET.get('scope') + select_across = request.GET.get('_select_across', False) == '1' + selected = request.GET.get('_selected_actions', '') + if scope == 'all': + queryset = self.admin_view.queryset() + elif scope == 'header_only': + queryset = [] + elif scope == 'selected': + if not select_across: + selected_pk = selected.split(',') + queryset = self.admin_view.queryset().filter(pk__in=selected_pk) + else: + queryset = self.admin_view.queryset() + else: + queryset = [r['object'] for r in context['results']] + return queryset + + def get_export_data(self, file_format, queryset, *args, **kwargs): + """ + Returns file_format representation for given queryset. + """ + request = kwargs.pop("request") + resource_class = self.get_export_resource_class() + data = resource_class(**self.get_export_resource_kwargs(request)).export(queryset, *args, **kwargs) + export_data = file_format.export_data(data) + return export_data + + +class ExportMenuPlugin(ExportMixin, BaseAdminPlugin): + import_export_args = {} + + # Media + def get_media(self, media): + return media + self.vendor('xadmin.plugin.importexport.css', 'xadmin.plugin.importexport.js') + + def init_request(self, *args, **kwargs): + return bool(self.import_export_args.get('export_resource_class')) + + def block_top_toolbar(self, context, nodes): + formats = self.get_export_formats() + form = ExportForm(formats) + + context = get_context_dict(context or {}) # no error! + context.update({ + 'form': form, + 'opts': self.opts, + 'form_params': self.admin_view.get_form_params({'_action_': 'export'}), + }) + nodes.append(loader.render_to_string('xadmin/blocks/model_list.top_toolbar.importexport.export.html', + context=context)) + + +class ExportPlugin(ExportMixin, BaseAdminPlugin): + + def init_request(self, *args, **kwargs): + return self.request.GET.get('_action_') == 'export' + + def get_response(self, response, context, *args, **kwargs): + has_view_perm = self.has_model_perm(self.model, 'view') + if not has_view_perm: + raise PermissionDenied + + export_format = self.request.GET.get('file_format') + + if not export_format: + messages.warning(self.request, _('You must select an export format.')) + else: + formats = self.get_export_formats() + file_format = formats[int(export_format)]() + queryset = self.get_export_queryset(self.request, context) + export_data = self.get_export_data(file_format, queryset, request=self.request) + content_type = file_format.get_content_type() + # Django 1.7 uses the content_type kwarg instead of mimetype + try: + response = HttpResponse(export_data, content_type=content_type) + except TypeError: + response = HttpResponse(export_data, mimetype=content_type) + response['Content-Disposition'] = 'attachment; filename=%s' % ( + self.get_export_filename(file_format), + ) + post_export.send(sender=None, model=self.model) + return response + + +site.register_modelview(r'^import/$', ImportView, name='%s_%s_import') +site.register_modelview(r'^process_import/$', ImportProcessView, name='%s_%s_process_import') +site.register_plugin(ImportMenuPlugin, ListAdminView) +site.register_plugin(ExportMenuPlugin, ListAdminView) +site.register_plugin(ExportPlugin, ListAdminView) diff --git a/xadmin/plugins/inline.py b/xadmin/plugins/inline.py index 56a0a5c18..2fbe5b19d 100644 --- a/xadmin/plugins/inline.py +++ b/xadmin/plugins/inline.py @@ -2,11 +2,17 @@ import inspect from django import forms from django.forms.formsets import all_valid, DELETION_FIELD_NAME -from django.forms.models import inlineformset_factory, BaseInlineFormSet -from django.contrib.contenttypes.generic import BaseGenericInlineFormSet, generic_inlineformset_factory +from django.forms.models import inlineformset_factory, BaseInlineFormSet, modelform_defines_fields +from django.contrib.contenttypes.forms import BaseGenericInlineFormSet, generic_inlineformset_factory from django.template import loader from django.template.loader import render_to_string +from django.contrib.auth import get_permission_codename +from django.utils import six +from django.utils.encoding import smart_text +from crispy_forms.utils import TEMPLATE_PACK + from xadmin.layout import FormHelper, Layout, flatatt, Container, Column, Field, Fieldset +from xadmin.plugins.utils import get_context_dict from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ModelFormAdminView, DetailAdminView, filter_hook @@ -20,23 +26,23 @@ def __init__(self, admin_view, *args, **kwargs): if admin_view.style == 'table': self.template = "xadmin/layout/field_value_td.html" - def render(self, form, form_style, context): + def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs): html = '' detail = form.detail for field in self.fields: if not isinstance(form.fields[field].widget, forms.HiddenInput): result = detail.get_field_result(field) html += loader.render_to_string( - self.template, {'field': form[field], 'result': result}) + self.template, context={'field': form[field], 'result': result}) return html class DeleteField(Field): - def render(self, form, form_style, context): + def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs): if form.instance.pk: self.attrs['type'] = 'hidden' - return super(DeleteField, self).render(form, form_style, context) + return super(DeleteField, self).render(form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs) else: return "" @@ -109,10 +115,11 @@ def get_attrs(self): def replace_field_to_value(layout, av): if layout: + cls_str = str if six.PY3 else basestring for i, lo in enumerate(layout.fields): if isinstance(lo, Field) or issubclass(lo.__class__, Field): layout.fields[i] = ShowField(av, *lo.fields, **lo.attrs) - elif isinstance(lo, basestring): + elif isinstance(lo, cls_str): layout.fields[i] = ShowField(av, lo) elif hasattr(lo, 'get_field_names'): replace_field_to_value(lo, av) @@ -157,6 +164,7 @@ def get_formset(self, **kwargs): "form": self.form, "formset": self.formset, "fk_name": self.fk_name, + 'fields': forms.ALL_FIELDS, "exclude": exclude, "formfield_callback": self.formfield_for_dbfield, "extra": self.extra, @@ -164,6 +172,7 @@ def get_formset(self, **kwargs): "can_delete": can_delete, } defaults.update(kwargs) + return inlineformset_factory(self.parent_model, self.model, **defaults) @filter_hook @@ -183,6 +192,7 @@ def instance_form(self, **kwargs): helper = FormHelper() helper.form_tag = False + helper.include_media = False # override form method to prevent render csrf_token in inline forms, see template 'bootstrap/whole_uni_form.html' helper.form_method = 'get' @@ -221,8 +231,8 @@ def instance_form(self, **kwargs): value = None label = None if readonly_field in inst._meta.get_all_field_names(): - label = inst._meta.get_field_by_name(readonly_field)[0].verbose_name - value = unicode(getattr(inst, readonly_field)) + label = inst._meta.get_field(readonly_field).verbose_name + value = smart_text(getattr(inst, readonly_field)) elif inspect.ismethod(getattr(inst, readonly_field, None)): value = getattr(inst, readonly_field)() label = getattr(getattr(inst, readonly_field), 'short_description', readonly_field) @@ -250,8 +260,9 @@ def queryset(self): def has_add_permission(self): if self.opts.auto_created: return self.has_change_permission() - return self.user.has_perm( - self.opts.app_label + '.' + self.opts.get_add_permission()) + + codename = get_permission_codename('add', self.opts) + return self.user.has_perm("%s.%s" % (self.opts.app_label, codename)) def has_change_permission(self): opts = self.opts @@ -260,14 +271,16 @@ def has_change_permission(self): if field.rel and field.rel.to != self.parent_model: opts = field.rel.to._meta break - return self.user.has_perm( - opts.app_label + '.' + opts.get_change_permission()) + + codename = get_permission_codename('change', opts) + return self.user.has_perm("%s.%s" % (opts.app_label, codename)) def has_delete_permission(self): if self.opts.auto_created: return self.has_change_permission() - return self.user.has_perm( - self.opts.app_label + '.' + self.opts.get_delete_permission()) + + codename = get_permission_codename('delete', self.opts) + return self.user.has_perm("%s.%s" % (self.opts.app_label, codename)) class GenericInlineModelAdmin(InlineModelAdmin): @@ -298,9 +311,11 @@ def get_formset(self, **kwargs): "can_delete": can_delete, "can_order": False, "max_num": self.max_num, - "exclude": exclude + "exclude": exclude, + 'fields': forms.ALL_FIELDS } defaults.update(kwargs) + return generic_inlineformset_factory(self.model, **defaults) @@ -321,10 +336,15 @@ def __init__(self, formset, allow_blank=False, **kwargs): self.flat_attrs = flatatt(kwargs) self.extra_attrs = formset.style.get_attrs() - def render(self, form, form_style, context): - return render_to_string( - self.template, dict({'formset': self, 'prefix': self.formset.prefix, 'inline_style': self.inline_style}, **self.extra_attrs), - context_instance=context) + def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs): + context = get_context_dict(context) + context.update(dict( + formset=self, + prefix=self.formset.prefix, + inline_style=self.inline_style, + **self.extra_attrs + )) + return render_to_string(self.template, context) class Inline(Fieldset): @@ -332,8 +352,9 @@ class Inline(Fieldset): def __init__(self, rel_model): self.model = rel_model self.fields = [] + super(Inline,self).__init__(legend="") - def render(self, form, form_style, context): + def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs): return "" @@ -377,6 +398,7 @@ def inline_instances(self): inline.max_num = 0 inline_instances.append(inline) self._inline_instances = inline_instances + return self._inline_instances def instance_forms(self, ret): @@ -441,7 +463,7 @@ def _get_detail_formset_instance(self, inline): replace_field_to_value(formset.helper.layout, inline) model = inline.model opts = model._meta - fake_admin_class = type(str('%s%sFakeAdmin' % (opts.app_label, opts.module_name)), (object, ), {'model': model}) + fake_admin_class = type(str('%s%sFakeAdmin' % (opts.app_label, opts.model_name)), (object, ), {'model': model}) for form in formset.forms: instance = form.instance if instance.pk: diff --git a/xadmin/plugins/language.py b/xadmin/plugins/language.py index fa65c7b08..3814771e4 100644 --- a/xadmin/plugins/language.py +++ b/xadmin/plugins/language.py @@ -1,19 +1,26 @@ from django.conf import settings -from django.template import loader, RequestContext - +from django.template import loader +from django.views.i18n import set_language +from xadmin.plugins.utils import get_context_dict from xadmin.sites import site -from xadmin.views import BaseAdminPlugin, CommAdminView +from xadmin.views import BaseAdminPlugin, CommAdminView, BaseAdminView class SetLangNavPlugin(BaseAdminPlugin): def block_top_navmenu(self, context, nodes): - nodes.append( - loader.render_to_string('xadmin/blocks/comm.top.setlang.html', { - 'redirect_to': self.request.get_full_path(), - }, context_instance=RequestContext(self.request))) + context = get_context_dict(context) + context['redirect_to'] = self.request.get_full_path() + nodes.append(loader.render_to_string('xadmin/blocks/comm.top.setlang.html', context=context)) + +class SetLangView(BaseAdminView): + + def post(self, request, *args, **kwargs): + if 'nav_menu' in request.session: + del request.session['nav_menu'] + return set_language(request) if settings.LANGUAGES and 'django.middleware.locale.LocaleMiddleware' in settings.MIDDLEWARE_CLASSES: site.register_plugin(SetLangNavPlugin, CommAdminView) - site.register_view(r'^i18n/', lambda site: 'django.conf.urls.i18n', 'i18n') + site.register_view(r'^i18n/setlang/$', SetLangView, 'set_language') diff --git a/xadmin/plugins/layout.py b/xadmin/plugins/layout.py index 2e45d1ab3..dd4f56680 100644 --- a/xadmin/plugins/layout.py +++ b/xadmin/plugins/layout.py @@ -2,6 +2,7 @@ from django.template import loader from django.utils.translation import ugettext_lazy as _ +from xadmin.plugins.utils import get_context_dict from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ListAdminView from xadmin.util import label_for_field @@ -73,7 +74,8 @@ def block_top_toolbar(self, context, nodes): 'layouts': self._active_layouts, 'current_icon': self._current_icon, }) - nodes.append(loader.render_to_string('xadmin/blocks/model_list.top_toolbar.layouts.html', context_instance=context)) + nodes.append(loader.render_to_string('xadmin/blocks/model_list.top_toolbar.layouts.html', + context=get_context_dict(context))) site.register_plugin(GridLayoutPlugin, ListAdminView) diff --git a/xadmin/plugins/multiselect.py b/xadmin/plugins/multiselect.py index 954f6b849..38e0c917d 100644 --- a/xadmin/plugins/multiselect.py +++ b/xadmin/plugins/multiselect.py @@ -1,15 +1,15 @@ -#coding:utf-8 +# coding:utf-8 from itertools import chain import xadmin from django import forms from django.db.models import ManyToManyField -from django.forms.util import flatatt +from django.forms.utils import flatatt from django.template import loader -from django.utils.encoding import force_unicode +from django.utils.encoding import force_text from django.utils.html import escape, conditional_escape from django.utils.safestring import mark_safe -from xadmin.util import vendor +from xadmin.util import vendor, DJANGO_11 from xadmin.views import BaseAdminPlugin, ModelFormAdminView @@ -25,9 +25,9 @@ def __init__(self, verbose_name, is_stacked, attrs=None, choices=()): super(SelectMultipleTransfer, self).__init__(attrs, choices) def render_opt(self, selected_choices, option_value, option_label): - option_value = force_unicode(option_value) + option_value = force_text(option_value) return u'' % ( - escape(option_value), conditional_escape(force_unicode(option_label))), bool(option_value in selected_choices) + escape(option_value), conditional_escape(force_text(option_label))), bool(option_value in selected_choices) def render(self, name, value, attrs=None, choices=()): if attrs is None: @@ -37,16 +37,19 @@ def render(self, name, value, attrs=None, choices=()): attrs['class'] += 'stacked' if value is None: value = [] - final_attrs = self.build_attrs(attrs, name=name) + if DJANGO_11: + final_attrs = self.build_attrs(attrs, extra_attrs={'name': name}) + else: + final_attrs = self.build_attrs(attrs, name=name) - selected_choices = set(force_unicode(v) for v in value) + selected_choices = set(force_text(v) for v in value) available_output = [] chosen_output = [] for option_value, option_label in chain(self.choices, choices): if isinstance(option_label, (list, tuple)): available_output.append(u'' % - escape(force_unicode(option_value))) + escape(force_text(option_value))) for option in option_label: output, selected = self.render_opt( selected_choices, *option) @@ -94,7 +97,7 @@ def init_request(self, *args, **kwargs): ( 'm2m_transfer' in self.admin_view.style_fields.values() or 'm2m_dropdown' in self.admin_view.style_fields.values() - ) + ) def get_field_style(self, attrs, db_field, style, **kwargs): if style == 'm2m_transfer' and isinstance(db_field, ManyToManyField): diff --git a/xadmin/plugins/passwords.py b/xadmin/plugins/passwords.py index 9395d1e60..ac7852714 100644 --- a/xadmin/plugins/passwords.py +++ b/xadmin/plugins/passwords.py @@ -27,8 +27,7 @@ def get(self, request, *args, **kwargs): context = super(ResetPasswordSendView, self).get_context() context['form'] = kwargs.get('form', self.password_reset_form()) - return TemplateResponse(request, self.password_reset_template, context, - current_app=self.admin_site.name) + return TemplateResponse(request, self.password_reset_template, context) @csrf_protect_m def post(self, request, *args, **kwargs): @@ -50,8 +49,7 @@ def post(self, request, *args, **kwargs): form.save(**opts) context = super(ResetPasswordSendView, self).get_context() - return TemplateResponse(request, self.password_reset_done_template, context, - current_app=self.admin_site.name) + return TemplateResponse(request, self.password_reset_done_template, context) else: return self.get(request, form=form) @@ -107,8 +105,7 @@ def get(self, request, *args, **kwargs): context = super(ResetPasswordCompleteView, self).get_context() context['login_url'] = self.get_admin_url('https://github.com/index') - return TemplateResponse(request, self.password_reset_complete_template, context, - current_app=self.admin_site.name) + return TemplateResponse(request, self.password_reset_complete_template, context) site.register_view(r'^xadmin/password_reset/complete/$', ResetPasswordCompleteView, name='xadmin_password_reset_complete') diff --git a/xadmin/plugins/portal.py b/xadmin/plugins/portal.py index de433a5cd..40199a249 100644 --- a/xadmin/plugins/portal.py +++ b/xadmin/plugins/portal.py @@ -23,7 +23,7 @@ def get_layout_objects(layout, clz, objects): class ModelFormPlugin(BasePortalPlugin): def _portal_key(self): - return '%s_%s_editform_portal' % (self.opts.app_label, self.opts.module_name) + return '%s_%s_editform_portal' % (self.opts.app_label, self.opts.model_name) def get_form_helper(self, helper): cs = [] @@ -64,7 +64,7 @@ def block_form_top(self, context, node): class ModelDetailPlugin(ModelFormPlugin): def _portal_key(self): - return '%s_%s_detail_portal' % (self.opts.app_label, self.opts.module_name) + return '%s_%s_detail_portal' % (self.opts.app_label, self.opts.model_name) def block_after_fieldsets(self, context, node): # put portal key and submit url to page diff --git a/xadmin/plugins/quickfilter.py b/xadmin/plugins/quickfilter.py index 928d4ebf5..6222c34b4 100644 --- a/xadmin/plugins/quickfilter.py +++ b/xadmin/plugins/quickfilter.py @@ -3,9 +3,12 @@ @author: LAB_ADM ''' +from future.utils import iteritems +from django.utils import six from django.utils.translation import ugettext_lazy as _ from xadmin.filters import manager,MultiSelectFieldListFilter from xadmin.plugins.filters import * +from xadmin.util import is_related_field @manager.register class QuickFilterMultiSelectFieldListFilter(MultiSelectFieldListFilter): @@ -56,7 +59,7 @@ def lookup_allowed(self, lookup, value): rel_name = None for part in parts[:-1]: try: - field, _, _, _ = model._meta.get_field_by_name(part) + field = model._meta.get_field(part) except FieldDoesNotExist: # Lookups on non-existants fields are ok, since they're ignored # later. @@ -64,7 +67,7 @@ def lookup_allowed(self, lookup, value): if hasattr(field, 'rel'): model = field.rel.to rel_name = field.rel.get_related_field().name - elif isinstance(field, RelatedObject): + elif is_related_field(field): model = field.model rel_name = model._meta.pk.name else: @@ -79,7 +82,7 @@ def lookup_allowed(self, lookup, value): def get_list_queryset(self, queryset): lookup_params = dict([(smart_str(k)[len(FILTER_PREFIX):], v) for k, v in self.admin_view.params.items() if smart_str(k).startswith(FILTER_PREFIX) and v != '']) - for p_key, p_val in lookup_params.iteritems(): + for p_key, p_val in iteritems(lookup_params): if p_val == "False": lookup_params[p_key] = False use_distinct = False @@ -135,7 +138,7 @@ def get_list_queryset(self, queryset): if spec and spec.has_output(): try: new_qs = spec.do_filte(queryset) - except ValidationError, e: + except ValidationError as e: new_qs = None self.admin_view.message_user(_("Filtering error: %s") % e.messages[0], 'error') if new_qs is not None: @@ -145,7 +148,10 @@ def get_list_queryset(self, queryset): self.has_filters = bool(self.filter_specs) self.admin_view.quickfilter['filter_specs'] = self.filter_specs - self.admin_view.quickfilter['used_filter_num'] = len(filter(lambda f: f.is_used, self.filter_specs)) + obj = filter(lambda f: f.is_used, self.filter_specs) + if six.PY3: + obj = list(obj) + self.admin_view.quickfilter['used_filter_num'] = len(obj) if use_distinct: return queryset.distinct() @@ -153,6 +159,7 @@ def get_list_queryset(self, queryset): return queryset def block_left_navbar(self, context, nodes): - nodes.append(loader.render_to_string('xadmin/blocks/modal_list.left_navbar.quickfilter.html',context)) + nodes.append(loader.render_to_string('xadmin/blocks/modal_list.left_navbar.quickfilter.html', + get_context_dict(context))) -site.register_plugin(QuickFilterPlugin, ListAdminView) \ No newline at end of file +site.register_plugin(QuickFilterPlugin, ListAdminView) diff --git a/xadmin/plugins/quickform.py b/xadmin/plugins/quickform.py index 823965add..d93e2c647 100644 --- a/xadmin/plugins/quickform.py +++ b/xadmin/plugins/quickform.py @@ -44,8 +44,8 @@ class RelatedFieldWidgetWrapper(forms.Widget): This class is a wrapper to a given widget to add the add icon for the admin interface. """ + def __init__(self, widget, rel, add_url, rel_add_url): - self.is_hidden = widget.is_hidden self.needs_multipart_form = widget.needs_multipart_form self.attrs = widget.attrs self.choices = widget.choices @@ -56,6 +56,9 @@ def __init__(self, widget, rel, add_url, rel_add_url): self.add_url = add_url self.rel_add_url = rel_add_url + if hasattr(self, 'input_type'): + self.input_type = widget.input_type + def __deepcopy__(self, memo): obj = copy.copy(self) obj.widget = copy.deepcopy(self.widget, memo) @@ -68,7 +71,7 @@ def media(self): media = self.widget.media + vendor('xadmin.plugin.quick-form.js') return media - def render(self, name, value, *args, **kwargs): + def render(self, name, value, renderer=None, *args, **kwargs): self.widget.choices = self.choices output = [] if self.add_url: @@ -77,7 +80,7 @@ def render(self, name, value, *args, **kwargs): self.add_url, (_('Create New %s') % self.rel.to._meta.verbose_name), name, "%s?_field=%s&%s=" % (self.rel_add_url, name, name))) output.extend(['
' % name, - self.widget.render(name, value, *args, **kwargs), '
']) + self.widget.render(name, value, *args, **kwargs), '']) return mark_safe(u''.join(output)) def build_attrs(self, extra_attrs=None, **kwargs): diff --git a/xadmin/plugins/refresh.py b/xadmin/plugins/refresh.py index 8c1a0fa91..a1341a23b 100644 --- a/xadmin/plugins/refresh.py +++ b/xadmin/plugins/refresh.py @@ -1,6 +1,7 @@ # coding=utf-8 from django.template import loader +from xadmin.plugins.utils import get_context_dict from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ListAdminView @@ -31,7 +32,8 @@ def block_top_toolbar(self, context, nodes): 'selected': str(r) == current_refresh, } for r in self.refresh_times], }) - nodes.append(loader.render_to_string('xadmin/blocks/model_list.top_toolbar.refresh.html', context_instance=context)) + nodes.append(loader.render_to_string('xadmin/blocks/model_list.top_toolbar.refresh.html', + get_context_dict(context))) site.register_plugin(RefreshPlugin, ListAdminView) diff --git a/xadmin/plugins/relate.py b/xadmin/plugins/relate.py index 37b8aee97..4d33977a3 100644 --- a/xadmin/plugins/relate.py +++ b/xadmin/plugins/relate.py @@ -1,15 +1,20 @@ # coding=UTF-8 +from itertools import chain + from django.core.urlresolvers import reverse -from django.utils.encoding import force_unicode +from django.db.models.options import PROXY_PARENTS +from django.utils import six +from django.utils.encoding import force_text from django.utils.encoding import smart_str from django.utils.safestring import mark_safe from django.db.models.sql.query import LOOKUP_SEP -from django.db.models.related import RelatedObject from django.utils.translation import ugettext as _ from django.db import models + from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ListAdminView, CreateAdminView, UpdateAdminView, DeleteAdminView +from xadmin.util import is_related_field2 RELATE_PREFIX = '_rel_' @@ -19,36 +24,63 @@ class RelateMenuPlugin(BaseAdminPlugin): related_list = [] use_related_menu = True + def _get_all_related_objects(self, local_only=False, include_hidden=False, + include_proxy_eq=False): + """ + Returns a list of related fields (also many to many) + :param local_only: + :param include_hidden: + :return: list + """ + include_parents = True if local_only is False else PROXY_PARENTS + fields = self.opts._get_fields( + forward=False, reverse=True, + include_parents=include_parents, + include_hidden=include_hidden + ) + if include_proxy_eq: + children = chain.from_iterable(c._relation_tree + for c in self.opts.concrete_model._meta.proxied_children + if c is not self.opts) + relations = (f.remote_field for f in children + if include_hidden or not f.remote_field.field.remote_field.is_hidden()) + fields = chain(fields, relations) + return list(fields) + + def get_related_list(self): if hasattr(self, '_related_acts'): return self._related_acts _related_acts = [] - for r in self.opts.get_all_related_objects() + self.opts.get_all_related_many_to_many_objects(): - if self.related_list and (r.get_accessor_name() not in self.related_list): + for rel in self._get_all_related_objects(): + if self.related_list and (rel.get_accessor_name() not in self.related_list): continue - if r.model not in self.admin_site._registry.keys(): + if rel.related_model not in self.admin_site._registry.keys(): continue - has_view_perm = self.has_model_perm(r.model, 'view') - has_add_perm = self.has_model_perm(r.model, 'add') + has_view_perm = self.has_model_perm(rel.related_model, 'view') + has_add_perm = self.has_model_perm(rel.related_model, 'add') if not (has_view_perm or has_add_perm): continue - _related_acts.append((r, has_view_perm, has_add_perm)) + _related_acts.append((rel, has_view_perm, has_add_perm)) self._related_acts = _related_acts return self._related_acts def related_link(self, instance): links = [] - for r, view_perm, add_perm in self.get_related_list(): - label = r.opts.app_label - model_name = r.opts.module_name - f = r.field - rel_name = f.rel.get_related_field().name + for rel, view_perm, add_perm in self.get_related_list(): + opts = rel.related_model._meta - verbose_name = force_unicode(r.opts.verbose_name) - lookup_name = '%s__%s__exact' % (f.name, rel_name) + label = opts.app_label + model_name = opts.model_name + + field = rel.field + rel_name = rel.get_related_field().name + + verbose_name = force_text(opts.verbose_name) + lookup_name = '%s__%s__exact' % (field.name, rel_name) link = ''.join(('
  • ', @@ -93,21 +125,16 @@ def __init__(self, admin_view, lookup, value): self.value = value parts = lookup.split(LOOKUP_SEP) - field = self.opts.get_field_by_name(parts[0])[0] + field = self.opts.get_field(parts[0]) - if not hasattr(field, 'rel') and not isinstance(field, RelatedObject): + if not is_related_field2(field): raise Exception(u'Relate Lookup field must a related field') - if hasattr(field, 'rel'): - self.to_model = field.rel.to - self.rel_name = field.rel.get_related_field().name - self.is_m2m = isinstance(field.rel, models.ManyToManyRel) - else: - self.to_model = field.model - self.rel_name = self.to_model._meta.pk.name - self.is_m2m = False + self.to_model = field.related_model + self.rel_name = '__'.join(parts[1:]) + self.is_m2m = bool(field.many_to_many) - to_qs = self.to_model._default_manager.get_query_set() + to_qs = self.to_model._default_manager.get_queryset() self.to_objs = to_qs.filter(**{self.rel_name: value}).all() self.field = field @@ -119,16 +146,16 @@ def get_brand_name(self): if len(self.to_objs) == 1: to_model_name = str(self.to_objs[0]) else: - to_model_name = force_unicode(self.to_model._meta.verbose_name) + to_model_name = force_text(self.to_model._meta.verbose_name) - return mark_safe(u"%s %s" % (to_model_name, force_unicode(self.opts.verbose_name_plural))) + return mark_safe(u"%s %s" % (to_model_name, force_text(self.opts.verbose_name_plural))) class BaseRelateDisplayPlugin(BaseAdminPlugin): def init_request(self, *args, **kwargs): self.relate_obj = None - for k, v in self.request.REQUEST.items(): + for k, v in self.request.GET.items(): if smart_str(k).startswith(RELATE_PREFIX): self.relate_obj = RelateObject( self.admin_view, smart_str(k)[len(RELATE_PREFIX):], v) @@ -158,6 +185,8 @@ def url_for_result(self, url, result): def get_context(self, context): context['brand_name'] = self.relate_obj.get_brand_name() context['rel_objs'] = self.relate_obj.to_objs + if len(self.relate_obj.to_objs) == 1: + context['rel_obj'] = self.relate_obj.to_objs[0] if 'add_url' in context: context['add_url'] = self._get_url(https://github.com/context['add_url']) return context @@ -180,7 +209,8 @@ def get_form_datas(self, datas): return datas def post_response(self, response): - if isinstance(response, basestring) and response != self.get_admin_url('https://github.com/index'): + cls_str = str if six.PY3 else basestring + if isinstance(response, cls_str) and response != self.get_admin_url('https://github.com/index'): return self._get_url(https://github.com/response) return response @@ -196,7 +226,8 @@ def block_after_fieldsets(self, context, nodes): class DeleteRelateDisplayPlugin(BaseRelateDisplayPlugin): def post_response(self, response): - if isinstance(response, basestring) and response != self.get_admin_url('https://github.com/index'): + cls_str = str if six.PY3 else basestring + if isinstance(response, cls_str) and response != self.get_admin_url('https://github.com/index'): return self._get_url(https://github.com/response) return response diff --git a/xadmin/plugins/relfield.py b/xadmin/plugins/relfield.py index 14248b44d..506222e4c 100644 --- a/xadmin/plugins/relfield.py +++ b/xadmin/plugins/relfield.py @@ -1,14 +1,16 @@ from django.db import models +from django.forms.utils import flatatt from django.utils.html import escape, format_html +from django.utils.safestring import mark_safe from django.utils.text import Truncator from django.utils.translation import ugettext as _ from django import forms from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ModelFormAdminView -from xadmin.util import vendor +from xadmin.util import vendor, DJANGO_11 -class ForeignKeySearchWidget(forms.TextInput): +class ForeignKeySearchWidget(forms.Widget): def __init__(self, rel, admin_view, attrs=None, using=None): self.rel = rel @@ -16,26 +18,39 @@ def __init__(self, rel, admin_view, attrs=None, using=None): self.db = using super(ForeignKeySearchWidget, self).__init__(attrs) - def render(self, name, value, attrs=None): + def build_attrs(self, attrs={}, extra_attrs=None, **kwargs): to_opts = self.rel.to._meta - if attrs is None: - attrs = {} if "class" not in attrs: attrs['class'] = 'select-search' else: attrs['class'] = attrs['class'] + ' select-search' attrs['data-search-url'] = self.admin_view.get_admin_url( - '%s_%s_changelist' % (to_opts.app_label, to_opts.module_name)) + '%s_%s_changelist' % (to_opts.app_label, to_opts.model_name)) attrs['data-placeholder'] = _('Search %s') % to_opts.verbose_name attrs['data-choices'] = '?' if self.rel.limit_choices_to: for i in list(self.rel.limit_choices_to): attrs['data-choices'] += "&_p_%s=%s" % (i, self.rel.limit_choices_to[i]) attrs['data-choices'] = format_html(attrs['data-choices']) - if value: - attrs['data-label'] = self.label_for_value(value) + if DJANGO_11: + attrs.update(kwargs) + return super(ForeignKeySearchWidget, self).build_attrs(attrs, extra_attrs=extra_attrs) + else: + if extra_attrs: + attrs.update(extra_attrs) + return super(ForeignKeySearchWidget, self).build_attrs(attrs, **kwargs) - return super(ForeignKeySearchWidget, self).render(name, value, attrs) + def render(self, name, value, attrs=None): + if DJANGO_11: + final_attrs = self.build_attrs(attrs, extra_attrs={'name': name}) + else: + final_attrs = self.build_attrs(attrs, name=name) + + output = [format_html('', flatatt(final_attrs))] + if value: + output.append(format_html('', value, self.label_for_value(value))) + output.append('') + return mark_safe('\n'.join(output)) def label_for_value(self, value): key = self.rel.get_related_field().name @@ -51,15 +66,28 @@ def media(self): return vendor('select.js', 'select.css', 'xadmin.widget.select.js') +class ForeignKeySelectWidget(ForeignKeySearchWidget): + + def build_attrs(self, attrs={}, **kwargs): + attrs = super(ForeignKeySelectWidget, self).build_attrs(attrs, **kwargs) + if "class" not in attrs: + attrs['class'] = 'select-preload' + else: + attrs['class'] = attrs['class'] + ' select-preload' + attrs['data-placeholder'] = _('Select %s') % self.rel.to._meta.verbose_name + return attrs + + class RelateFieldPlugin(BaseAdminPlugin): def get_field_style(self, attrs, db_field, style, **kwargs): # search able fk field - if style == 'fk-ajax' and isinstance(db_field, models.ForeignKey): - if (db_field.rel.to in self.admin_view.admin_site._registry) and \ - self.has_model_perm(db_field.rel.to, 'view'): + if style in ('fk-ajax', 'fk-select') and isinstance(db_field, models.ForeignKey): + if (db_field.remote_field.to in self.admin_view.admin_site._registry) and \ + self.has_model_perm(db_field.remote_field.to, 'view'): db = kwargs.get('using') - return dict(attrs or {}, widget=ForeignKeySearchWidget(db_field.rel, self.admin_view, using=db)) + return dict(attrs or {}, + widget=(style == 'fk-ajax' and ForeignKeySearchWidget or ForeignKeySelectWidget)(db_field.remote_field, self.admin_view, using=db)) return attrs site.register_plugin(RelateFieldPlugin, ModelFormAdminView) diff --git a/xadmin/plugins/sortable.py b/xadmin/plugins/sortable.py deleted file mode 100644 index 8806eeaf8..000000000 --- a/xadmin/plugins/sortable.py +++ /dev/null @@ -1,36 +0,0 @@ -#coding:utf-8 -from xadmin.sites import site -from xadmin.views import BaseAdminPlugin, ListAdminView - -SORTBY_VAR = '_sort_by' - - -class SortablePlugin(BaseAdminPlugin): - - sortable_fields = ['sort'] - - # Media - def get_media(self, media): - if self.sortable_fields and self.request.GET.get(SORTBY_VAR): - media = media + self.vendor('xadmin.plugin.sortable.js') - return media - - # Block Views - def block_top_toolbar(self, context, nodes): - if self.sortable_fields: - pass - # current_refresh = self.request.GET.get(REFRESH_VAR) - # context.update({ - # 'has_refresh': bool(current_refresh), - # 'clean_refresh_url': self.admin_view.get_query_string(remove=(REFRESH_VAR,)), - # 'current_refresh': current_refresh, - # 'refresh_times': [{ - # 'time': r, - # 'url': self.admin_view.get_query_string({REFRESH_VAR: r}), - # 'selected': str(r) == current_refresh, - # } for r in self.refresh_times], - # }) - # nodes.append(loader.render_to_string('xadmin/blocks/refresh.html', context_instance=context)) - - -site.register_plugin(SortablePlugin, ListAdminView) diff --git a/xadmin/plugins/sortablelist.py b/xadmin/plugins/sortablelist.py new file mode 100644 index 000000000..8b9942f6e --- /dev/null +++ b/xadmin/plugins/sortablelist.py @@ -0,0 +1,81 @@ +# coding: utf-8 +""" +Make items sortable by drag-drop in list view. Diffierent from +builtin plugin sortable, it touches model field indeed intead +of only for display. +""" + +from __future__ import unicode_literals + +from django.template.loader import render_to_string +from django.core.urlresolvers import reverse +from django.db import transaction + +from xadmin.views import ( + BaseAdminPlugin, ModelAdminView, ListAdminView +) +from xadmin.sites import site +from xadmin.views.base import csrf_protect_m + + +class SortableListPlugin(BaseAdminPlugin): + + list_order_field = None + + def init_request(self, *args, **kwargs): + return bool(self.list_order_field) + + @property + def is_list_sortable(self): + return True + + def result_row(self, __, obj): + row = __() + row.update({ + "tagattrs": "order-key=order_{}".format(obj.pk) + }) + return row + + def result_item(self, item, obj, field_name, row): + if self.is_list_sortable and field_name == self.list_order_field: + item.btns.append('') + return item + + def get_context(self, context): + context['save_order_url'] = self.get_model_url(https://github.com/self.admin_view.model,%20'save_order') + return context + + def block_top_toolbar(self, context, nodes): + save_node = render_to_string( + 'xadmin/blocks/model_list.top_toolbar.saveorder.html', context_instance=context + ) + nodes.append(save_node) + + def get_media(self, media): + if self.is_list_sortable: + media = media + self.vendor('xadmin.plugin.sortablelist.js') + return media + + +class SaveOrderView(ModelAdminView): + + @csrf_protect_m + @transaction.atomic + def post(self, request): + order_objs = request.POST.getlist("order[]") + for order_value, pk in enumerate(order_objs, start=1): + self.save_order(pk, order_value) + return self.render_response({}) + + def save_order(self, pk, order_value): + obj = self.model.objects.get(pk=pk) + order_field = self.list_order_field + is_order_changed = lambda x: getattr(x, order_field) != order_value + + if is_order_changed(obj): + setattr(obj, order_field, order_value) + obj.save() + + +site.register_plugin(SortableListPlugin, ListAdminView) +site.register_modelview(r'^save-order/$', SaveOrderView, name='%s_%s_save_order') diff --git a/xadmin/plugins/themes.py b/xadmin/plugins/themes.py index cc202e252..d83dd9cc3 100644 --- a/xadmin/plugins/themes.py +++ b/xadmin/plugins/themes.py @@ -1,12 +1,19 @@ #coding:utf-8 -import urllib +from __future__ import print_function +import requests from django.template import loader from django.core.cache import cache +from django.utils import six from django.utils.translation import ugettext as _ from xadmin.sites import site from xadmin.models import UserSettings from xadmin.views import BaseAdminPlugin, BaseAdminView from xadmin.util import static, json +import six +if six.PY2: + import urllib +else: + import urllib.parse THEME_CACHE_KEY = 'xadmin_themes' @@ -30,7 +37,11 @@ def _get_theme(self): except Exception: pass if '_theme' in self.request.COOKIES: - return urllib.unquote(self.request.COOKIES['_theme']) + if six.PY2: + func = urllib.unquote + else: + func = urllib.parse.unquote + return func(self.request.COOKIES['_theme']) return self.default_theme def get_context(self, context): @@ -44,10 +55,10 @@ def get_media(self, media): # Block Views def block_top_navmenu(self, context, nodes): - themes = [{'name': _(u"Default"), 'description': _( - u"Default bootstrap theme"), 'css': self.default_theme}, - {'name': _(u"Bootstrap2"), 'description': _(u"Bootstrap 2.x theme"), - 'css': self.bootstrap2_theme}] + themes = [ + {'name': _(u"Default"), 'description': _(u"Default bootstrap theme"), 'css': self.default_theme}, + {'name': _(u"Bootstrap2"), 'description': _(u"Bootstrap 2.x theme"), 'css': self.bootstrap2_theme}, + ] select_css = context.get('site_theme', self.default_theme) if self.user_themes: @@ -60,14 +71,15 @@ def block_top_navmenu(self, context, nodes): else: ex_themes = [] try: - watch_themes = json.loads(urllib.urlopen( - 'http://api.bootswatch.com/3/').read())['themes'] - ex_themes.extend([ - {'name': t['name'], 'description': t['description'], - 'css': t['cssMin'], 'thumbnail': t['thumbnail']} - for t in watch_themes]) - except Exception: - pass + headers = {"Accept": "application/json", "User-Agent": self.request.META['HTTP_USER_AGENT']} + content = requests.get("https://bootswatch.com/api/3.json", headers=headers) + if six.PY3: + content = content.text.decode() + watch_themes = json.loads(content.text)['themes'] + ex_themes.extend([{'name': t['name'], 'description': t['description'], 'css': t['cssMin'], + 'thumbnail': t['thumbnail']} for t in watch_themes]) + except Exception as e: + print(e) cache.set(THEME_CACHE_KEY, json.dumps(ex_themes), 24 * 3600) themes.extend(ex_themes) diff --git a/xadmin/plugins/topnav.py b/xadmin/plugins/topnav.py index d7a81ddad..c92fce549 100644 --- a/xadmin/plugins/topnav.py +++ b/xadmin/plugins/topnav.py @@ -31,7 +31,7 @@ def block_top_navbar(self, context, nodes): app_label = model._meta.app_label if self.has_model_perm(model, "view"): - info = (app_label, model._meta.module_name) + info = (app_label, model._meta.model_name) if getattr(self.admin_site._registry[model], 'search_fields', None): try: search_models.append({ @@ -41,8 +41,7 @@ def block_top_navbar(self, context, nodes): }) except NoReverseMatch: pass - - nodes.append(loader.render_to_string('xadmin/blocks/comm.top.topnav.html', {'search_models': search_models, 'search_name': SEARCH_VAR})) + return nodes.append(loader.render_to_string('xadmin/blocks/comm.top.topnav.html', {'search_models': search_models, 'search_name': SEARCH_VAR})) def block_top_navmenu(self, context, nodes): add_models = [] @@ -57,7 +56,7 @@ def block_top_navmenu(self, context, nodes): app_label = model._meta.app_label if self.has_model_perm(model, "add"): - info = (app_label, model._meta.module_name) + info = (app_label, model._meta.model_name) try: add_models.append({ 'title': _('Add %s') % capfirst(model._meta.verbose_name), diff --git a/xadmin/plugins/utils.py b/xadmin/plugins/utils.py new file mode 100644 index 000000000..6bc7e7915 --- /dev/null +++ b/xadmin/plugins/utils.py @@ -0,0 +1,15 @@ +from django.template.context import RequestContext + + +def get_context_dict(context): + """ + Contexts in django version 1.9+ must be dictionaries. As xadmin has a legacy with older versions of django, + the function helps the transition by converting the [RequestContext] object to the dictionary when necessary. + :param context: RequestContext + :return: dict + """ + if isinstance(context, RequestContext): + ctx = context.flatten() + else: + ctx = context + return ctx diff --git a/xadmin/plugins/wizard.py b/xadmin/plugins/wizard.py index d354f69cd..38d21d406 100644 --- a/xadmin/plugins/wizard.py +++ b/xadmin/plugins/wizard.py @@ -1,16 +1,29 @@ import re +from collections import OrderedDict from django import forms from django.db import models from django.template import loader -from django.contrib.formtools.wizard.storage import get_storage -from django.contrib.formtools.wizard.forms import ManagementForm -from django.contrib.formtools.wizard.views import StepsHelper -from django.utils.datastructures import SortedDict +try: + from formtools.wizard.storage import get_storage + from formtools.wizard.forms import ManagementForm + from formtools.wizard.views import StepsHelper +except: + # work for django<1.8 + from django.contrib.formtools.wizard.storage import get_storage + from django.contrib.formtools.wizard.forms import ManagementForm + from django.contrib.formtools.wizard.views import StepsHelper + +from django.utils import six +from django.utils.encoding import smart_text +from django.utils.module_loading import import_string from django.forms import ValidationError from django.forms.models import modelform_factory + from xadmin.sites import site from xadmin.views import BaseAdminPlugin, ModelFormAdminView +from xadmin.util import DJANGO_11 + def normalize_name(name): new = re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', '_\\1', name) @@ -22,7 +35,7 @@ class WizardFormPlugin(BaseAdminPlugin): wizard_form_list = None wizard_for_update = False - storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage' + storage_name = 'formtools.wizard.storage.session.SessionStorage' form_list = None initial_dict = None instance_dict = None @@ -32,17 +45,20 @@ class WizardFormPlugin(BaseAdminPlugin): def _get_form_prefix(self, step=None): if step is None: step = self.steps.current - return 'step_%d' % self.get_form_list().keys().index(step) + obj = self.get_form_list().keys() + if six.PY3: + obj = [s for s in obj] + return 'step_%d' % obj.index(step) def get_form_list(self): if not hasattr(self, '_form_list'): - init_form_list = SortedDict() + init_form_list = OrderedDict() assert len( self.wizard_form_list) > 0, 'at least one form is needed' for i, form in enumerate(self.wizard_form_list): - init_form_list[unicode(form[0])] = form[1] + init_form_list[smart_text(form[0])] = form[1] self._form_list = init_form_list @@ -51,7 +67,7 @@ def get_form_list(self): # Plugin replace methods def init_request(self, *args, **kwargs): if self.request.is_ajax() or ("_ajax" in self.request.GET) or not hasattr(self.request, 'session') or (args and not self.wizard_for_update): - #update view + # update view return False return bool(self.wizard_form_list) @@ -75,8 +91,10 @@ def prepare_form(self, __): # form. (This makes stepping back a lot easier). wizard_goto_step = self.request.POST.get('wizard_goto_step', None) if wizard_goto_step and int(wizard_goto_step) < len(self.get_form_list()): - self.storage.current_step = self.get_form_list( - ).keys()[int(wizard_goto_step)] + obj = self.get_form_list().keys() + if six.PY3: + obj = [s for s in obj] + self.storage.current_step = obj[int(wizard_goto_step)] self.admin_view.model_form = self.get_step_form() self.wizard_goto_step = True return @@ -84,6 +102,7 @@ def prepare_form(self, __): # Check if form was refreshed management_form = ManagementForm( self.request.POST, prefix=self.prefix) + if not management_form.is_valid(): raise ValidationError( 'ManagementForm data is missing or has been tampered.') @@ -269,10 +288,12 @@ def get_next_step(self, step=None): """ if step is None: step = self.steps.current - form_list = self.get_form_list() - key = form_list.keyOrder.index(step) + 1 - if len(form_list.keyOrder) > key: - return form_list.keyOrder[key] + obj = self.get_form_list().keys() + if six.PY3: + obj = [s for s in obj] + key = obj.index(step) + 1 + if len(obj) > key: + return obj[key] return None def get_prev_step(self, step=None): @@ -283,10 +304,12 @@ def get_prev_step(self, step=None): """ if step is None: step = self.steps.current - form_list = self.get_form_list() - key = form_list.keyOrder.index(step) - 1 + obj = self.get_form_list().keys() + if six.PY3: + obj = [s for s in obj] + key = obj.index(step) - 1 if key >= 0: - return form_list.keyOrder[key] + return obj[key] return None def get_step_index(self, step=None): @@ -296,23 +319,27 @@ def get_step_index(self, step=None): """ if step is None: step = self.steps.current - return self.get_form_list().keyOrder.index(step) + obj = self.get_form_list().keys() + if six.PY3: + obj = [s for s in obj] + return obj.index(step) def block_before_fieldsets(self, context, nodes): - context.update(dict(self.storage.extra_data)) + context = context.update(dict(self.storage.extra_data)) context['wizard'] = { 'steps': self.steps, 'management_form': ManagementForm(prefix=self.prefix, initial={ 'current_step': self.steps.current, }), } - nodes.append(loader.render_to_string('xadmin/blocks/model_form.before_fieldsets.wizard.html', context_instance=context)) + nodes.append(loader.render_to_string('xadmin/blocks/model_form.before_fieldsets.wizard.html', context)) def block_submit_line(self, context, nodes): - context.update(dict(self.storage.extra_data)) + context = context.update(dict(self.storage.extra_data)) context['wizard'] = { 'steps': self.steps } - nodes.append(loader.render_to_string('xadmin/blocks/model_form.submit_line.wizard.html', context_instance=context)) + + nodes.append(loader.render_to_string('xadmin/blocks/model_form.submit_line.wizard.html', context)) site.register_plugin(WizardFormPlugin, ModelFormAdminView) diff --git a/xadmin/plugins/xversion.py b/xadmin/plugins/xversion.py index d4ff5f727..6e337a72b 100644 --- a/xadmin/plugins/xversion.py +++ b/xadmin/plugins/xversion.py @@ -1,14 +1,15 @@ -from django.contrib.contenttypes.generic import GenericRelation +from crispy_forms.utils import TEMPLATE_PACK +from django.contrib.contenttypes.fields import GenericRelation from django.contrib.contenttypes.models import ContentType from django.core.exceptions import PermissionDenied from django.db import models from django.db.models.query import QuerySet -from django.db.models.related import RelatedObject from django.forms.models import model_to_dict from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 from django.template.response import TemplateResponse -from django.utils.encoding import force_unicode +from django.utils import six +from django.utils.encoding import force_text, smart_text from django.utils.safestring import mark_safe from django.utils.text import capfirst from django.utils.translation import ugettext as _ @@ -17,12 +18,13 @@ from xadmin.plugins.actions import BaseActionView from xadmin.plugins.inline import InlineModelAdmin from xadmin.sites import site -from xadmin.util import unquote, quote, model_format_dict +from xadmin.util import unquote, quote, model_format_dict, is_related_field2 from xadmin.views import BaseAdminPlugin, ModelAdminView, CreateAdminView, UpdateAdminView, DetailAdminView, ModelFormAdminView, DeleteAdminView, ListAdminView from xadmin.views.base import csrf_protect_m, filter_hook from xadmin.views.detail import DetailAdminUtil from reversion.models import Revision, Version -from reversion.revisions import default_revision_manager, RegistrationError +from reversion.revisions import is_active, register, is_registered, set_comment, create_revision, set_user +from contextlib import contextmanager from functools import partial @@ -30,22 +32,19 @@ def _autoregister(admin, model, follow=None): """Registers a model with reversion, if required.""" if model._meta.proxy: raise RegistrationError("Proxy models cannot be used with django-reversion, register the parent class instead") - if not admin.revision_manager.is_registered(model): + if not is_registered(model): follow = follow or [] for parent_cls, field in model._meta.parents.items(): follow.append(field.name) _autoregister(admin, parent_cls) - admin.revision_manager.register( - model, follow=follow, format=admin.reversion_format) + register(model, follow=follow, format=admin.reversion_format) def _register_model(admin, model): - if not hasattr(admin, 'revision_manager'): - admin.revision_manager = default_revision_manager if not hasattr(admin, 'reversion_format'): admin.reversion_format = 'json' - if not admin.revision_manager.is_registered(model): + if not is_registered(model): inline_fields = [] for inline in getattr(admin, 'inlines', []): inline_model = inline.model @@ -53,7 +52,10 @@ def _register_model(admin, model): ct_field = getattr(inline, 'ct_field', 'content_type') ct_fk_field = getattr(inline, 'ct_fk_field', 'object_id') for field in model._meta.many_to_many: - if isinstance(field, GenericRelation) and field.rel.to == inline_model and field.object_id_field_name == ct_fk_field and field.content_type_field_name == ct_field: + if isinstance(field, GenericRelation) \ + and field.rel.to == inline_model \ + and field.object_id_field_name == ct_fk_field \ + and field.content_type_field_name == ct_field: inline_fields.append(field.name) _autoregister(admin, inline_model) else: @@ -64,8 +66,7 @@ def _register_model(admin, model): fk_name = field.name _autoregister(admin, inline_model, follow=[fk_name]) if not inline_model._meta.get_field(fk_name).rel.is_hidden(): - accessor = inline_model._meta.get_field( - fk_name).related.get_accessor_name() + accessor = inline_model._meta.get_field(fk_name).remote_field.get_accessor_name() inline_fields.append(accessor) _autoregister(admin, model, inline_fields) @@ -78,12 +79,14 @@ def register_models(admin_site=None): if getattr(admin, 'reversion_enable', False): _register_model(admin, model) +@contextmanager +def do_create_revision(request): + with create_revision(): + set_user(request.user) + yield class ReversionPlugin(BaseAdminPlugin): - # The revision manager instance used to manage revisions. - revision_manager = default_revision_manager - # The serialization format to use when registering models with reversion. reversion_format = "json" @@ -95,32 +98,6 @@ class ReversionPlugin(BaseAdminPlugin): def init_request(self, *args, **kwargs): return self.reversion_enable - @property - def revision_context_manager(self): - """The revision context manager for this VersionAdmin.""" - return self.revision_manager._revision_context_manager - - def get_revision_instances(self, obj): - """Returns all the instances to be used in the object's revision.""" - return [obj] - - def get_revision_data(self, obj, flag): - """Returns all the revision data to be used in the object's revision.""" - return dict( - (o, self.revision_manager.get_adapter( - o.__class__).get_version_data(o, flag)) - for o in self.get_revision_instances(obj) - ) - - def save_revision(self, obj, tag, comment): - self.revision_manager.save_revision( - self.get_revision_data(obj, tag), - user=self.user, - comment=comment, - ignore_duplicates=self.ignore_duplicate_revisions, - db=self.revision_context_manager.get_db(), - ) - def do_post(self, __): def _method(): self.revision_context_manager.set_user(self.user) @@ -142,23 +119,8 @@ def _method(): return _method def post(self, __, request, *args, **kwargs): - return self.revision_context_manager.create_revision(manage_manually=False)(self.do_post(__))() - - # def save_models(self, __): - # self.revision_context_manager.create_revision(manage_manually=True)(__)() - - # if self.admin_view.org_obj is None: - # self.save_revision(self.admin_view.new_obj, VERSION_ADD, _(u"Initial version.")) - # else: - # self.save_revision(self.admin_view.new_obj, VERSION_CHANGE, _(u"Change version.")) - - # def save_related(self, __): - # self.revision_context_manager.create_revision(manage_manually=True)(__)() - - # def delete_model(self, __): - # self.save_revision(self.admin_view.obj, VERSION_DELETE, \ - # _(u"Deleted %(verbose_name)s.") % {"verbose_name": self.opts.verbose_name}) - # self.revision_context_manager.create_revision(manage_manually=True)(__)() + with do_create_revision(request): + return __() # Block Views def block_top_toolbar(self, context, nodes): @@ -171,7 +133,7 @@ def block_nav_toggles(self, context, nodes): if obj: revisionlist_url = self.admin_view.model_admin_url( 'revisionlist', quote(obj.pk)) - nodes.append(mark_safe('' % revisionlist_url)) + nodes.append(mark_safe('' % revisionlist_url)) def block_nav_btns(self, context, nodes): obj = getattr( @@ -179,13 +141,22 @@ def block_nav_btns(self, context, nodes): if obj: revisionlist_url = self.admin_view.model_admin_url( 'revisionlist', quote(obj.pk)) - nodes.append(mark_safe(' %s' % (revisionlist_url, _(u'History')))) + nodes.append(mark_safe(' %s' % (revisionlist_url, _(u'History')))) +# action revision +class ActionRevisionPlugin(BaseAdminPlugin): -class BaseReversionView(ModelAdminView): + reversion_enable = False + + def init_request(self, *args, **kwargs): + return self.reversion_enable + + def do_action(self, __, queryset): + with do_create_revision(self.request): + return __() - # The revision manager instance used to manage revisions. - revision_manager = default_revision_manager + +class BaseReversionView(ModelAdminView): # The serialization format to use when registering models with reversion. reversion_format = "json" @@ -216,13 +187,12 @@ class RecoverListView(BaseReversionView): def get_context(self): context = super(RecoverListView, self).get_context() opts = self.opts - deleted = self._order_version_queryset( - self.revision_manager.get_deleted(self.model)) + deleted = self._order_version_queryset(Version.objects.get_deleted(self.model)) context.update({ "opts": opts, "app_label": opts.app_label, - "module_name": capfirst(opts.verbose_name), - "title": _("Recover deleted %(name)s") % {"name": force_unicode(opts.verbose_name_plural)}, + "model_name": capfirst(opts.verbose_name), + "title": _("Recover deleted %(name)s") % {"name": force_text(opts.verbose_name_plural)}, "deleted": deleted, "changelist_url": self.model_admin_url("https://github.com/changelist"), }) @@ -234,8 +204,8 @@ def get(self, request, *args, **kwargs): return TemplateResponse( request, self.recover_list_template or self.get_template_list( - "views/recover_list.html"), - context, current_app=self.admin_site.name) + "views/recover_list.html"), + context) class RevisionListView(BaseReversionView): @@ -243,6 +213,12 @@ class RevisionListView(BaseReversionView): object_history_template = None revision_diff_template = None + def _reversion_order_version_queryset(self, queryset): + """Applies the correct ordering to the given version queryset.""" + if not self.history_latest_first: + queryset = queryset.order_by("pk") + return queryset + def get_context(self): context = super(RevisionListView, self).get_context() @@ -254,15 +230,15 @@ def get_context(self): "version": version } for version - in self._order_version_queryset(self.revision_manager.get_for_object_reference( + in self._reversion_order_version_queryset(Version.objects.get_for_object_reference( self.model, self.obj.pk, ).select_related("revision__user")) ] context.update({ - 'title': _('Change history: %s') % force_unicode(self.obj), + 'title': _('Change history: %s') % force_text(self.obj), 'action_list': action_list, - 'module_name': capfirst(force_unicode(opts.verbose_name_plural)), + 'model_name': capfirst(force_text(opts.verbose_name_plural)), 'object': self.obj, 'app_label': opts.app_label, "changelist_url": self.model_admin_url("https://github.com/changelist"), @@ -284,10 +260,10 @@ def get_response(self): context = self.get_context() return TemplateResponse(self.request, self.object_history_template or - self.get_template_list('views/model_history.html'), context, current_app=self.admin_site.name) + self.get_template_list('views/model_history.html'), context) def get_version_object(self, version): - obj_version = version.object_version + obj_version = version._object_version obj = obj_version.object obj._state.db = self.obj._state.db @@ -330,7 +306,7 @@ def post(self, request, object_id, *args, **kwargs): obj_b, detail_b = self.get_version_object(version_b) for f in (self.opts.fields + self.opts.many_to_many): - if isinstance(f, RelatedObject): + if is_related_field2(f): label = f.opts.verbose_name else: label = f.verbose_name @@ -365,7 +341,7 @@ def post(self, request, object_id, *args, **kwargs): return TemplateResponse( self.request, self.revision_diff_template or self.get_template_list('views/revision_diff.html'), - context, current_app=self.admin_site.name) + context) @filter_hook def get_media(self): @@ -401,11 +377,11 @@ def get_media(self): class DiffField(Field): - def render(self, form, form_style, context): + def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs): html = '' for field in self.fields: html += ('
    %s
    ' % - (_('Current: %s') % self.attrs.pop('orgdata', ''), render_field(field, form, form_style, context, template=self.template, attrs=self.attrs))) + (_('Current: %s') % self.attrs.pop('orgdata', ''), render_field(field, form, form_style, context, template_pack=template_pack, attrs=self.attrs))) return html @@ -418,7 +394,7 @@ def init_request(self, object_id, version_id): DetailAdminView, self.model, object_id) self.org_obj = self.detail.obj self.version = get_object_or_404( - Version, pk=version_id, object_id=unicode(self.org_obj.pk)) + Version, pk=version_id, object_id=smart_text(self.org_obj.pk)) self.prepare_form() @@ -426,8 +402,17 @@ def get_form_helper(self): helper = super(RevisionView, self).get_form_helper() diff_fields = {} version_data = self.version.field_dict + for f in self.opts.fields: - if f.value_from_object(self.org_obj) != version_data.get(f.name, None): + fvalue = f.value_from_object(self.org_obj) + vvalue = version_data.get(f.name, None) + + if fvalue is None and vvalue == '': + vvalue = None + if is_related_field2(f): + vvalue = version_data.get(f.name + '_' + f.rel.get_related_field().name, None) + + if fvalue != vvalue: diff_fields[f.name] = self.detail.get_field_result(f.name).val for k, v in diff_fields.items(): helper[k].wrap(DiffField, orgdata=v) @@ -437,7 +422,7 @@ def get_form_helper(self): def get_context(self): context = super(RevisionView, self).get_context() context["title"] = _( - "Revert %s") % force_unicode(self.model._meta.verbose_name) + "Revert %s") % force_text(self.model._meta.verbose_name) return context @filter_hook @@ -449,12 +434,12 @@ def get_response(self): return TemplateResponse( self.request, form_template or self.get_template_list( 'views/revision_form.html'), - context, current_app=self.admin_site.name) + context) @filter_hook def post_response(self): self.message_user(_('The %(model)s "%(name)s" was reverted successfully. You may edit it again below.') % - {"model": force_unicode(self.opts.verbose_name), "name": unicode(self.new_obj)}, 'success') + {"model": force_text(self.opts.verbose_name), "name": smart_text(self.new_obj)}, 'success') return HttpResponseRedirect(self.model_admin_url('https://github.com/change',%20self.new_obj.pk)) @@ -467,7 +452,7 @@ def init_request(self, version_id): raise PermissionDenied self.version = get_object_or_404(Version, pk=version_id) - self.org_obj = self.version.object_version.object + self.org_obj = self.version._object_version.object self.prepare_form() @@ -486,18 +471,18 @@ def get_response(self): return TemplateResponse( self.request, form_template or self.get_template_list( 'views/recover_form.html'), - context, current_app=self.admin_site.name) + context) @filter_hook def post_response(self): self.message_user(_('The %(model)s "%(name)s" was recovered successfully. You may edit it again below.') % - {"model": force_unicode(self.opts.verbose_name), "name": unicode(self.new_obj)}, 'success') + {"model": force_text(self.opts.verbose_name), "name": smart_text(self.new_obj)}, 'success') return HttpResponseRedirect(self.model_admin_url('https://github.com/change',%20self.new_obj.pk)) class InlineDiffField(Field): - def render(self, form, form_style, context): + def render(self, form, form_style, context, template_pack=TEMPLATE_PACK, **kwargs): html = '' instance = form.instance if not instance.pk: @@ -509,7 +494,7 @@ def render(self, form, form_style, context): for field in self.fields: f = opts.get_field(field) f_html = render_field(field, form, form_style, context, - template=self.template, attrs=self.attrs) + template_pack=template_pack, attrs=self.attrs) if f.value_from_object(instance) != initial.get(field, None): current_val = detail.get_field_result(f.name).val html += ('
    %s
    ' @@ -528,7 +513,7 @@ def get_related_versions(self, obj, version, formset): object_id = obj.pk # Get the fk name. try: - fk_name = formset.fk.name + fk_name = formset.fk.name + '_' + formset.fk.rel.get_related_field().name except AttributeError: # This is a GenericInlineFormset, or similar. fk_name = formset.ct_fk_field.name @@ -537,7 +522,7 @@ def get_related_versions(self, obj, version, formset): related_versions = dict([(related_version.object_id, related_version) for related_version in revision_versions if ContentType.objects.get_for_id(related_version.content_type_id).model_class() == formset.model - and unicode(related_version.field_dict[fk_name]) == unicode(object_id)]) + and smart_text(related_version.field_dict[fk_name]) == smart_text(object_id)]) return related_versions def _hack_inline_formset_initial(self, revision_view, formset): @@ -548,9 +533,9 @@ def _hack_inline_formset_initial(self, revision_view, formset): revision_view.org_obj, revision_view.version, formset) formset.related_versions = related_versions for related_obj in formset.queryset: - if unicode(related_obj.pk) in related_versions: + if smart_text(related_obj.pk) in related_versions: initial.append( - related_versions.pop(unicode(related_obj.pk)).field_dict) + related_versions.pop(smart_text(related_obj.pk)).field_dict) else: initial_data = model_to_dict(related_obj) initial_data["DELETE"] = True @@ -579,8 +564,9 @@ def total_form_count_hack(count): if self.request.method == 'GET' and formset.helper and formset.helper.layout: helper = formset.helper - helper.filter(basestring).wrap(InlineDiffField) - fake_admin_class = type(str('%s%sFakeAdmin' % (self.opts.app_label, self.opts.module_name)), (object, ), {'model': self.model}) + cls_str = str if six.PY3 else basestring + helper.filter(cls_str).wrap(InlineDiffField) + fake_admin_class = type(str('%s%sFakeAdmin' % (self.opts.app_label, self.opts.model_name)), (object, ), {'model': self.model}) for form in formset.forms: instance = form.instance if instance.pk: @@ -593,34 +579,6 @@ def instance_form(self, formset, **kwargs): self._hack_inline_formset_initial(admin_view, formset) return formset -# action revision - - -class ActionRevisionPlugin(BaseAdminPlugin): - - revision_manager = default_revision_manager - reversion_enable = False - - def init_request(self, *args, **kwargs): - return self.reversion_enable - - @property - def revision_context_manager(self): - return self.revision_manager._revision_context_manager - - def do_action_func(self, __): - def _method(): - self.revision_context_manager.set_user(self.user) - action_view = self.admin_view - comment = action_view.description % model_format_dict(self.opts) - - self.revision_context_manager.set_comment(comment) - return __() - return _method - - def do_action(self, __, queryset): - return self.revision_context_manager.create_revision(manage_manually=False)(self.do_action_func(__))() - class VersionInline(object): model = Version diff --git a/xadmin/sites.py b/xadmin/sites.py index 5ad923afd..f5bff8de8 100644 --- a/xadmin/sites.py +++ b/xadmin/sites.py @@ -1,12 +1,18 @@ import sys from functools import update_wrapper +from future.utils import iteritems from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.db.models.base import ModelBase +from django.utils import six from django.views.decorators.cache import never_cache +from django.template.engine import Engine +import inspect -reload(sys) -sys.setdefaultencoding("utf-8") +if six.PY2 and sys.getdefaultencoding() == 'ascii': + import imp + imp.reload(sys) + sys.setdefaultencoding("utf-8") class AlreadyRegistered(Exception): @@ -18,6 +24,7 @@ class NotRegistered(Exception): class MergeAdminMetaclass(type): + def __new__(cls, name, bases, attrs): return type.__new__(cls, str(name), bases, attrs) @@ -32,14 +39,14 @@ def __init__(self, name='xadmin'): self._registry_avs = {} # admin_view_class class -> admin_class class self._registry_settings = {} # settings name -> admin_class class self._registry_views = [] - # url instance contains (path, admin_view class, name) + # url instance contains (path, admin_view class, name) self._registry_modelviews = [] - # url instance contains (path, admin_view class, name) + # url instance contains (path, admin_view class, name) self._registry_plugins = {} # view_class class -> plugin_class class self._admin_view_cache = {} - self.check_dependencies() + # self.check_dependencies() self.model_admins_order = 0 @@ -68,7 +75,7 @@ def register_modelview(self, path, admin_view_class, name): self._registry_modelviews.append((path, admin_view_class, name)) else: raise ImproperlyConfigured(u'The registered view class %s isn\'t subclass of %s' % - (admin_view_class.__name__, BaseAdminView.__name__)) + (admin_view_class.__name__, BaseAdminView.__name__)) def register_view(self, path, admin_view_class, name): self._registry_views.append((path, admin_view_class, name)) @@ -80,7 +87,7 @@ def register_plugin(self, plugin_class, admin_view_class): admin_view_class, []).append(plugin_class) else: raise ImproperlyConfigured(u'The registered plugin class %s isn\'t subclass of %s' % - (plugin_class.__name__, BaseAdminPlugin.__name__)) + (plugin_class.__name__, BaseAdminPlugin.__name__)) def register_settings(self, name, admin_class): self._registry_settings[name.lower()] = admin_class @@ -107,7 +114,7 @@ def register(self, model_or_iterable, admin_class=object, **options): # which causes issues later on. options['__module__'] = __name__ - admin_class = type(str("%s%sAdmin" % (model._meta.app_label, model._meta.module_name)), (admin_class,), options or {}) + admin_class = type(str("%s%sAdmin" % (model._meta.app_label, model._meta.model_name)), (admin_class,), options or {}) admin_class.model = model admin_class.order = self.model_admins_order self.model_admins_order += 1 @@ -165,8 +172,10 @@ def check_dependencies(self): if not ContentType._meta.installed: raise ImproperlyConfigured("Put 'django.contrib.contenttypes' in " "your INSTALLED_APPS setting in order to use the admin application.") - if not ('django.contrib.auth.context_processors.auth' in settings.TEMPLATE_CONTEXT_PROCESSORS or - 'django.core.context_processors.auth' in settings.TEMPLATE_CONTEXT_PROCESSORS): + + default_template_engine = Engine.get_default() + if not ('django.contrib.auth.context_processors.auth' in default_template_engine.context_processors or + 'django.core.context_processors.auth' in default_template_engine.context_processors): raise ImproperlyConfigured("Put 'django.contrib.auth.context_processors.auth' " "in your TEMPLATE_CONTEXT_PROCESSORS setting in order to use the admin application.") @@ -181,12 +190,12 @@ def admin_view(self, view, cacheable=False): class MyAdminSite(AdminSite): def get_urls(self): - from django.conf.urls import patterns, url + from django.conf.urls import url urls = super(MyAdminSite, self).get_urls() - urls += patterns('', + urls += [ url(https://github.com/r'%5Emy_view/),%20self.admin_view(some_view)) - ) + ] return urls By default, admin_views are marked non-cacheable using the @@ -203,7 +212,7 @@ def inner(request, *args, **kwargs): def _get_merge_attrs(self, option_class, plugin_class): return dict([(name, getattr(option_class, name)) for name in dir(option_class) - if name[0] != '_' and not callable(getattr(option_class, name)) and hasattr(plugin_class, name)]) + if name[0] != '_' and not callable(getattr(option_class, name)) and hasattr(plugin_class, name)]) def _get_settings_class(self, admin_view_class): name = admin_view_class.__name__.lower() @@ -280,7 +289,7 @@ def create_model_admin_view(self, admin_view_class, model, option_class): return self.get_view_class(admin_view_class, option_class).as_view() def get_urls(self): - from django.conf.urls import patterns, url, include + from django.conf.urls import url, include from xadmin.views.base import BaseAdminView if settings.DEBUG: @@ -292,32 +301,37 @@ def wrapper(*args, **kwargs): return update_wrapper(wrapper, view) # Admin-site-wide views. - urlpatterns = patterns('', - url(r'^jsi18n/$', wrap(self.i18n_javascript, - cacheable=True), name='jsi18n') - ) + urlpatterns = [ + url(https://github.com/r'%5Ejsi18n/),%20wrap(self.i18n_javascript,%20cacheable=True), name='jsi18n') + ] # Registed admin views - urlpatterns += patterns('', - *[url( - path, wrap(self.create_admin_view(clz_or_func)) if type(clz_or_func) == type and issubclass(clz_or_func, BaseAdminView) else include(clz_or_func(self)), - name=name) for path, clz_or_func, name in self._registry_views] - ) + # inspect[isclass]: Only checks if the object is a class. With it lets you create an custom view that + # inherits from multiple views and have more of a metaclass. + urlpatterns += [ + url( + path, + wrap(self.create_admin_view(clz_or_func)) + if inspect.isclass(clz_or_func) and issubclass(clz_or_func, BaseAdminView) + else include(clz_or_func(self)), + name=name + ) + for path, clz_or_func, name in self._registry_views + ] # Add in each model's views. - for model, admin_class in self._registry.iteritems(): - view_urls = [url( - path, wrap( - self.create_model_admin_view(clz, model, admin_class)), - name=name % (model._meta.app_label, model._meta.module_name)) - for path, clz, name in self._registry_modelviews] - urlpatterns += patterns('', - url( - r'^%s/%s/' % ( - model._meta.app_label, model._meta.module_name), - include(patterns('', *view_urls))) - ) - + for model, admin_class in iteritems(self._registry): + view_urls = [ + url( + path, + wrap(self.create_model_admin_view(clz, model, admin_class)), + name=name % (model._meta.app_label, model._meta.model_name) + ) + for path, clz, name in self._registry_modelviews + ] + urlpatterns += [ + url(https://github.com/r'%5E%s/%s/'%20%%20(model._meta.app_label,%20model._meta.model_name), include(view_urls)) + ] return urlpatterns @property @@ -340,3 +354,10 @@ def i18n_javascript(self, request): # This global object represents the default admin site, for the common case. # You can instantiate AdminSite in your own code to create a custom admin site. site = AdminSite() + + +def register(models, **kwargs): + + def _model_admin_wrapper(admin_class): + site.register(models, admin_class) + return _model_admin_wrapper diff --git a/xadmin/static/xadmin/css/xadmin.form.css b/xadmin/static/xadmin/css/xadmin.form.css index 022a9e5fd..54cb761a5 100644 --- a/xadmin/static/xadmin/css/xadmin.form.css +++ b/xadmin/static/xadmin/css/xadmin.form.css @@ -85,7 +85,7 @@ select.selectmultiple { { max-width: 300px; } - .input-group.date{ max-width: 220px;} + .input-group.date{ max-width: 300px;} .input-group.time{ max-width: 180px;} .int-field { max-width: 100px; @@ -187,4 +187,9 @@ img.field_img { /** tabs **/ .nav.nav-tabs { margin-bottom: 15px; +} + +/** selectize **/ +.selectize-input { + vertical-align: bottom; } \ No newline at end of file diff --git a/xadmin/static/xadmin/css/xadmin.page.dashboard.css b/xadmin/static/xadmin/css/xadmin.page.dashboard.css index 5cbad7837..7b7dd7e62 100644 --- a/xadmin/static/xadmin/css/xadmin.page.dashboard.css +++ b/xadmin/static/xadmin/css/xadmin.page.dashboard.css @@ -7,11 +7,8 @@ } .widget { - position: relative; } .widget_options { - overflow: visible; - position: absolute; } /* Quick Buttons diff --git a/xadmin/static/xadmin/css/xadmin.plugin.importexport.css b/xadmin/static/xadmin/css/xadmin.plugin.importexport.css new file mode 100644 index 000000000..72d8cd6f4 --- /dev/null +++ b/xadmin/static/xadmin/css/xadmin.plugin.importexport.css @@ -0,0 +1,21 @@ +/* FORM ROWS */ + +.form-row { + overflow: hidden; + padding: 10px; + font-size: 13px; + border-bottom: 1px solid #eee; +} + +.form-row img, .form-row input { + vertical-align: middle; +} + +.form-row label input[type="checkbox"] { + margin-top: 0; + vertical-align: 0; +} + +form .form-row p { + padding-left: 0; +} diff --git a/xadmin/static/xadmin/css/xadmin.responsive.css b/xadmin/static/xadmin/css/xadmin.responsive.css index d6e53153f..6fad0a94d 100644 --- a/xadmin/static/xadmin/css/xadmin.responsive.css +++ b/xadmin/static/xadmin/css/xadmin.responsive.css @@ -28,6 +28,7 @@ @media (min-width: 768px) { #content-block:not(.full-content) { padding-left: 5px; + min-height: 450px; } .form-actions .more-btns{ display: inline-block !important; diff --git a/xadmin/static/xadmin/js/xadmin.main.js b/xadmin/static/xadmin/js/xadmin.main.js index ef9371b15..a06a5af62 100644 --- a/xadmin/static/xadmin/js/xadmin.main.js +++ b/xadmin/static/xadmin/js/xadmin.main.js @@ -81,7 +81,7 @@ var el = $(this); el.find('.btn-remove').click(function(){ el.find('input[name=_delete]').val('on'); - return true; + el.submit(); }); }); diff --git a/xadmin/static/xadmin/js/xadmin.page.dashboard.js b/xadmin/static/xadmin/js/xadmin.page.dashboard.js index c901c9d0c..520fe5d54 100644 --- a/xadmin/static/xadmin/js/xadmin.page.dashboard.js +++ b/xadmin/static/xadmin/js/xadmin.page.dashboard.js @@ -11,8 +11,8 @@ jQuery(function() { if(!btn.data('form-modal')){ var modal = $(''); + ''); $('body').append(modal); btn.data('form-modal', modal); modal.find('.modal-body').load(form_url, function(form_html, status, xhr){ diff --git a/xadmin/static/xadmin/js/xadmin.plugin.batch.js b/xadmin/static/xadmin/js/xadmin.plugin.batch.js index 53d204af6..991722494 100644 --- a/xadmin/static/xadmin/js/xadmin.plugin.batch.js +++ b/xadmin/static/xadmin/js/xadmin.plugin.batch.js @@ -13,4 +13,4 @@ } }); -})(jQuery) \ No newline at end of file +})(jQuery) diff --git a/xadmin/static/xadmin/js/xadmin.plugin.details.js b/xadmin/static/xadmin/js/xadmin.plugin.details.js index 9bfa75dbf..12b4a0b8a 100644 --- a/xadmin/static/xadmin/js/xadmin.plugin.details.js +++ b/xadmin/static/xadmin/js/xadmin.plugin.details.js @@ -21,12 +21,17 @@ modal = $(''); + ''); $('body').append(modal); } modal.find('.modal-title').html(el.attr('title')); - modal.find('.edit-btn').attr('href', this.edit_uri); + var edit_btn = modal.find('.edit-btn'); + if(this.edit_uri != ""){ + edit_btn.attr('href', this.edit_uri); + }else{ + edit_btn.remove(); + } modal.find('.modal-body').html('

    '); modal.find('.modal-body').load(this.res_uri + '?_format=html', function(response, status, xhr) { if (status == "error") { diff --git a/xadmin/static/xadmin/js/xadmin.plugin.editable.js b/xadmin/static/xadmin/js/xadmin.plugin.editable.js index 31cb89f31..251861394 100644 --- a/xadmin/static/xadmin/js/xadmin.plugin.editable.js +++ b/xadmin/static/xadmin/js/xadmin.plugin.editable.js @@ -67,11 +67,11 @@ if(this.content == null){ var that = this - $el.find('>i').removeClass('fa fa-edit').addClass('fa-spinner fa-spin') + $el.find('>i').removeClass('fa fa-edit').addClass('fa fa-spinner fa-spin') $.ajax({ url: $el.data('editable-loadurl'), success: function(content){ - $el.find('>i').removeClass('fa-spinner fa-spin').addClass('fa fa-edit') + $el.find('>i').removeClass('fa fa-spinner fa-spin').addClass('fa fa-edit') that.content = content that.toggle() }, @@ -127,6 +127,7 @@ $.when(this.save()) .done($.proxy(function(data) { this.$mask.hide() + this.$mask.parents('.popover').hide() if(data['result'] != 'success' && data['errors']){ var err_html = [] for (var i = data['errors'].length - 1; i >= 0; i--) { @@ -139,11 +140,12 @@ this.$form.find('.controls').append(err_html.join('\n')) } else { this.$text.html(data['new_html'][this.field]) - this.hide() + this.leave(this) } }, this)) .fail($.proxy(function(xhr) { this.$mask.hide() + this.$mask.parents('.popover').hide() alert(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!'); }, this)) } diff --git a/xadmin/static/xadmin/js/xadmin.plugin.filters.js b/xadmin/static/xadmin/js/xadmin.plugin.filters.js index fe2980110..2d77cd690 100644 --- a/xadmin/static/xadmin/js/xadmin.plugin.filters.js +++ b/xadmin/static/xadmin/js/xadmin.plugin.filters.js @@ -26,8 +26,8 @@ $('.menu-date-range form').each(function(){ var el = $(this); - var start_date = el.find('.calendar.date-start').datepicker({format: $.date_local.dateJSFormat, language: 'xadmin'}); - var end_date = el.find('.calendar.date-end').datepicker({format: $.date_local.dateJSFormat, language: 'xadmin'}); + var start_date = el.find('.calendar.date-start').datepicker({format: 'yyyy-mm-dd', language: 'xadmin'}); + var end_date = el.find('.calendar.date-end').datepicker({format: 'yyyy-mm-dd', language: 'xadmin'}); var checkAvailable = function(){ if(start_date.data('datepicker').getDate().valueOf() <= end_date.data('datepicker').getDate().valueOf()){ diff --git a/xadmin/static/xadmin/js/xadmin.plugin.formset.js b/xadmin/static/xadmin/js/xadmin.plugin.formset.js index f2252bd94..5eeabb05b 100644 --- a/xadmin/static/xadmin/js/xadmin.plugin.formset.js +++ b/xadmin/static/xadmin/js/xadmin.plugin.formset.js @@ -63,12 +63,18 @@ }); if ($$.length) { - var template = $('#' + options.prefix + '-empty'); - if(template.is('textarea')){ - template = $(template.val()); - }else if(template.is('script')){ - template = $(template.html()); + var template, el = $('#' + options.prefix + '-empty'); + if(el.is('textarea')) { + template = el.val(); + } else if(el.is('span')) { + template = el.html(); + }else if(el.is('script')) { + template = el.html(); } + + template = el.html(template).text(); // decoded + template = $($.parseHTML(template)); + template.removeAttr('id'); if(template.data("replace-id")){ template.attr('id', template.data("replace-id")); @@ -129,11 +135,11 @@ } } } - } + }; $(function(){ $('.formset-content').each(function(){ $(this).formset(); }); }); -})(jQuery) \ No newline at end of file +})(jQuery); diff --git a/xadmin/static/xadmin/js/xadmin.plugin.importexport.js b/xadmin/static/xadmin/js/xadmin.plugin.importexport.js new file mode 100644 index 000000000..4f76c4d41 --- /dev/null +++ b/xadmin/static/xadmin/js/xadmin.plugin.importexport.js @@ -0,0 +1,12 @@ +$("#export-menu").click(function () { + $("input[name='_select_across']").val($("input[name='select_across']").val()); + if (0 == $("input[name='select_across']").val()) { + var selectedRecords = []; + $.each($('.action-select'), function () { + if (true == $(this).prop('checked')) { + selectedRecords.push($(this).val()); + } + }); + $("input[name='_selected_actions']").val(selectedRecords.join(',')); + } +}); diff --git a/xadmin/static/xadmin/js/xadmin.plugin.sortable.js b/xadmin/static/xadmin/js/xadmin.plugin.sortable.js deleted file mode 100644 index a89d03641..000000000 --- a/xadmin/static/xadmin/js/xadmin.plugin.sortable.js +++ /dev/null @@ -1,16 +0,0 @@ -(function($) { - - $(function(){ - $(".results table tbody").sortable({ - axis: 'y', - items: 'tr', - //handle: 'a.sort_hand', - cursor: 'move', - opacity: 0.8, - stop: function(event, ui) { - //alert(0); - } - }); - }); - -})(jQuery); \ No newline at end of file diff --git a/xadmin/static/xadmin/js/xadmin.plugin.sortablelist.js b/xadmin/static/xadmin/js/xadmin.plugin.sortablelist.js new file mode 100644 index 000000000..0f78e1085 --- /dev/null +++ b/xadmin/static/xadmin/js/xadmin.plugin.sortablelist.js @@ -0,0 +1,49 @@ +(function($) { + $(function() { + $.ajaxSetup({ + beforeSend: function(xhr, settings) { + function getCookie(name) { + var cookieValue = null; + if (document.cookie && document.cookie != '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; + } + if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) { + // Only send the token to relative URLs i.e. locally. + xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); + } + } + }); + + $(".results table tbody").sortable({ + axis: 'y', + items: 'tr', + cursor: 'move', + opacity: 0.8, + update: function(event, ui) { + var $rows = $(this); + $("#save-order").on("click", function(e) { + $.ajax({ + url: $(this).attr('post-url'), + method: 'POST', + data: $rows.sortable('serialize', { + attribute: 'order-key', + expression: (/(.+)_(.+)/), + }) + }); + location.reload(); + }).show(); + } + }); + }); + +})(jQuery); diff --git a/xadmin/static/xadmin/js/xadmin.widget.datetime.js b/xadmin/static/xadmin/js/xadmin.widget.datetime.js index 1ce9d7c70..b0eb9cb6c 100644 --- a/xadmin/static/xadmin/js/xadmin.widget.datetime.js +++ b/xadmin/static/xadmin/js/xadmin.widget.datetime.js @@ -53,8 +53,23 @@ dp.update(new Date()); }) }) + if($.fn.clockpicker){ + f.find('.input-group.bootstrap-clockpicker').each(function(e){ + var el = $(this).find('input'); + var tp = el.clockpicker({ + autoclose: true, + 'default': 'now' + }); + + $(this).find('button').click(function(e){ + var now = new Date() + , value = now.getHours() + ':' + now.getMinutes(); + el.attr('value', value); + }) + }) + } if($.fn.timepicker){ - f.find('.input-group.time').each(function(e){ + f.find('.input-group.bootstrap-timepicker').each(function(e){ var el = $(this).find('input'); var value = el.val(); var tp = el.timepicker({ diff --git a/xadmin/static/xadmin/js/xadmin.widget.select.js b/xadmin/static/xadmin/js/xadmin.widget.select.js index 669b33d91..1dd9a3830 100644 --- a/xadmin/static/xadmin/js/xadmin.widget.select.js +++ b/xadmin/static/xadmin/js/xadmin.widget.select.js @@ -1,64 +1,38 @@ ;(function($){ - // add select2 render - if(!window.__admin_ismobile__){ - $.fn.exform.renders.push(function(f){ - if($.fn.selectize){ - f.find('select:not(.select-search):not([multiple=multiple])').selectize(); - f.find('.select-search').each(function(){ - var $el = $(this); - $el.select2({ - minimumInputLength: 1, - initSelection: function(elem, callback){ - callback({id: elem.val(), '__str__': $el.data('label')}); - }, - ajax: { + // add select render + $.fn.exform.renders.push(function(f){ + if($.fn.selectize){ + f.find('select:not(.select-search):not([multiple=multiple])').selectize(); + f.find('.select-search').each(function(){ + var $el = $(this); + var preload = $el.hasClass('select-preload'); + $el.selectize({ + valueField: 'id', + labelField: '__str__', + searchField: '__str__', + create: false, + maxItems: 1, + preload: preload, + load: function(query, callback) { + if(!preload && !query.length) return callback(); + $.ajax({ url: $el.data('search-url')+$el.data('choices'), dataType: 'json', - data: function (term, page) { - return { - '_q_' : term, - '_cols': 'id.__str__', - 'p': page - 1 - }; + data: { + '_q_' : query, + '_cols': 'id.__str__' }, - results: function (data, page) { - return {results: data.objects, more: data.has_more}; - } - }, - formatResult: function(item){return item['__str__']}, - formatSelection: function(item){return item['__str__']} - }); - }) - }}); - } else { - $.fn.exform.renders.push(function(f){ - if($.fn.select2){ - f.find('.select-search').each(function(){ - var $el = $(this); - $el.select2({ - minimumInputLength: 1, - initSelection: function(elem, callback){ - callback({id: elem.val(), '__str__': $el.data('label')}); - }, - ajax: { - url: $el.data('search-url')+$el.data('choices'), - dataType: 'json', - data: function (term, page) { - return { - '_q_' : term, - '_cols': 'id.__str__', - 'p': page - 1 - }; + type: 'GET', + error: function() { + callback(); }, - results: function (data, page) { - return {results: data.objects, more: data.has_more}; + success: function(res) { + callback(res.objects); } - }, - formatResult: function(item){return item['__str__']}, - formatSelection: function(item){return item['__str__']} - }); - }) - }}); - } + }); + } + }); + }) + }}); })(jQuery) diff --git a/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.css b/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.css new file mode 100755 index 000000000..67d2dc331 --- /dev/null +++ b/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.css @@ -0,0 +1,168 @@ +/*! + * ClockPicker v0.0.7 for Bootstrap (http://weareoutman.github.io/clockpicker/) + * Copyright 2014 Wang Shenwei. + * Licensed under MIT (https://github.com/weareoutman/clockpicker/blob/gh-pages/LICENSE) + */ + +.clockpicker .input-group-addon { + cursor: pointer; +} +.clockpicker-moving { + cursor: move; +} +.clockpicker-align-left.popover > .arrow { + left: 25px; +} +.clockpicker-align-top.popover > .arrow { + top: 17px; +} +.clockpicker-align-right.popover > .arrow { + left: auto; + right: 25px; +} +.clockpicker-align-bottom.popover > .arrow { + top: auto; + bottom: 6px; +} +.clockpicker-popover .popover-title { + background-color: #fff; + color: #999; + font-size: 24px; + font-weight: bold; + line-height: 30px; + text-align: center; +} +.clockpicker-popover .popover-title span { + cursor: pointer; +} +.clockpicker-popover .popover-content { + background-color: #f8f8f8; + padding: 12px; +} +.popover-content:last-child { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; +} +.clockpicker-plate { + background-color: #fff; + border: 1px solid #ccc; + border-radius: 50%; + width: 200px; + height: 200px; + overflow: visible; + position: relative; + /* Disable text selection highlighting. Thanks to Hermanya */ + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.clockpicker-canvas, +.clockpicker-dial { + width: 200px; + height: 200px; + position: absolute; + left: -1px; + top: -1px; +} +.clockpicker-minutes { + visibility: hidden; +} +.clockpicker-tick { + border-radius: 50%; + color: #666; + line-height: 26px; + text-align: center; + width: 26px; + height: 26px; + position: absolute; + cursor: pointer; +} +.clockpicker-tick.active, +.clockpicker-tick:hover { + background-color: rgb(192, 229, 247); + background-color: rgba(0, 149, 221, .25); +} +.clockpicker-button { + background-image: none; + background-color: #fff; + border-width: 1px 0 0; + border-top-left-radius: 0; + border-top-right-radius: 0; + margin: 0; + padding: 10px 0; +} +.clockpicker-button:hover { + background-image: none; + background-color: #ebebeb; +} +.clockpicker-button:focus { + outline: none!important; +} +.clockpicker-dial { + -webkit-transition: -webkit-transform 350ms, opacity 350ms; + -moz-transition: -moz-transform 350ms, opacity 350ms; + -ms-transition: -ms-transform 350ms, opacity 350ms; + -o-transition: -o-transform 350ms, opacity 350ms; + transition: transform 350ms, opacity 350ms; +} +.clockpicker-dial-out { + opacity: 0; +} +.clockpicker-hours.clockpicker-dial-out { + -webkit-transform: scale(1.2, 1.2); + -moz-transform: scale(1.2, 1.2); + -ms-transform: scale(1.2, 1.2); + -o-transform: scale(1.2, 1.2); + transform: scale(1.2, 1.2); +} +.clockpicker-minutes.clockpicker-dial-out { + -webkit-transform: scale(.8, .8); + -moz-transform: scale(.8, .8); + -ms-transform: scale(.8, .8); + -o-transform: scale(.8, .8); + transform: scale(.8, .8); +} +.clockpicker-canvas { + -webkit-transition: opacity 175ms; + -moz-transition: opacity 175ms; + -ms-transition: opacity 175ms; + -o-transition: opacity 175ms; + transition: opacity 175ms; +} +.clockpicker-canvas-out { + opacity: 0.25; +} +.clockpicker-canvas-bearing, +.clockpicker-canvas-fg { + stroke: none; + fill: rgb(0, 149, 221); +} +.clockpicker-canvas-bg { + stroke: none; + fill: rgb(192, 229, 247); +} +.clockpicker-canvas-bg-trans { + fill: rgba(0, 149, 221, .25); +} +.clockpicker-canvas line { + stroke: rgb(0, 149, 221); + stroke-width: 1; + stroke-linecap: round; + /*shape-rendering: crispEdges;*/ +} +.clockpicker-button.am-button { + margin: 1px; + padding: 5px; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 4px; + +} +.clockpicker-button.pm-button { + margin: 1px 1px 1px 136px; + padding: 5px; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 4px; +} diff --git a/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.js b/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.js new file mode 100755 index 000000000..e930b4ff1 --- /dev/null +++ b/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.js @@ -0,0 +1,729 @@ +/*! + * ClockPicker v0.0.7 (http://weareoutman.github.io/clockpicker/) + * Copyright 2014 Wang Shenwei. + * Licensed under MIT (https://github.com/weareoutman/clockpicker/blob/gh-pages/LICENSE) + */ + +;(function(){ + var $ = window.jQuery, + $win = $(window), + $doc = $(document), + $body; + + // Can I use inline svg ? + var svgNS = 'http://www.w3.org/2000/svg', + svgSupported = 'SVGAngle' in window && (function(){ + var supported, + el = document.createElement('div'); + el.innerHTML = ''; + supported = (el.firstChild && el.firstChild.namespaceURI) == svgNS; + el.innerHTML = ''; + return supported; + })(); + + // Can I use transition ? + var transitionSupported = (function(){ + var style = document.createElement('div').style; + return 'transition' in style || + 'WebkitTransition' in style || + 'MozTransition' in style || + 'msTransition' in style || + 'OTransition' in style; + })(); + + // Listen touch events in touch screen device, instead of mouse events in desktop. + var touchSupported = 'ontouchstart' in window, + mousedownEvent = 'mousedown' + ( touchSupported ? ' touchstart' : ''), + mousemoveEvent = 'mousemove.clockpicker' + ( touchSupported ? ' touchmove.clockpicker' : ''), + mouseupEvent = 'mouseup.clockpicker' + ( touchSupported ? ' touchend.clockpicker' : ''); + + // Vibrate the device if supported + var vibrate = navigator.vibrate ? 'vibrate' : navigator.webkitVibrate ? 'webkitVibrate' : null; + + function createSvgElement(name) { + return document.createElementNS(svgNS, name); + } + + function leadingZero(num) { + return (num < 10 ? '0' : '') + num; + } + + // Get a unique id + var idCounter = 0; + function uniqueId(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + } + + // Clock size + var dialRadius = 100, + outerRadius = 80, + // innerRadius = 80 on 12 hour clock + innerRadius = 54, + tickRadius = 13, + diameter = dialRadius * 2, + duration = transitionSupported ? 350 : 1; + + // Popover template + var tpl = [ + '
    ', + '
    ', + '
    ', + '', + ' : ', + '', + '', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '', + '', + '
    ', + '
    ' + ].join(''); + + // ClockPicker + function ClockPicker(element, options) { + var popover = $(tpl), + plate = popover.find('.clockpicker-plate'), + hoursView = popover.find('.clockpicker-hours'), + minutesView = popover.find('.clockpicker-minutes'), + amPmBlock = popover.find('.clockpicker-am-pm-block'), + isInput = element.prop('tagName') === 'INPUT', + input = isInput ? element : element.find('input'), + addon = element.find('.input-group-addon'), + self = this, + timer; + + this.id = uniqueId('cp'); + this.element = element; + this.options = options; + this.isAppended = false; + this.isShown = false; + this.currentView = 'hours'; + this.isInput = isInput; + this.input = input; + this.addon = addon; + this.popover = popover; + this.plate = plate; + this.hoursView = hoursView; + this.minutesView = minutesView; + this.amPmBlock = amPmBlock; + this.spanHours = popover.find('.clockpicker-span-hours'); + this.spanMinutes = popover.find('.clockpicker-span-minutes'); + this.spanAmPm = popover.find('.clockpicker-span-am-pm'); + this.amOrPm = "PM"; + + // Setup for for 12 hour clock if option is selected + if (options.twelvehour) { + + var amPmButtonsTemplate = ['
    ', + '', + '', + '
    '].join(''); + + var amPmButtons = $(amPmButtonsTemplate); + //amPmButtons.appendTo(plate); + + ////Not working b/c they are not shown when this runs + //$('clockpicker-am-button') + // .on("click", function() { + // self.amOrPm = "AM"; + // $('.clockpicker-span-am-pm').empty().append('AM'); + // }); + // + //$('clockpicker-pm-button') + // .on("click", function() { + // self.amOrPm = "PM"; + // $('.clockpicker-span-am-pm').empty().append('PM'); + // }); + + $('') + .on("click", function() { + self.amOrPm = "AM"; + $('.clockpicker-span-am-pm').empty().append('AM'); + }).appendTo(this.amPmBlock); + + + $('') + .on("click", function() { + self.amOrPm = 'PM'; + $('.clockpicker-span-am-pm').empty().append('PM'); + }).appendTo(this.amPmBlock); + + } + + if (! options.autoclose) { + // If autoclose is not setted, append a button + $('') + .click($.proxy(this.done, this)) + .appendTo(popover); + } + + // Placement and arrow align - make sure they make sense. + if ((options.placement === 'top' || options.placement === 'bottom') && (options.align === 'top' || options.align === 'bottom')) options.align = 'left'; + if ((options.placement === 'left' || options.placement === 'right') && (options.align === 'left' || options.align === 'right')) options.align = 'top'; + + popover.addClass(options.placement); + popover.addClass('clockpicker-align-' + options.align); + + this.spanHours.click($.proxy(this.toggleView, this, 'hours')); + this.spanMinutes.click($.proxy(this.toggleView, this, 'minutes')); + + // Show or toggle + input.on('focus.clockpicker click.clockpicker', $.proxy(this.show, this)); + addon.on('click.clockpicker', $.proxy(this.toggle, this)); + + // Build ticks + var tickTpl = $('
    '), + i, tick, radian, radius; + + // Hours view + if (options.twelvehour) { + for (i = 1; i < 13; i += 1) { + tick = tickTpl.clone(); + radian = i / 6 * Math.PI; + radius = outerRadius; + tick.css('font-size', '120%'); + tick.css({ + left: dialRadius + Math.sin(radian) * radius - tickRadius, + top: dialRadius - Math.cos(radian) * radius - tickRadius + }); + tick.html(i === 0 ? '00' : i); + hoursView.append(tick); + tick.on(mousedownEvent, mousedown); + } + } else { + for (i = 0; i < 24; i += 1) { + tick = tickTpl.clone(); + radian = i / 6 * Math.PI; + var inner = i > 0 && i < 13; + radius = inner ? innerRadius : outerRadius; + tick.css({ + left: dialRadius + Math.sin(radian) * radius - tickRadius, + top: dialRadius - Math.cos(radian) * radius - tickRadius + }); + if (inner) { + tick.css('font-size', '120%'); + } + tick.html(i === 0 ? '00' : i); + hoursView.append(tick); + tick.on(mousedownEvent, mousedown); + } + } + + // Minutes view + for (i = 0; i < 60; i += 5) { + tick = tickTpl.clone(); + radian = i / 30 * Math.PI; + tick.css({ + left: dialRadius + Math.sin(radian) * outerRadius - tickRadius, + top: dialRadius - Math.cos(radian) * outerRadius - tickRadius + }); + tick.css('font-size', '120%'); + tick.html(leadingZero(i)); + minutesView.append(tick); + tick.on(mousedownEvent, mousedown); + } + + // Clicking on minutes view space + plate.on(mousedownEvent, function(e){ + if ($(e.target).closest('.clockpicker-tick').length === 0) { + mousedown(e, true); + } + }); + + // Mousedown or touchstart + function mousedown(e, space) { + var offset = plate.offset(), + isTouch = /^touch/.test(e.type), + x0 = offset.left + dialRadius, + y0 = offset.top + dialRadius, + dx = (isTouch ? e.originalEvent.touches[0] : e).pageX - x0, + dy = (isTouch ? e.originalEvent.touches[0] : e).pageY - y0, + z = Math.sqrt(dx * dx + dy * dy), + moved = false; + + // When clicking on minutes view space, check the mouse position + if (space && (z < outerRadius - tickRadius || z > outerRadius + tickRadius)) { + return; + } + e.preventDefault(); + + // Set cursor style of body after 200ms + var movingTimer = setTimeout(function(){ + $body.addClass('clockpicker-moving'); + }, 200); + + // Place the canvas to top + if (svgSupported) { + plate.append(self.canvas); + } + + // Clock + self.setHand(dx, dy, ! space, true); + + // Mousemove on document + $doc.off(mousemoveEvent).on(mousemoveEvent, function(e){ + e.preventDefault(); + var isTouch = /^touch/.test(e.type), + x = (isTouch ? e.originalEvent.touches[0] : e).pageX - x0, + y = (isTouch ? e.originalEvent.touches[0] : e).pageY - y0; + if (! moved && x === dx && y === dy) { + // Clicking in chrome on windows will trigger a mousemove event + return; + } + moved = true; + self.setHand(x, y, false, true); + }); + + // Mouseup on document + $doc.off(mouseupEvent).on(mouseupEvent, function(e){ + $doc.off(mouseupEvent); + e.preventDefault(); + var isTouch = /^touch/.test(e.type), + x = (isTouch ? e.originalEvent.changedTouches[0] : e).pageX - x0, + y = (isTouch ? e.originalEvent.changedTouches[0] : e).pageY - y0; + if ((space || moved) && x === dx && y === dy) { + self.setHand(x, y); + } + if (self.currentView === 'hours') { + self.toggleView('minutes', duration / 2); + } else { + if (options.autoclose) { + self.minutesView.addClass('clockpicker-dial-out'); + setTimeout(function(){ + self.done(); + }, duration / 2); + } + } + plate.prepend(canvas); + + // Reset cursor style of body + clearTimeout(movingTimer); + $body.removeClass('clockpicker-moving'); + + // Unbind mousemove event + $doc.off(mousemoveEvent); + }); + } + + if (svgSupported) { + // Draw clock hands and others + var canvas = popover.find('.clockpicker-canvas'), + svg = createSvgElement('svg'); + svg.setAttribute('class', 'clockpicker-svg'); + svg.setAttribute('width', diameter); + svg.setAttribute('height', diameter); + var g = createSvgElement('g'); + g.setAttribute('transform', 'translate(' + dialRadius + ',' + dialRadius + ')'); + var bearing = createSvgElement('circle'); + bearing.setAttribute('class', 'clockpicker-canvas-bearing'); + bearing.setAttribute('cx', 0); + bearing.setAttribute('cy', 0); + bearing.setAttribute('r', 2); + var hand = createSvgElement('line'); + hand.setAttribute('x1', 0); + hand.setAttribute('y1', 0); + var bg = createSvgElement('circle'); + bg.setAttribute('class', 'clockpicker-canvas-bg'); + bg.setAttribute('r', tickRadius); + var fg = createSvgElement('circle'); + fg.setAttribute('class', 'clockpicker-canvas-fg'); + fg.setAttribute('r', 3.5); + g.appendChild(hand); + g.appendChild(bg); + g.appendChild(fg); + g.appendChild(bearing); + svg.appendChild(g); + canvas.append(svg); + + this.hand = hand; + this.bg = bg; + this.fg = fg; + this.bearing = bearing; + this.g = g; + this.canvas = canvas; + } + + raiseCallback(this.options.init); + } + + function raiseCallback(callbackFunction) { + if (callbackFunction && typeof callbackFunction === "function") { + callbackFunction(); + } + } + + // Default options + ClockPicker.DEFAULTS = { + 'default': '', // default time, 'now' or '13:14' e.g. + fromnow: 0, // set default time to * milliseconds from now (using with default = 'now') + placement: 'bottom', // clock popover placement + align: 'left', // popover arrow align + donetext: '完成', // done button text + autoclose: false, // auto close when minute is selected + twelvehour: false, // change to 12 hour AM/PM clock from 24 hour + vibrate: true // vibrate the device when dragging clock hand + }; + + // Show or hide popover + ClockPicker.prototype.toggle = function(){ + this[this.isShown ? 'hide' : 'show'](); + }; + + // Set popover position + ClockPicker.prototype.locate = function(){ + var element = this.element, + popover = this.popover, + offset = element.offset(), + width = element.outerWidth(), + height = element.outerHeight(), + placement = this.options.placement, + align = this.options.align, + styles = {}, + self = this; + + popover.show(); + + // Place the popover + switch (placement) { + case 'bottom': + styles.top = offset.top + height; + break; + case 'right': + styles.left = offset.left + width; + break; + case 'top': + styles.top = offset.top - popover.outerHeight(); + break; + case 'left': + styles.left = offset.left - popover.outerWidth(); + break; + } + + // Align the popover arrow + switch (align) { + case 'left': + styles.left = offset.left; + break; + case 'right': + styles.left = offset.left + width - popover.outerWidth(); + break; + case 'top': + styles.top = offset.top; + break; + case 'bottom': + styles.top = offset.top + height - popover.outerHeight(); + break; + } + + popover.css(styles); + }; + + // Show popover + ClockPicker.prototype.show = function(e){ + // Not show again + if (this.isShown) { + return; + } + + raiseCallback(this.options.beforeShow); + + var self = this; + + // Initialize + if (! this.isAppended) { + // Append popover to body + $body = $(document.body).append(this.popover); + + // Reset position when resize + $win.on('resize.clockpicker' + this.id, function(){ + if (self.isShown) { + self.locate(); + } + }); + + this.isAppended = true; + } + + // Get the time + var value = ((this.input.prop('value') || this.options['default'] || '') + '').split(':'); + if (value[0] === 'now') { + var now = new Date(+ new Date() + this.options.fromnow); + value = [ + now.getHours(), + now.getMinutes() + ]; + } + this.hours = + value[0] || 0; + this.minutes = + value[1] || 0; + this.spanHours.html(leadingZero(this.hours)); + this.spanMinutes.html(leadingZero(this.minutes)); + + // Toggle to hours view + this.toggleView('hours'); + + // Set position + this.locate(); + + this.isShown = true; + + // Hide when clicking or tabbing on any element except the clock, input and addon + $doc.on('click.clockpicker.' + this.id + ' focusin.clockpicker.' + this.id, function(e){ + var target = $(e.target); + if (target.closest(self.popover).length === 0 && + target.closest(self.addon).length === 0 && + target.closest(self.input).length === 0) { + self.hide(); + } + }); + + // Hide when ESC is pressed + $doc.on('keyup.clockpicker.' + this.id, function(e){ + if (e.keyCode === 27) { + self.hide(); + } + }); + + raiseCallback(this.options.afterShow); + }; + + // Hide popover + ClockPicker.prototype.hide = function(){ + raiseCallback(this.options.beforeHide); + + this.isShown = false; + + // Unbinding events on document + $doc.off('click.clockpicker.' + this.id + ' focusin.clockpicker.' + this.id); + $doc.off('keyup.clockpicker.' + this.id); + + this.popover.hide(); + + raiseCallback(this.options.afterHide); + }; + + // Toggle to hours or minutes view + ClockPicker.prototype.toggleView = function(view, delay){ + var raiseAfterHourSelect = false; + if (view === 'minutes' && $(this.hoursView).css("visibility") === "visible") { + raiseCallback(this.options.beforeHourSelect); + raiseAfterHourSelect = true; + } + var isHours = view === 'hours', + nextView = isHours ? this.hoursView : this.minutesView, + hideView = isHours ? this.minutesView : this.hoursView; + + this.currentView = view; + + this.spanHours.toggleClass('text-primary', isHours); + this.spanMinutes.toggleClass('text-primary', ! isHours); + + // Let's make transitions + hideView.addClass('clockpicker-dial-out'); + nextView.css('visibility', 'visible').removeClass('clockpicker-dial-out'); + + // Reset clock hand + this.resetClock(delay); + + // After transitions ended + clearTimeout(this.toggleViewTimer); + this.toggleViewTimer = setTimeout(function(){ + hideView.css('visibility', 'hidden'); + }, duration); + + if (raiseAfterHourSelect) { + raiseCallback(this.options.afterHourSelect); + } + }; + + // Reset clock hand + ClockPicker.prototype.resetClock = function(delay){ + var view = this.currentView, + value = this[view], + isHours = view === 'hours', + unit = Math.PI / (isHours ? 6 : 30), + radian = value * unit, + radius = isHours && value > 0 && value < 13 ? innerRadius : outerRadius, + x = Math.sin(radian) * radius, + y = - Math.cos(radian) * radius, + self = this; + if (svgSupported && delay) { + self.canvas.addClass('clockpicker-canvas-out'); + setTimeout(function(){ + self.canvas.removeClass('clockpicker-canvas-out'); + self.setHand(x, y); + }, delay); + } else { + this.setHand(x, y); + } + }; + + // Set clock hand to (x, y) + ClockPicker.prototype.setHand = function(x, y, roundBy5, dragging){ + var radian = Math.atan2(x, - y), + isHours = this.currentView === 'hours', + unit = Math.PI / (isHours || roundBy5 ? 6 : 30), + z = Math.sqrt(x * x + y * y), + options = this.options, + inner = isHours && z < (outerRadius + innerRadius) / 2, + radius = inner ? innerRadius : outerRadius, + value; + + if (options.twelvehour) { + radius = outerRadius; + } + + // Radian should in range [0, 2PI] + if (radian < 0) { + radian = Math.PI * 2 + radian; + } + + // Get the round value + value = Math.round(radian / unit); + + // Get the round radian + radian = value * unit; + + // Correct the hours or minutes + if (options.twelvehour) { + if (isHours) { + if (value === 0) { + value = 12; + } + } else { + if (roundBy5) { + value *= 5; + } + if (value === 60) { + value = 0; + } + } + } else { + if (isHours) { + if (value === 12) { + value = 0; + } + value = inner ? (value === 0 ? 12 : value) : value === 0 ? 0 : value + 12; + } else { + if (roundBy5) { + value *= 5; + } + if (value === 60) { + value = 0; + } + } + } + + // Once hours or minutes changed, vibrate the device + if (this[this.currentView] !== value) { + if (vibrate && this.options.vibrate) { + // Do not vibrate too frequently + if (! this.vibrateTimer) { + navigator[vibrate](10); + this.vibrateTimer = setTimeout($.proxy(function(){ + this.vibrateTimer = null; + }, this), 100); + } + } + } + + this[this.currentView] = value; + this[isHours ? 'spanHours' : 'spanMinutes'].html(leadingZero(value)); + + // If svg is not supported, just add an active class to the tick + if (! svgSupported) { + this[isHours ? 'hoursView' : 'minutesView'].find('.clockpicker-tick').each(function(){ + var tick = $(this); + tick.toggleClass('active', value === + tick.html()); + }); + return; + } + + // Place clock hand at the top when dragging + if (dragging || (! isHours && value % 5)) { + this.g.insertBefore(this.hand, this.bearing); + this.g.insertBefore(this.bg, this.fg); + this.bg.setAttribute('class', 'clockpicker-canvas-bg clockpicker-canvas-bg-trans'); + } else { + // Or place it at the bottom + this.g.insertBefore(this.hand, this.bg); + this.g.insertBefore(this.fg, this.bg); + this.bg.setAttribute('class', 'clockpicker-canvas-bg'); + } + + // Set clock hand and others' position + var cx = Math.sin(radian) * radius, + cy = - Math.cos(radian) * radius; + this.hand.setAttribute('x2', cx); + this.hand.setAttribute('y2', cy); + this.bg.setAttribute('cx', cx); + this.bg.setAttribute('cy', cy); + this.fg.setAttribute('cx', cx); + this.fg.setAttribute('cy', cy); + }; + + // Hours and minutes are selected + ClockPicker.prototype.done = function() { + raiseCallback(this.options.beforeDone); + this.hide(); + var last = this.input.prop('value'), + value = leadingZero(this.hours) + ':' + leadingZero(this.minutes); + if (this.options.twelvehour) { + value = value + this.amOrPm; + } + + this.input.prop('value', value); + if (value !== last) { + this.input.triggerHandler('change'); + if (! this.isInput) { + this.element.trigger('change'); + } + } + + if (this.options.autoclose) { + this.input.trigger('blur'); + } + + raiseCallback(this.options.afterDone); + }; + + // Remove clockpicker from input + ClockPicker.prototype.remove = function() { + this.element.removeData('clockpicker'); + this.input.off('focus.clockpicker click.clockpicker'); + this.addon.off('click.clockpicker'); + if (this.isShown) { + this.hide(); + } + if (this.isAppended) { + $win.off('resize.clockpicker' + this.id); + this.popover.remove(); + } + }; + + // Extends $.fn.clockpicker + $.fn.clockpicker = function(option){ + var args = Array.prototype.slice.call(arguments, 1); + return this.each(function(){ + var $this = $(this), + data = $this.data('clockpicker'); + if (! data) { + var options = $.extend({}, ClockPicker.DEFAULTS, $this.data(), typeof option == 'object' && option); + $this.data('clockpicker', new ClockPicker($this, options)); + } else { + // Manual operatsions. show, hide, remove, e.g. + if (typeof data[option] === 'function') { + data[option].apply(data, args); + } + } + }); + }; +}()); diff --git a/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.min.css b/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.min.css new file mode 100755 index 000000000..cf1507843 --- /dev/null +++ b/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.min.css @@ -0,0 +1,5 @@ +/*! + * ClockPicker v0.0.7 for Bootstrap (http://weareoutman.github.io/clockpicker/) + * Copyright 2014 Wang Shenwei. + * Licensed under MIT (https://github.com/weareoutman/clockpicker/blob/gh-pages/LICENSE) + */.clockpicker .input-group-addon{cursor:pointer}.clockpicker-moving{cursor:move}.clockpicker-align-left.popover>.arrow{left:25px}.clockpicker-align-top.popover>.arrow{top:17px}.clockpicker-align-right.popover>.arrow{left:auto;right:25px}.clockpicker-align-bottom.popover>.arrow{top:auto;bottom:6px}.clockpicker-popover .popover-title{background-color:#fff;color:#999;font-size:24px;font-weight:700;line-height:30px;text-align:center}.clockpicker-popover .popover-title span{cursor:pointer}.clockpicker-popover .popover-content{background-color:#f8f8f8;padding:12px}.popover-content:last-child{border-bottom-left-radius:5px;border-bottom-right-radius:5px}.clockpicker-plate{background-color:#fff;border:1px solid #ccc;border-radius:50%;width:200px;height:200px;overflow:visible;position:relative;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.clockpicker-canvas,.clockpicker-dial{width:200px;height:200px;position:absolute;left:-1px;top:-1px}.clockpicker-minutes{visibility:hidden}.clockpicker-tick{border-radius:50%;color:#666;line-height:26px;text-align:center;width:26px;height:26px;position:absolute;cursor:pointer}.clockpicker-tick.active,.clockpicker-tick:hover{background-color:#c0e5f7;background-color:rgba(0,149,221,.25)}.clockpicker-button{background-image:none;background-color:#fff;border-width:1px 0 0;border-top-left-radius:0;border-top-right-radius:0;margin:0;padding:10px 0}.clockpicker-button:hover{background-image:none;background-color:#ebebeb}.clockpicker-button:focus{outline:0!important}.clockpicker-dial{-webkit-transition:-webkit-transform 350ms,opacity 350ms;-moz-transition:-moz-transform 350ms,opacity 350ms;-ms-transition:-ms-transform 350ms,opacity 350ms;-o-transition:-o-transform 350ms,opacity 350ms;transition:transform 350ms,opacity 350ms}.clockpicker-dial-out{opacity:0}.clockpicker-hours.clockpicker-dial-out{-webkit-transform:scale(1.2,1.2);-moz-transform:scale(1.2,1.2);-ms-transform:scale(1.2,1.2);-o-transform:scale(1.2,1.2);transform:scale(1.2,1.2)}.clockpicker-minutes.clockpicker-dial-out{-webkit-transform:scale(.8,.8);-moz-transform:scale(.8,.8);-ms-transform:scale(.8,.8);-o-transform:scale(.8,.8);transform:scale(.8,.8)}.clockpicker-canvas{-webkit-transition:opacity 175ms;-moz-transition:opacity 175ms;-ms-transition:opacity 175ms;-o-transition:opacity 175ms;transition:opacity 175ms}.clockpicker-canvas-out{opacity:.25}.clockpicker-canvas-bearing,.clockpicker-canvas-fg{stroke:none;fill:#0095dd}.clockpicker-canvas-bg{stroke:none;fill:#c0e5f7}.clockpicker-canvas-bg-trans{fill:rgba(0,149,221,.25)}.clockpicker-canvas line{stroke:#0095dd;stroke-width:1;stroke-linecap:round}.clockpicker-button.am-button{margin:1px;padding:5px;border:1px solid rgba(0,0,0,.2);border-radius:4px}.clockpicker-button.pm-button{margin:1px 1px 1px 136px;padding:5px;border:1px solid rgba(0,0,0,.2);border-radius:4px} \ No newline at end of file diff --git a/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.min.js b/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.min.js new file mode 100755 index 000000000..c8006a382 --- /dev/null +++ b/xadmin/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.min.js @@ -0,0 +1,6 @@ +/*! + * ClockPicker v0.0.7 (http://weareoutman.github.io/clockpicker/) + * Copyright 2014 Wang Shenwei. + * Licensed under MIT (https://github.com/weareoutman/clockpicker/blob/gh-pages/LICENSE) + */ +!function(){function t(t){return document.createElementNS(p,t)}function i(t){return(10>t?"0":"")+t}function e(t){var i=++m+"";return t?t+i:i}function s(s,r){function p(t,i){var e=u.offset(),s=/^touch/.test(t.type),o=e.left+b,n=e.top+b,p=(s?t.originalEvent.touches[0]:t).pageX-o,h=(s?t.originalEvent.touches[0]:t).pageY-n,k=Math.sqrt(p*p+h*h),v=!1;if(!i||!(g-y>k||k>g+y)){t.preventDefault();var m=setTimeout(function(){c.addClass("clockpicker-moving")},200);l&&u.append(x.canvas),x.setHand(p,h,!i,!0),a.off(d).on(d,function(t){t.preventDefault();var i=/^touch/.test(t.type),e=(i?t.originalEvent.touches[0]:t).pageX-o,s=(i?t.originalEvent.touches[0]:t).pageY-n;(v||e!==p||s!==h)&&(v=!0,x.setHand(e,s,!1,!0))}),a.off(f).on(f,function(t){a.off(f),t.preventDefault();var e=/^touch/.test(t.type),s=(e?t.originalEvent.changedTouches[0]:t).pageX-o,l=(e?t.originalEvent.changedTouches[0]:t).pageY-n;(i||v)&&s===p&&l===h&&x.setHand(s,l),"hours"===x.currentView?x.toggleView("minutes",A/2):r.autoclose&&(x.minutesView.addClass("clockpicker-dial-out"),setTimeout(function(){x.done()},A/2)),u.prepend(j),clearTimeout(m),c.removeClass("clockpicker-moving"),a.off(d)})}}var h=n(V),u=h.find(".clockpicker-plate"),v=h.find(".clockpicker-hours"),m=h.find(".clockpicker-minutes"),T=h.find(".clockpicker-am-pm-block"),C="INPUT"===s.prop("tagName"),H=C?s:s.find("input"),P=s.find(".input-group-addon"),x=this;if(this.id=e("cp"),this.element=s,this.options=r,this.isAppended=!1,this.isShown=!1,this.currentView="hours",this.isInput=C,this.input=H,this.addon=P,this.popover=h,this.plate=u,this.hoursView=v,this.minutesView=m,this.amPmBlock=T,this.spanHours=h.find(".clockpicker-span-hours"),this.spanMinutes=h.find(".clockpicker-span-minutes"),this.spanAmPm=h.find(".clockpicker-span-am-pm"),this.amOrPm="PM",r.twelvehour){{var S=['
    ','",'","
    "].join("");n(S)}n('').on("click",function(){x.amOrPm="AM",n(".clockpicker-span-am-pm").empty().append("AM")}).appendTo(this.amPmBlock),n('').on("click",function(){x.amOrPm="PM",n(".clockpicker-span-am-pm").empty().append("PM")}).appendTo(this.amPmBlock)}r.autoclose||n('").click(n.proxy(this.done,this)).appendTo(h),"top"!==r.placement&&"bottom"!==r.placement||"top"!==r.align&&"bottom"!==r.align||(r.align="left"),"left"!==r.placement&&"right"!==r.placement||"left"!==r.align&&"right"!==r.align||(r.align="top"),h.addClass(r.placement),h.addClass("clockpicker-align-"+r.align),this.spanHours.click(n.proxy(this.toggleView,this,"hours")),this.spanMinutes.click(n.proxy(this.toggleView,this,"minutes")),H.on("focus.clockpicker click.clockpicker",n.proxy(this.show,this)),P.on("click.clockpicker",n.proxy(this.toggle,this));var E,D,I,B,z=n('
    ');if(r.twelvehour)for(E=1;13>E;E+=1)D=z.clone(),I=E/6*Math.PI,B=g,D.css("font-size","120%"),D.css({left:b+Math.sin(I)*B-y,top:b-Math.cos(I)*B-y}),D.html(0===E?"00":E),v.append(D),D.on(k,p);else for(E=0;24>E;E+=1){D=z.clone(),I=E/6*Math.PI;var O=E>0&&13>E;B=O?w:g,D.css({left:b+Math.sin(I)*B-y,top:b-Math.cos(I)*B-y}),O&&D.css("font-size","120%"),D.html(0===E?"00":E),v.append(D),D.on(k,p)}for(E=0;60>E;E+=5)D=z.clone(),I=E/30*Math.PI,D.css({left:b+Math.sin(I)*g-y,top:b-Math.cos(I)*g-y}),D.css("font-size","120%"),D.html(i(E)),m.append(D),D.on(k,p);if(u.on(k,function(t){0===n(t.target).closest(".clockpicker-tick").length&&p(t,!0)}),l){var j=h.find(".clockpicker-canvas"),L=t("svg");L.setAttribute("class","clockpicker-svg"),L.setAttribute("width",M),L.setAttribute("height",M);var U=t("g");U.setAttribute("transform","translate("+b+","+b+")");var W=t("circle");W.setAttribute("class","clockpicker-canvas-bearing"),W.setAttribute("cx",0),W.setAttribute("cy",0),W.setAttribute("r",2);var N=t("line");N.setAttribute("x1",0),N.setAttribute("y1",0);var X=t("circle");X.setAttribute("class","clockpicker-canvas-bg"),X.setAttribute("r",y);var Y=t("circle");Y.setAttribute("class","clockpicker-canvas-fg"),Y.setAttribute("r",3.5),U.appendChild(N),U.appendChild(X),U.appendChild(Y),U.appendChild(W),L.appendChild(U),j.append(L),this.hand=N,this.bg=X,this.fg=Y,this.bearing=W,this.g=U,this.canvas=j}o(this.options.init)}function o(t){t&&"function"==typeof t&&t()}var c,n=window.jQuery,r=n(window),a=n(document),p="http://www.w3.org/2000/svg",l="SVGAngle"in window&&function(){var t,i=document.createElement("div");return i.innerHTML="",t=(i.firstChild&&i.firstChild.namespaceURI)==p,i.innerHTML="",t}(),h=function(){var t=document.createElement("div").style;return"transition"in t||"WebkitTransition"in t||"MozTransition"in t||"msTransition"in t||"OTransition"in t}(),u="ontouchstart"in window,k="mousedown"+(u?" touchstart":""),d="mousemove.clockpicker"+(u?" touchmove.clockpicker":""),f="mouseup.clockpicker"+(u?" touchend.clockpicker":""),v=navigator.vibrate?"vibrate":navigator.webkitVibrate?"webkitVibrate":null,m=0,b=100,g=80,w=54,y=13,M=2*b,A=h?350:1,V=['
    ','
    ','
    ',''," : ",'','',"
    ",'
    ','
    ','
    ','
    ','
    ',"
    ",'',"","
    ","
    "].join("");s.DEFAULTS={"default":"",fromnow:0,placement:"bottom",align:"left",donetext:"完成",autoclose:!1,twelvehour:!1,vibrate:!0},s.prototype.toggle=function(){this[this.isShown?"hide":"show"]()},s.prototype.locate=function(){var t=this.element,i=this.popover,e=t.offset(),s=t.outerWidth(),o=t.outerHeight(),c=this.options.placement,n=this.options.align,r={};switch(i.show(),c){case"bottom":r.top=e.top+o;break;case"right":r.left=e.left+s;break;case"top":r.top=e.top-i.outerHeight();break;case"left":r.left=e.left-i.outerWidth()}switch(n){case"left":r.left=e.left;break;case"right":r.left=e.left+s-i.outerWidth();break;case"top":r.top=e.top;break;case"bottom":r.top=e.top+o-i.outerHeight()}i.css(r)},s.prototype.show=function(){if(!this.isShown){o(this.options.beforeShow);var t=this;this.isAppended||(c=n(document.body).append(this.popover),r.on("resize.clockpicker"+this.id,function(){t.isShown&&t.locate()}),this.isAppended=!0);var e=((this.input.prop("value")||this.options["default"]||"")+"").split(":");if("now"===e[0]){var s=new Date(+new Date+this.options.fromnow);e=[s.getHours(),s.getMinutes()]}this.hours=+e[0]||0,this.minutes=+e[1]||0,this.spanHours.html(i(this.hours)),this.spanMinutes.html(i(this.minutes)),this.toggleView("hours"),this.locate(),this.isShown=!0,a.on("click.clockpicker."+this.id+" focusin.clockpicker."+this.id,function(i){var e=n(i.target);0===e.closest(t.popover).length&&0===e.closest(t.addon).length&&0===e.closest(t.input).length&&t.hide()}),a.on("keyup.clockpicker."+this.id,function(i){27===i.keyCode&&t.hide()}),o(this.options.afterShow)}},s.prototype.hide=function(){o(this.options.beforeHide),this.isShown=!1,a.off("click.clockpicker."+this.id+" focusin.clockpicker."+this.id),a.off("keyup.clockpicker."+this.id),this.popover.hide(),o(this.options.afterHide)},s.prototype.toggleView=function(t,i){var e=!1;"minutes"===t&&"visible"===n(this.hoursView).css("visibility")&&(o(this.options.beforeHourSelect),e=!0);var s="hours"===t,c=s?this.hoursView:this.minutesView,r=s?this.minutesView:this.hoursView;this.currentView=t,this.spanHours.toggleClass("text-primary",s),this.spanMinutes.toggleClass("text-primary",!s),r.addClass("clockpicker-dial-out"),c.css("visibility","visible").removeClass("clockpicker-dial-out"),this.resetClock(i),clearTimeout(this.toggleViewTimer),this.toggleViewTimer=setTimeout(function(){r.css("visibility","hidden")},A),e&&o(this.options.afterHourSelect)},s.prototype.resetClock=function(t){var i=this.currentView,e=this[i],s="hours"===i,o=Math.PI/(s?6:30),c=e*o,n=s&&e>0&&13>e?w:g,r=Math.sin(c)*n,a=-Math.cos(c)*n,p=this;l&&t?(p.canvas.addClass("clockpicker-canvas-out"),setTimeout(function(){p.canvas.removeClass("clockpicker-canvas-out"),p.setHand(r,a)},t)):this.setHand(r,a)},s.prototype.setHand=function(t,e,s,o){var c,r=Math.atan2(t,-e),a="hours"===this.currentView,p=Math.PI/(a||s?6:30),h=Math.sqrt(t*t+e*e),u=this.options,k=a&&(g+w)/2>h,d=k?w:g;if(u.twelvehour&&(d=g),0>r&&(r=2*Math.PI+r),c=Math.round(r/p),r=c*p,u.twelvehour?a?0===c&&(c=12):(s&&(c*=5),60===c&&(c=0)):a?(12===c&&(c=0),c=k?0===c?12:c:0===c?0:c+12):(s&&(c*=5),60===c&&(c=0)),this[this.currentView]!==c&&v&&this.options.vibrate&&(this.vibrateTimer||(navigator[v](10),this.vibrateTimer=setTimeout(n.proxy(function(){this.vibrateTimer=null},this),100))),this[this.currentView]=c,this[a?"spanHours":"spanMinutes"].html(i(c)),!l)return void this[a?"hoursView":"minutesView"].find(".clockpicker-tick").each(function(){var t=n(this);t.toggleClass("active",c===+t.html())});o||!a&&c%5?(this.g.insertBefore(this.hand,this.bearing),this.g.insertBefore(this.bg,this.fg),this.bg.setAttribute("class","clockpicker-canvas-bg clockpicker-canvas-bg-trans")):(this.g.insertBefore(this.hand,this.bg),this.g.insertBefore(this.fg,this.bg),this.bg.setAttribute("class","clockpicker-canvas-bg"));var f=Math.sin(r)*d,m=-Math.cos(r)*d;this.hand.setAttribute("x2",f),this.hand.setAttribute("y2",m),this.bg.setAttribute("cx",f),this.bg.setAttribute("cy",m),this.fg.setAttribute("cx",f),this.fg.setAttribute("cy",m)},s.prototype.done=function(){o(this.options.beforeDone),this.hide();var t=this.input.prop("value"),e=i(this.hours)+":"+i(this.minutes);this.options.twelvehour&&(e+=this.amOrPm),this.input.prop("value",e),e!==t&&(this.input.triggerHandler("change"),this.isInput||this.element.trigger("change")),this.options.autoclose&&this.input.trigger("blur"),o(this.options.afterDone)},s.prototype.remove=function(){this.element.removeData("clockpicker"),this.input.off("focus.clockpicker click.clockpicker"),this.addon.off("click.clockpicker"),this.isShown&&this.hide(),this.isAppended&&(r.off("resize.clockpicker"+this.id),this.popover.remove())},n.fn.clockpicker=function(t){var i=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=n(this),o=e.data("clockpicker");if(o)"function"==typeof o[t]&&o[t].apply(o,i);else{var c=n.extend({},s.DEFAULTS,e.data(),"object"==typeof t&&t);e.data("clockpicker",new s(e,c))}})}}(); \ No newline at end of file diff --git a/xadmin/static/xadmin/vendor/bootstrap-datepicker/js/bootstrap-datepicker.js b/xadmin/static/xadmin/vendor/bootstrap-datepicker/js/bootstrap-datepicker.js index 1653b5518..da25ad2d4 100644 --- a/xadmin/static/xadmin/vendor/bootstrap-datepicker/js/bootstrap-datepicker.js +++ b/xadmin/static/xadmin/vendor/bootstrap-datepicker/js/bootstrap-datepicker.js @@ -65,7 +65,7 @@ if (this.isRTL){ this.picker.addClass('datepicker-rtl'); this.picker.find('.prev i, .next i') - .toggleClass('icon-arrow-left icon-arrow-right'); + .toggleClass('fa fa-arrow-left fa-arrow-right'); } this.autoclose = false; @@ -1010,9 +1010,9 @@ }, headTemplate: ''+ ''+ - ''+ + ''+ ''+ - ''+ + ''+ ''+ '', contTemplate: '', diff --git a/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot b/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot new file mode 100755 index 000000000..423bd5d3a Binary files /dev/null and b/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot differ diff --git a/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg b/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg new file mode 100755 index 000000000..446948874 --- /dev/null +++ b/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf b/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf new file mode 100755 index 000000000..a498ef4e7 Binary files /dev/null and b/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf differ diff --git a/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff b/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff new file mode 100755 index 000000000..d83c539b8 Binary files /dev/null and b/xadmin/static/xadmin/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff differ diff --git a/xadmin/static/xadmin/vendor/select2/select2_locale_en.js b/xadmin/static/xadmin/vendor/select2/select2_locale_en.js new file mode 100644 index 000000000..5fb0fa1af --- /dev/null +++ b/xadmin/static/xadmin/vendor/select2/select2_locale_en.js @@ -0,0 +1,15 @@ +/** + * Select2 English translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "No matches found"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " more character" + (n == 1 ? "" : "s"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1 ? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Loading more results..."; }, + formatSearching: function () { return "Searching..."; } + }); +})(jQuery); \ No newline at end of file diff --git a/xadmin/static/xadmin/vendor/select2/select2_locale_zh-hans.js b/xadmin/static/xadmin/vendor/select2/select2_locale_zh-hans.js new file mode 100644 index 000000000..49d8e5994 --- /dev/null +++ b/xadmin/static/xadmin/vendor/select2/select2_locale_zh-hans.js @@ -0,0 +1,14 @@ +/** + * Select2 Chinese translation + */ +(function ($) { + "use strict"; + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "没有找到匹配项"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "请再输入" + n + "个字符";}, + formatInputTooLong: function (input, max) { var n = input.length - max; return "请删掉" + n + "个字符";}, + formatSelectionTooBig: function (limit) { return "你只能选择最多" + limit + "项"; }, + formatLoadMore: function (pageNumber) { return "加载结果中..."; }, + formatSearching: function () { return "搜索中..."; } + }); +})(jQuery); diff --git a/xadmin/static/xadmin/vendor/selectize/selectize.bootstrap2.css b/xadmin/static/xadmin/vendor/selectize/selectize.bootstrap2.css new file mode 100644 index 000000000..16b792cd7 --- /dev/null +++ b/xadmin/static/xadmin/vendor/selectize/selectize.bootstrap2.css @@ -0,0 +1,487 @@ +/** + * selectize.bootstrap2.css (v0.12.1) - Bootstrap 2 Theme + * Copyright (c) 2013–2015 Brian Reavis & contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + * file except in compliance with the License. You may obtain a copy of the License at: + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF + * ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + * + * @author Brian Reavis + */ +.selectize-control.plugin-drag_drop.multi > .selectize-input > div.ui-sortable-placeholder { + visibility: visible !important; + background: #f2f2f2 !important; + background: rgba(0, 0, 0, 0.06) !important; + border: 0 none !important; + -webkit-box-shadow: inset 0 0 12px 4px #ffffff; + box-shadow: inset 0 0 12px 4px #ffffff; +} +.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after { + content: '!'; + visibility: hidden; +} +.selectize-control.plugin-drag_drop .ui-sortable-helper { + -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); +} +.selectize-dropdown-header { + position: relative; + padding: 3px 10px; + border-bottom: 1px solid #d0d0d0; + background: #f8f8f8; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.selectize-dropdown-header-close { + position: absolute; + right: 10px; + top: 50%; + color: #333333; + opacity: 0.4; + margin-top: -12px; + line-height: 20px; + font-size: 20px !important; +} +.selectize-dropdown-header-close:hover { + color: #000000; +} +.selectize-dropdown.plugin-optgroup_columns .optgroup { + border-right: 1px solid #f2f2f2; + border-top: 0 none; + float: left; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child { + border-right: 0 none; +} +.selectize-dropdown.plugin-optgroup_columns .optgroup:before { + display: none; +} +.selectize-dropdown.plugin-optgroup_columns .optgroup-header { + border-top: 0 none; +} +.selectize-control.plugin-remove_button [data-value] { + position: relative; + padding-right: 24px !important; +} +.selectize-control.plugin-remove_button [data-value] .remove { + z-index: 1; + /* fixes ie bug (see #392) */ + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 17px; + text-align: center; + font-weight: bold; + font-size: 12px; + color: inherit; + text-decoration: none; + vertical-align: middle; + display: inline-block; + padding: 1px 0 0 0; + border-left: 1px solid #cccccc; + -webkit-border-radius: 0 2px 2px 0; + -moz-border-radius: 0 2px 2px 0; + border-radius: 0 2px 2px 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.selectize-control.plugin-remove_button [data-value] .remove:hover { + background: rgba(0, 0, 0, 0.05); +} +.selectize-control.plugin-remove_button [data-value].active .remove { + border-left-color: #0077b3; +} +.selectize-control.plugin-remove_button .disabled [data-value] .remove:hover { + background: none; +} +.selectize-control.plugin-remove_button .disabled [data-value] .remove { + border-left-color: #e0e0e0; +} +.selectize-control { + position: relative; +} +.selectize-dropdown, +.selectize-input, +.selectize-input input { + color: #333333; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + -webkit-font-smoothing: inherit; +} +.selectize-input, +.selectize-control.single .selectize-input.input-active { + background: #ffffff; + cursor: text; + display: inline-block; +} +.selectize-input { + border: 1px solid #d0d0d0; + padding: 7px 10px; + display: inline-block; + width: 100%; + overflow: hidden; + position: relative; + z-index: 1; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: none; + box-shadow: none; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.selectize-control.multi .selectize-input.has-items { + padding: 5px 10px 2px; +} +.selectize-input.full { + background-color: #ffffff; +} +.selectize-input.disabled, +.selectize-input.disabled * { + cursor: default !important; +} +.selectize-input.focus { + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); +} +.selectize-input.dropdown-active { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.selectize-input > * { + vertical-align: baseline; + display: -moz-inline-stack; + display: inline-block; + zoom: 1; + *display: inline; +} +.selectize-control.multi .selectize-input > div { + cursor: pointer; + margin: 0 3px 3px 0; + padding: 1px 3px; + background: #e6e6e6; + color: #333333; + border: 1px solid #cccccc; +} +.selectize-control.multi .selectize-input > div.active { + background: #0088cc; + color: #ffffff; + border: 1px solid #0077b3; +} +.selectize-control.multi .selectize-input.disabled > div, +.selectize-control.multi .selectize-input.disabled > div.active { + color: #474747; + background: #fafafa; + border: 1px solid #e0e0e0; +} +.selectize-input > input { + display: inline-block !important; + padding: 0 !important; + min-height: 0 !important; + max-height: none !important; + max-width: 100% !important; + margin: 0 !important; + text-indent: 0 !important; + border: 0 none !important; + background: none !important; + line-height: inherit !important; + -webkit-user-select: auto !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; +} +.selectize-input > input::-ms-clear { + display: none; +} +.selectize-input > input:focus { + outline: none !important; +} +.selectize-input::after { + content: ' '; + display: block; + clear: left; +} +.selectize-input.dropdown-active::before { + content: ' '; + display: block; + position: absolute; + background: #e5e5e5; + height: 1px; + bottom: 0; + left: 0; + right: 0; +} +.selectize-dropdown { + position: absolute; + z-index: 10; + border: 1px solid #cccccc; + background: #ffffff; + margin: -1px 0 0 0; + border-top: 0 none; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} +.selectize-dropdown [data-selectable] { + cursor: pointer; + overflow: hidden; +} +.selectize-dropdown [data-selectable] .highlight { + background: rgba(255, 237, 40, 0.4); + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; +} +.selectize-dropdown [data-selectable], +.selectize-dropdown .optgroup-header { + padding: 3px 10px; +} +.selectize-dropdown .optgroup:first-child .optgroup-header { + border-top: 0 none; +} +.selectize-dropdown .optgroup-header { + color: #999999; + background: #ffffff; + cursor: default; +} +.selectize-dropdown .active { + background-color: #0088cc; + color: #ffffff; +} +.selectize-dropdown .active.create { + color: #ffffff; +} +.selectize-dropdown .create { + color: rgba(51, 51, 51, 0.5); +} +.selectize-dropdown-content { + overflow-y: auto; + overflow-x: hidden; + max-height: 200px; +} +.selectize-control.single .selectize-input, +.selectize-control.single .selectize-input input { + cursor: pointer; +} +.selectize-control.single .selectize-input.input-active, +.selectize-control.single .selectize-input.input-active input { + cursor: text; +} +.selectize-control.single .selectize-input:after { + content: ' '; + display: block; + position: absolute; + top: 50%; + right: 15px; + margin-top: -3px; + width: 0; + height: 0; + border-style: solid; + border-width: 5px 5px 0 5px; + border-color: #000000 transparent transparent transparent; +} +.selectize-control.single .selectize-input.dropdown-active:after { + margin-top: -4px; + border-width: 0 5px 5px 5px; + border-color: transparent transparent #000000 transparent; +} +.selectize-control.rtl.single .selectize-input:after { + left: 15px; + right: auto; +} +.selectize-control.rtl .selectize-input > input { + margin: 0 4px 0 -2px !important; +} +.selectize-control .selectize-input.disabled { + opacity: 0.5; + background-color: #ffffff; +} +.selectize-dropdown { + margin: 2px 0 0 0; + z-index: 1000; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 4px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); +} +.selectize-dropdown .optgroup-header { + font-size: 11px; + font-weight: bold; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase; +} +.selectize-dropdown .optgroup:first-child:before { + display: none; +} +.selectize-dropdown .optgroup:before { + content: ' '; + display: block; + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; + margin-left: -10px; + margin-right: -10px; +} +.selectize-dropdown [data-selectable].active { + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} +.selectize-dropdown-content { + padding: 5px 0; +} +.selectize-dropdown-header { + padding: 6px 10px; +} +.selectize-input { + -webkit-transition: border linear .2s, box-shadow linear .2s; + -moz-transition: border linear .2s, box-shadow linear .2s; + -o-transition: border linear .2s, box-shadow linear .2s; + transition: border linear .2s, box-shadow linear .2s; +} +.selectize-input.dropdown-active { + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.selectize-input.dropdown-active::before { + display: none; +} +.selectize-input.input-active, +.selectize-input.input-active:hover, +.selectize-control.multi .selectize-input.focus { + background: #ffffff !important; + border-color: rgba(82, 168, 236, 0.8) !important; + outline: 0 !important; + outline: thin dotted \9 !important; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6) !important; + -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6) !important; + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6) !important; +} +.selectize-control.single .selectize-input { + color: #333333; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + background-color: #f5f5f5; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #e6e6e6; + /* Darken IE7 buttons by default so they stand out more given they won't have borders */ + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); +} +.selectize-control.single .selectize-input:hover, +.selectize-control.single .selectize-input:focus, +.selectize-control.single .selectize-input:active, +.selectize-control.single .selectize-input.active, +.selectize-control.single .selectize-input.disabled, +.selectize-control.single .selectize-input[disabled] { + color: #333333; + background-color: #e6e6e6; + *background-color: #d9d9d9; +} +.selectize-control.single .selectize-input:active, +.selectize-control.single .selectize-input.active { + background-color: #cccccc \9; +} +.selectize-control.single .selectize-input:hover { + color: #333333; + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} +.selectize-control.single .selectize-input.disabled { + background: #e6e6e6 !important; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.selectize-control.multi .selectize-input { + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.selectize-control.multi .selectize-input.has-items { + padding-left: 7px; + padding-right: 7px; +} +.selectize-control.multi .selectize-input > div { + color: #333333; + text-shadow: none; + background-color: #f5f5f5; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #e6e6e6; + border: 1px solid #cccccc; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); + box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); +} +.selectize-control.multi .selectize-input > div.active { + -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05); + -moz-box-shadow: 0 1px 2px rgba(0,0,0,.05); + box-shadow: 0 1px 2px rgba(0,0,0,.05); + color: #ffffff; + text-shadow: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); + border-color: #0077b3 #0077b3 #004466; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + *background-color: #0088cc; + border: 1px solid #0088cc; +} diff --git a/xadmin/static/xadmin/vendor/selectize/selectize.bootstrap3.css b/xadmin/static/xadmin/vendor/selectize/selectize.bootstrap3.css index f385e3310..cfb2bfa2f 100644 --- a/xadmin/static/xadmin/vendor/selectize/selectize.bootstrap3.css +++ b/xadmin/static/xadmin/vendor/selectize/selectize.bootstrap3.css @@ -1,6 +1,6 @@ /** - * selectize.bootstrap3.css (v0.8.4) - Bootstrap 3 Theme - * Copyright (c) 2013 Brian Reavis & contributors + * selectize.bootstrap3.css (v0.12.1) - Bootstrap 3 Theme + * Copyright (c) 2013–2015 Brian Reavis & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this * file except in compliance with the License. You may obtain a copy of the License at: @@ -13,436 +13,389 @@ * * @author Brian Reavis */ - .selectize-control.plugin-drag_drop.multi > .selectize-input > div.ui-sortable-placeholder { + visibility: visible !important; background: #f2f2f2 !important; background: rgba(0, 0, 0, 0.06) !important; border: 0 none !important; - visibility: visible !important; -webkit-box-shadow: inset 0 0 12px 4px #ffffff; - box-shadow: inset 0 0 12px 4px #ffffff; + box-shadow: inset 0 0 12px 4px #ffffff; } - .selectize-control.plugin-drag_drop .ui-sortable-placeholder::after { content: '!'; visibility: hidden; } - .selectize-control.plugin-drag_drop .ui-sortable-helper { -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } - .selectize-dropdown-header { position: relative; padding: 3px 12px; - background: #f8f8f8; border-bottom: 1px solid #d0d0d0; + background: #f8f8f8; -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; } - .selectize-dropdown-header-close { position: absolute; - top: 50%; right: 12px; - margin-top: -12px; - font-size: 20px !important; - line-height: 20px; + top: 50%; color: #333333; opacity: 0.4; + margin-top: -12px; + line-height: 20px; + font-size: 20px !important; } - .selectize-dropdown-header-close:hover { color: #000000; } - .selectize-dropdown.plugin-optgroup_columns .optgroup { - float: left; - border-top: 0 none; border-right: 1px solid #f2f2f2; + border-top: 0 none; + float: left; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } - .selectize-dropdown.plugin-optgroup_columns .optgroup:last-child { border-right: 0 none; } - .selectize-dropdown.plugin-optgroup_columns .optgroup:before { display: none; } - .selectize-dropdown.plugin-optgroup_columns .optgroup-header { border-top: 0 none; } - .selectize-control.plugin-remove_button [data-value] { position: relative; padding-right: 24px !important; } - .selectize-control.plugin-remove_button [data-value] .remove { + z-index: 1; + /* fixes ie bug (see #392) */ position: absolute; top: 0; right: 0; bottom: 0; - display: inline-block; width: 17px; - padding: 1px 0 0 0; - font-size: 12px; + text-align: center; font-weight: bold; + font-size: 12px; color: inherit; - text-align: center; text-decoration: none; vertical-align: middle; + display: inline-block; + padding: 1px 0 0 0; border-left: 1px solid rgba(0, 0, 0, 0); -webkit-border-radius: 0 2px 2px 0; - -moz-border-radius: 0 2px 2px 0; - border-radius: 0 2px 2px 0; + -moz-border-radius: 0 2px 2px 0; + border-radius: 0 2px 2px 0; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } - .selectize-control.plugin-remove_button [data-value] .remove:hover { background: rgba(0, 0, 0, 0.05); } - .selectize-control.plugin-remove_button [data-value].active .remove { border-left-color: rgba(0, 0, 0, 0); } - .selectize-control.plugin-remove_button .disabled [data-value] .remove:hover { background: none; } - .selectize-control.plugin-remove_button .disabled [data-value] .remove { border-left-color: rgba(77, 77, 77, 0); } - .selectize-control { position: relative; } - .selectize-dropdown, .selectize-input, .selectize-input input { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - -webkit-font-smoothing: inherit; - line-height: 20px; color: #333333; + font-family: inherit; + font-size: inherit; + line-height: 20px; + -webkit-font-smoothing: inherit; } - .selectize-input, .selectize-control.single .selectize-input.input-active { - display: inline-block; - cursor: text; background: #ffffff; + cursor: text; + display: inline-block; } - .selectize-input { - position: relative; - z-index: 1; + border: 1px solid #cccccc; + padding: 6px 12px; display: inline-block; width: 100%; - padding: 6px 12px; overflow: hidden; - border: 1px solid #cccccc; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: none; - box-shadow: none; + position: relative; + z-index: 1; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: none; + box-shadow: none; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; } - .selectize-control.multi .selectize-input.has-items { padding: 5px 12px 2px; } - .selectize-input.full { background-color: #ffffff; } - .selectize-input.disabled, .selectize-input.disabled * { cursor: default !important; } - .selectize-input.focus { -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); } - .selectize-input.dropdown-active { -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; } - .selectize-input > * { + vertical-align: baseline; display: -moz-inline-stack; display: inline-block; - *display: inline; - vertical-align: baseline; zoom: 1; + *display: inline; } - .selectize-control.multi .selectize-input > div { - padding: 1px 3px; - margin: 0 3px 3px 0; - color: #333333; cursor: pointer; + margin: 0 3px 3px 0; + padding: 1px 3px; background: #efefef; + color: #333333; border: 0 solid rgba(0, 0, 0, 0); } - .selectize-control.multi .selectize-input > div.active { - color: #ffffff; background: #428bca; + color: #ffffff; border: 0 solid rgba(0, 0, 0, 0); } - .selectize-control.multi .selectize-input.disabled > div, .selectize-control.multi .selectize-input.disabled > div.active { color: #808080; background: #ffffff; border: 0 solid rgba(77, 77, 77, 0); } - .selectize-input > input { - max-width: 100% !important; - max-height: none !important; - min-height: 0 !important; + display: inline-block !important; padding: 0 !important; + min-height: 0 !important; + max-height: none !important; + max-width: 100% !important; margin: 0 !important; - line-height: inherit !important; text-indent: 0 !important; - background: none !important; border: 0 none !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; + background: none !important; + line-height: inherit !important; -webkit-user-select: auto !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; +} +.selectize-input > input::-ms-clear { + display: none; } - .selectize-input > input:focus { outline: none !important; } - .selectize-input::after { + content: ' '; display: block; clear: left; - content: ' '; } - .selectize-input.dropdown-active::before { + content: ' '; + display: block; position: absolute; - right: 0; + background: #ffffff; + height: 1px; bottom: 0; left: 0; - display: block; - height: 1px; - background: #ffffff; - content: ' '; + right: 0; } - .selectize-dropdown { position: absolute; z-index: 10; - margin: -1px 0 0 0; + border: 1px solid #d0d0d0; background: #ffffff; - border: 1px solid #cccccc; + margin: -1px 0 0 0; border-top: 0 none; - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; } - .selectize-dropdown [data-selectable] { - overflow: hidden; cursor: pointer; + overflow: hidden; } - .selectize-dropdown [data-selectable] .highlight { background: rgba(255, 237, 40, 0.4); -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; } - .selectize-dropdown [data-selectable], .selectize-dropdown .optgroup-header { padding: 3px 12px; } - .selectize-dropdown .optgroup:first-child .optgroup-header { border-top: 0 none; } - .selectize-dropdown .optgroup-header { - color: #999999; - cursor: default; + color: #777777; background: #ffffff; + cursor: default; } - .selectize-dropdown .active { - color: #ffffff; - background-color: #428bca; + background-color: #f5f5f5; + color: #262626; } - .selectize-dropdown .active.create { - color: #ffffff; + color: #262626; } - .selectize-dropdown .create { color: rgba(51, 51, 51, 0.5); } - .selectize-dropdown-content { - max-height: 200px; - overflow-x: hidden; overflow-y: auto; + overflow-x: hidden; + max-height: 200px; } - .selectize-control.single .selectize-input, .selectize-control.single .selectize-input input { cursor: pointer; } - .selectize-control.single .selectize-input.input-active, .selectize-control.single .selectize-input.input-active input { cursor: text; } - .selectize-control.single .selectize-input:after { + content: ' '; + display: block; position: absolute; top: 50%; right: 17px; - display: block; + margin-top: -3px; width: 0; height: 0; - margin-top: -3px; - border-color: #000000 transparent transparent transparent; border-style: solid; border-width: 5px 5px 0 5px; - content: ' '; + border-color: #333333 transparent transparent transparent; } - .selectize-control.single .selectize-input.dropdown-active:after { margin-top: -4px; - border-color: transparent transparent #000000 transparent; border-width: 0 5px 5px 5px; + border-color: transparent transparent #333333 transparent; } - .selectize-control.rtl.single .selectize-input:after { - right: auto; left: 17px; + right: auto; } - .selectize-control.rtl .selectize-input > input { margin: 0 4px 0 -2px !important; } - .selectize-control .selectize-input.disabled { - background-color: #ffffff; opacity: 0.5; + background-color: #ffffff; } - .selectize-dropdown, .selectize-dropdown.form-control { - z-index: 1000; height: auto; padding: 0; margin: 2px 0 0 0; + z-index: 1000; background: #ffffff; border: 1px solid #cccccc; border: 1px solid rgba(0, 0, 0, 0.15); -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); } - .selectize-dropdown .optgroup-header { font-size: 12px; - line-height: 1.428571429; + line-height: 1.42857143; } - .selectize-dropdown .optgroup:first-child:before { display: none; } - .selectize-dropdown .optgroup:before { + content: ' '; display: block; height: 1px; margin: 9px 0; - margin-right: -12px; - margin-left: -12px; overflow: hidden; background-color: #e5e5e5; - content: ' '; + margin-left: -12px; + margin-right: -12px; } - .selectize-dropdown-content { padding: 5px 0; } - .selectize-dropdown-header { padding: 6px 12px; } - .selectize-input { min-height: 34px; } - .selectize-input.dropdown-active { -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; } - .selectize-input.dropdown-active::before { display: none; } - .selectize-input.focus { border-color: #66afe9; outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.has-error .selectize-input { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .selectize-input:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; } - .selectize-control.multi .selectize-input.has-items { - padding-right: 9px; padding-left: 9px; + padding-right: 9px; } - .selectize-control.multi .selectize-input > div { -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; } - .form-control.selectize-control { - height: auto; padding: 0; - background: none; + height: auto; border: none; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; + background: none; -webkit-box-shadow: none; - box-shadow: none; -} \ No newline at end of file + box-shadow: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} diff --git a/xadmin/static/xadmin/vendor/selectize/selectize.css b/xadmin/static/xadmin/vendor/selectize/selectize.css index aab32d5e0..6c3ba0b24 100644 --- a/xadmin/static/xadmin/vendor/selectize/selectize.css +++ b/xadmin/static/xadmin/vendor/selectize/selectize.css @@ -1,6 +1,6 @@ /** - * selectize.css (v0.8.4) - * Copyright (c) 2013 Brian Reavis & contributors + * selectize.css (v0.12.1) + * Copyright (c) 2013–2015 Brian Reavis & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this * file except in compliance with the License. You may obtain a copy of the License at: @@ -15,346 +15,303 @@ */ .selectize-control.plugin-drag_drop.multi > .selectize-input > div.ui-sortable-placeholder { + visibility: visible !important; background: #f2f2f2 !important; background: rgba(0, 0, 0, 0.06) !important; border: 0 none !important; - visibility: visible !important; -webkit-box-shadow: inset 0 0 12px 4px #ffffff; - box-shadow: inset 0 0 12px 4px #ffffff; + box-shadow: inset 0 0 12px 4px #ffffff; } - .selectize-control.plugin-drag_drop .ui-sortable-placeholder::after { content: '!'; visibility: hidden; } - .selectize-control.plugin-drag_drop .ui-sortable-helper { -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } - .selectize-dropdown-header { position: relative; padding: 5px 8px; - background: #f8f8f8; border-bottom: 1px solid #d0d0d0; + background: #f8f8f8; -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; } - .selectize-dropdown-header-close { position: absolute; - top: 50%; right: 8px; - margin-top: -12px; - font-size: 20px !important; - line-height: 20px; + top: 50%; color: #303030; opacity: 0.4; + margin-top: -12px; + line-height: 20px; + font-size: 20px !important; } - .selectize-dropdown-header-close:hover { color: #000000; } - .selectize-dropdown.plugin-optgroup_columns .optgroup { - float: left; - border-top: 0 none; border-right: 1px solid #f2f2f2; + border-top: 0 none; + float: left; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } - .selectize-dropdown.plugin-optgroup_columns .optgroup:last-child { border-right: 0 none; } - .selectize-dropdown.plugin-optgroup_columns .optgroup:before { display: none; } - .selectize-dropdown.plugin-optgroup_columns .optgroup-header { border-top: 0 none; } - .selectize-control.plugin-remove_button [data-value] { position: relative; padding-right: 24px !important; } - .selectize-control.plugin-remove_button [data-value] .remove { + z-index: 1; + /* fixes ie bug (see #392) */ position: absolute; top: 0; right: 0; bottom: 0; - display: inline-block; width: 17px; - padding: 2px 0 0 0; - font-size: 12px; + text-align: center; font-weight: bold; + font-size: 12px; color: inherit; - text-align: center; text-decoration: none; vertical-align: middle; + display: inline-block; + padding: 2px 0 0 0; border-left: 1px solid #d0d0d0; -webkit-border-radius: 0 2px 2px 0; - -moz-border-radius: 0 2px 2px 0; - border-radius: 0 2px 2px 0; + -moz-border-radius: 0 2px 2px 0; + border-radius: 0 2px 2px 0; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } - .selectize-control.plugin-remove_button [data-value] .remove:hover { background: rgba(0, 0, 0, 0.05); } - .selectize-control.plugin-remove_button [data-value].active .remove { border-left-color: #cacaca; } - .selectize-control.plugin-remove_button .disabled [data-value] .remove:hover { background: none; } - .selectize-control.plugin-remove_button .disabled [data-value] .remove { border-left-color: #ffffff; } - .selectize-control { position: relative; } - .selectize-dropdown, .selectize-input, .selectize-input input { + color: #303030; font-family: inherit; font-size: 13px; - -webkit-font-smoothing: inherit; line-height: 18px; - color: #303030; + -webkit-font-smoothing: inherit; } - .selectize-input, .selectize-control.single .selectize-input.input-active { - display: inline-block; - cursor: text; background: #ffffff; + cursor: text; + display: inline-block; } - .selectize-input { - position: relative; - z-index: 1; + border: 1px solid #d0d0d0; + padding: 8px 8px; display: inline-block; width: 100%; - padding: 8px 8px; overflow: hidden; - border: 1px solid #d0d0d0; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + position: relative; + z-index: 1; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; } - .selectize-control.multi .selectize-input.has-items { padding: 6px 8px 3px; } - .selectize-input.full { background-color: #ffffff; } - .selectize-input.disabled, .selectize-input.disabled * { cursor: default !important; } - .selectize-input.focus { -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); } - .selectize-input.dropdown-active { -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; } - .selectize-input > * { + vertical-align: baseline; display: -moz-inline-stack; display: inline-block; - *display: inline; - vertical-align: baseline; zoom: 1; + *display: inline; } - .selectize-control.multi .selectize-input > div { - padding: 2px 6px; - margin: 0 3px 3px 0; - color: #303030; cursor: pointer; + margin: 0 3px 3px 0; + padding: 2px 6px; background: #f2f2f2; + color: #303030; border: 0 solid #d0d0d0; } - .selectize-control.multi .selectize-input > div.active { - color: #303030; background: #e8e8e8; + color: #303030; border: 0 solid #cacaca; } - .selectize-control.multi .selectize-input.disabled > div, .selectize-control.multi .selectize-input.disabled > div.active { color: #7d7d7d; background: #ffffff; border: 0 solid #ffffff; } - .selectize-input > input { - max-width: 100% !important; - max-height: none !important; - min-height: 0 !important; + display: inline-block !important; padding: 0 !important; + min-height: 0 !important; + max-height: none !important; + max-width: 100% !important; margin: 0 2px 0 0 !important; - line-height: inherit !important; text-indent: 0 !important; - background: none !important; border: 0 none !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; + background: none !important; + line-height: inherit !important; -webkit-user-select: auto !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; +} +.selectize-input > input::-ms-clear { + display: none; } - .selectize-input > input:focus { outline: none !important; } - .selectize-input::after { + content: ' '; display: block; clear: left; - content: ' '; } - .selectize-input.dropdown-active::before { + content: ' '; + display: block; position: absolute; - right: 0; + background: #f0f0f0; + height: 1px; bottom: 0; left: 0; - display: block; - height: 1px; - background: #f0f0f0; - content: ' '; + right: 0; } - .selectize-dropdown { position: absolute; z-index: 10; - margin: -1px 0 0 0; - background: #ffffff; border: 1px solid #d0d0d0; + background: #ffffff; + margin: -1px 0 0 0; border-top: 0 none; - -webkit-border-radius: 0 0 3px 3px; - -moz-border-radius: 0 0 3px 3px; - border-radius: 0 0 3px 3px; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; } - .selectize-dropdown [data-selectable] { - overflow: hidden; cursor: pointer; + overflow: hidden; } - .selectize-dropdown [data-selectable] .highlight { background: rgba(125, 168, 208, 0.2); -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; } - .selectize-dropdown [data-selectable], .selectize-dropdown .optgroup-header { padding: 5px 8px; } - .selectize-dropdown .optgroup:first-child .optgroup-header { border-top: 0 none; } - .selectize-dropdown .optgroup-header { color: #303030; - cursor: default; background: #ffffff; + cursor: default; } - .selectize-dropdown .active { - color: #495c68; background-color: #f5fafd; + color: #495c68; } - .selectize-dropdown .active.create { color: #495c68; } - .selectize-dropdown .create { color: rgba(48, 48, 48, 0.5); } - .selectize-dropdown-content { - max-height: 200px; - overflow-x: hidden; overflow-y: auto; + overflow-x: hidden; + max-height: 200px; } - .selectize-control.single .selectize-input, .selectize-control.single .selectize-input input { cursor: pointer; } - .selectize-control.single .selectize-input.input-active, .selectize-control.single .selectize-input.input-active input { cursor: text; } - .selectize-control.single .selectize-input:after { + content: ' '; + display: block; position: absolute; top: 50%; right: 15px; - display: block; + margin-top: -3px; width: 0; height: 0; - margin-top: -3px; - border-color: #808080 transparent transparent transparent; border-style: solid; border-width: 5px 5px 0 5px; - content: ' '; + border-color: #808080 transparent transparent transparent; } - .selectize-control.single .selectize-input.dropdown-active:after { margin-top: -4px; - border-color: transparent transparent #808080 transparent; border-width: 0 5px 5px 5px; + border-color: transparent transparent #808080 transparent; } - .selectize-control.rtl.single .selectize-input:after { - right: auto; left: 15px; + right: auto; } - .selectize-control.rtl .selectize-input > input { margin: 0 4px 0 -2px !important; } - .selectize-control .selectize-input.disabled { - background-color: #fafafa; opacity: 0.5; -} \ No newline at end of file + background-color: #fafafa; +} diff --git a/xadmin/static/xadmin/vendor/selectize/selectize.default.css b/xadmin/static/xadmin/vendor/selectize/selectize.default.css index cfdc0151d..ffd219c46 100644 --- a/xadmin/static/xadmin/vendor/selectize/selectize.default.css +++ b/xadmin/static/xadmin/vendor/selectize/selectize.default.css @@ -1,6 +1,6 @@ /** - * selectize.default.css (v0.8.4) - Default Theme - * Copyright (c) 2013 Brian Reavis & contributors + * selectize.default.css (v0.12.1) - Default Theme + * Copyright (c) 2013–2015 Brian Reavis & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this * file except in compliance with the License. You may obtain a copy of the License at: @@ -13,376 +13,330 @@ * * @author Brian Reavis */ - .selectize-control.plugin-drag_drop.multi > .selectize-input > div.ui-sortable-placeholder { + visibility: visible !important; background: #f2f2f2 !important; background: rgba(0, 0, 0, 0.06) !important; border: 0 none !important; - visibility: visible !important; -webkit-box-shadow: inset 0 0 12px 4px #ffffff; - box-shadow: inset 0 0 12px 4px #ffffff; + box-shadow: inset 0 0 12px 4px #ffffff; } - .selectize-control.plugin-drag_drop .ui-sortable-placeholder::after { content: '!'; visibility: hidden; } - .selectize-control.plugin-drag_drop .ui-sortable-helper { -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } - .selectize-dropdown-header { position: relative; padding: 5px 8px; - background: #f8f8f8; border-bottom: 1px solid #d0d0d0; + background: #f8f8f8; -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; } - .selectize-dropdown-header-close { position: absolute; - top: 50%; right: 8px; - margin-top: -12px; - font-size: 20px !important; - line-height: 20px; + top: 50%; color: #303030; opacity: 0.4; + margin-top: -12px; + line-height: 20px; + font-size: 20px !important; } - .selectize-dropdown-header-close:hover { color: #000000; } - .selectize-dropdown.plugin-optgroup_columns .optgroup { - float: left; - border-top: 0 none; border-right: 1px solid #f2f2f2; + border-top: 0 none; + float: left; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } - .selectize-dropdown.plugin-optgroup_columns .optgroup:last-child { border-right: 0 none; } - .selectize-dropdown.plugin-optgroup_columns .optgroup:before { display: none; } - .selectize-dropdown.plugin-optgroup_columns .optgroup-header { border-top: 0 none; } - .selectize-control.plugin-remove_button [data-value] { position: relative; padding-right: 24px !important; } - .selectize-control.plugin-remove_button [data-value] .remove { + z-index: 1; + /* fixes ie bug (see #392) */ position: absolute; top: 0; right: 0; bottom: 0; - display: inline-block; width: 17px; - padding: 2px 0 0 0; - font-size: 12px; + text-align: center; font-weight: bold; + font-size: 12px; color: inherit; - text-align: center; text-decoration: none; vertical-align: middle; + display: inline-block; + padding: 2px 0 0 0; border-left: 1px solid #0073bb; -webkit-border-radius: 0 2px 2px 0; - -moz-border-radius: 0 2px 2px 0; - border-radius: 0 2px 2px 0; + -moz-border-radius: 0 2px 2px 0; + border-radius: 0 2px 2px 0; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } - .selectize-control.plugin-remove_button [data-value] .remove:hover { background: rgba(0, 0, 0, 0.05); } - .selectize-control.plugin-remove_button [data-value].active .remove { border-left-color: #00578d; } - .selectize-control.plugin-remove_button .disabled [data-value] .remove:hover { background: none; } - .selectize-control.plugin-remove_button .disabled [data-value] .remove { border-left-color: #aaaaaa; } - .selectize-control { position: relative; } - .selectize-dropdown, .selectize-input, .selectize-input input { + color: #303030; font-family: inherit; font-size: 13px; - -webkit-font-smoothing: inherit; line-height: 18px; - color: #303030; + -webkit-font-smoothing: inherit; } - .selectize-input, .selectize-control.single .selectize-input.input-active { - display: inline-block; - cursor: text; background: #ffffff; + cursor: text; + display: inline-block; } - .selectize-input { - position: relative; - z-index: 1; + border: 1px solid #d0d0d0; + padding: 8px 8px; display: inline-block; width: 100%; - padding: 8px 8px; overflow: hidden; - border: 1px solid #d0d0d0; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + position: relative; + z-index: 1; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; } - .selectize-control.multi .selectize-input.has-items { padding: 5px 8px 2px; } - .selectize-input.full { background-color: #ffffff; } - .selectize-input.disabled, .selectize-input.disabled * { cursor: default !important; } - .selectize-input.focus { -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); } - .selectize-input.dropdown-active { -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; } - .selectize-input > * { + vertical-align: baseline; display: -moz-inline-stack; display: inline-block; - *display: inline; - vertical-align: baseline; zoom: 1; + *display: inline; } - .selectize-control.multi .selectize-input > div { - padding: 2px 6px; - margin: 0 3px 3px 0; - color: #ffffff; cursor: pointer; + margin: 0 3px 3px 0; + padding: 2px 6px; background: #1da7ee; + color: #ffffff; border: 1px solid #0073bb; } - .selectize-control.multi .selectize-input > div.active { - color: #ffffff; background: #92c836; + color: #ffffff; border: 1px solid #00578d; } - .selectize-control.multi .selectize-input.disabled > div, .selectize-control.multi .selectize-input.disabled > div.active { color: #ffffff; background: #d2d2d2; border: 1px solid #aaaaaa; } - .selectize-input > input { - max-width: 100% !important; - max-height: none !important; - min-height: 0 !important; + display: inline-block !important; padding: 0 !important; + min-height: 0 !important; + max-height: none !important; + max-width: 100% !important; margin: 0 1px !important; - line-height: inherit !important; text-indent: 0 !important; - background: none !important; border: 0 none !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; + background: none !important; + line-height: inherit !important; -webkit-user-select: auto !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; +} +.selectize-input > input::-ms-clear { + display: none; } - .selectize-input > input:focus { outline: none !important; } - .selectize-input::after { + content: ' '; display: block; clear: left; - content: ' '; } - .selectize-input.dropdown-active::before { + content: ' '; + display: block; position: absolute; - right: 0; + background: #f0f0f0; + height: 1px; bottom: 0; left: 0; - display: block; - height: 1px; - background: #f0f0f0; - content: ' '; + right: 0; } - .selectize-dropdown { position: absolute; z-index: 10; - margin: -1px 0 0 0; - background: #ffffff; border: 1px solid #d0d0d0; + background: #ffffff; + margin: -1px 0 0 0; border-top: 0 none; - -webkit-border-radius: 0 0 3px 3px; - -moz-border-radius: 0 0 3px 3px; - border-radius: 0 0 3px 3px; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; } - .selectize-dropdown [data-selectable] { - overflow: hidden; cursor: pointer; + overflow: hidden; } - .selectize-dropdown [data-selectable] .highlight { background: rgba(125, 168, 208, 0.2); -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; } - .selectize-dropdown [data-selectable], .selectize-dropdown .optgroup-header { padding: 5px 8px; } - .selectize-dropdown .optgroup:first-child .optgroup-header { border-top: 0 none; } - .selectize-dropdown .optgroup-header { color: #303030; - cursor: default; background: #ffffff; + cursor: default; } - .selectize-dropdown .active { - color: #495c68; background-color: #f5fafd; + color: #495c68; } - .selectize-dropdown .active.create { color: #495c68; } - .selectize-dropdown .create { color: rgba(48, 48, 48, 0.5); } - .selectize-dropdown-content { - max-height: 200px; - overflow-x: hidden; overflow-y: auto; + overflow-x: hidden; + max-height: 200px; } - .selectize-control.single .selectize-input, .selectize-control.single .selectize-input input { cursor: pointer; } - .selectize-control.single .selectize-input.input-active, .selectize-control.single .selectize-input.input-active input { cursor: text; } - .selectize-control.single .selectize-input:after { + content: ' '; + display: block; position: absolute; top: 50%; right: 15px; - display: block; + margin-top: -3px; width: 0; height: 0; - margin-top: -3px; - border-color: #808080 transparent transparent transparent; border-style: solid; border-width: 5px 5px 0 5px; - content: ' '; + border-color: #808080 transparent transparent transparent; } - .selectize-control.single .selectize-input.dropdown-active:after { margin-top: -4px; - border-color: transparent transparent #808080 transparent; border-width: 0 5px 5px 5px; + border-color: transparent transparent #808080 transparent; } - .selectize-control.rtl.single .selectize-input:after { - right: auto; left: 15px; + right: auto; } - .selectize-control.rtl .selectize-input > input { margin: 0 4px 0 -2px !important; } - .selectize-control .selectize-input.disabled { - background-color: #fafafa; opacity: 0.5; + background-color: #fafafa; } - .selectize-control.multi .selectize-input.has-items { - padding-right: 5px; padding-left: 5px; + padding-right: 5px; } - .selectize-control.multi .selectize-input.disabled [data-value] { color: #999; text-shadow: none; background: none; -webkit-box-shadow: none; - box-shadow: none; + box-shadow: none; } - .selectize-control.multi .selectize-input.disabled [data-value], .selectize-control.multi .selectize-input.disabled [data-value] .remove { border-color: #e6e6e6; } - .selectize-control.multi .selectize-input.disabled [data-value] .remove { background: none; } - .selectize-control.multi .selectize-input [data-value] { text-shadow: 0 1px 0 rgba(0, 51, 83, 0.3); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; background-color: #1b9dec; background-image: -moz-linear-gradient(top, #1da7ee, #178ee9); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#1da7ee), to(#178ee9)); @@ -390,14 +344,10 @@ background-image: -o-linear-gradient(top, #1da7ee, #178ee9); background-image: linear-gradient(to bottom, #1da7ee, #178ee9); background-repeat: repeat-x; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff1da7ee', endColorstr='#ff178ee9', GradientType=0); - -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), inset 0 1px rgba(255, 255, 255, 0.03); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), inset 0 1px rgba(255, 255, 255, 0.03); + -webkit-box-shadow: 0 1px 0 rgba(0,0,0,0.2),inset 0 1px rgba(255,255,255,0.03); + box-shadow: 0 1px 0 rgba(0,0,0,0.2),inset 0 1px rgba(255,255,255,0.03); } - .selectize-control.multi .selectize-input [data-value].active { background-color: #0085d4; background-image: -moz-linear-gradient(top, #008fd8, #0075cf); @@ -408,8 +358,9 @@ background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff008fd8', endColorstr='#ff0075cf', GradientType=0); } - .selectize-control.single .selectize-input { + -webkit-box-shadow: 0 1px 0 rgba(0,0,0,0.05), inset 0 1px 0 rgba(255,255,255,0.8); + box-shadow: 0 1px 0 rgba(0,0,0,0.05), inset 0 1px 0 rgba(255,255,255,0.8); background-color: #f9f9f9; background-image: -moz-linear-gradient(top, #fefefe, #f2f2f2); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fefefe), to(#f2f2f2)); @@ -418,25 +369,19 @@ background-image: linear-gradient(to bottom, #fefefe, #f2f2f2); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffefefe', endColorstr='#fff2f2f2', GradientType=0); - -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.8); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.8); } - .selectize-control.single .selectize-input, .selectize-dropdown.single { border-color: #b8b8b8; } - .selectize-dropdown .optgroup-header { padding-top: 7px; - font-size: 0.85em; font-weight: bold; + font-size: 0.85em; } - .selectize-dropdown .optgroup { border-top: 1px solid #f0f0f0; } - .selectize-dropdown .optgroup:first-child { border-top: 0 none; -} \ No newline at end of file +} diff --git a/xadmin/static/xadmin/vendor/selectize/selectize.js b/xadmin/static/xadmin/vendor/selectize/selectize.js index 28d56bbc9..e8c091408 100644 --- a/xadmin/static/xadmin/vendor/selectize/selectize.js +++ b/xadmin/static/xadmin/vendor/selectize/selectize.js @@ -16,7 +16,7 @@ (function(root, factory) { if (typeof define === 'function' && define.amd) { - define(factory); + define('sifter', factory); } else if (typeof exports === 'object') { module.exports = factory(); } else { @@ -221,7 +221,7 @@ * @param {object} result * @return {mixed} */ - get_field = function(name, result) { + get_field = function(name, result) { if (name === '$score') return result.score; return self.items[result.id][name]; }; @@ -391,8 +391,8 @@ if (typeof a === 'number' && typeof b === 'number') { return a > b ? 1 : (a < b ? -1 : 0); } - a = String(a || '').toLowerCase(); - b = String(b || '').toLowerCase(); + a = asciifold(String(a || '')); + b = asciifold(String(b || '')); if (a > b) return 1; if (b > a) return -1; return 0; @@ -425,19 +425,44 @@ }; var DIACRITICS = { - 'a': '[aÀÁÂÃÄÅàáâãäå]', + 'a': '[aÀÁÂÃÄÅàáâãäåĀāąĄ]', 'c': '[cÇçćĆčČ]', - 'd': '[dđĐ]', - 'e': '[eÈÉÊËèéêë]', - 'i': '[iÌÍÎÏìíîï]', - 'n': '[nÑñ]', - 'o': '[oÒÓÔÕÕÖØòóôõöø]', - 's': '[sŠš]', - 'u': '[uÙÚÛÜùúûü]', - 'y': '[yŸÿý]', - 'z': '[zŽž]' + 'd': '[dđĐďĎ]', + 'e': '[eÈÉÊËèéêëěĚĒēęĘ]', + 'i': '[iÌÍÎÏìíîïĪī]', + 'l': '[lłŁ]', + 'n': '[nÑñňŇńŃ]', + 'o': '[oÒÓÔÕÕÖØòóôõöøŌō]', + 'r': '[rřŘ]', + 's': '[sŠšśŚ]', + 't': '[tťŤ]', + 'u': '[uÙÚÛÜùúûüůŮŪū]', + 'y': '[yŸÿýÝ]', + 'z': '[zŽžżŻźŹ]' }; + var asciifold = (function() { + var i, n, k, chunk; + var foreignletters = ''; + var lookup = {}; + for (k in DIACRITICS) { + if (DIACRITICS.hasOwnProperty(k)) { + chunk = DIACRITICS[k].substring(2, DIACRITICS[k].length - 1); + foreignletters += chunk; + for (i = 0, n = chunk.length; i < n; i++) { + lookup[chunk.charAt(i)] = k; + } + } + } + var regexp = new RegExp('[' + foreignletters + ']', 'g'); + return function(str) { + return str.replace(regexp, function(foreignletter) { + return lookup[foreignletter]; + }).toLowerCase(); + }; + })(); + + // export // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -464,7 +489,7 @@ (function(root, factory) { if (typeof define === 'function' && define.amd) { - define(factory); + define('microplugin', factory); } else if (typeof exports === 'object') { module.exports = factory(); } else { @@ -583,8 +608,8 @@ })); /** - * selectize.js (v0.8.4) - * Copyright (c) 2013 Brian Reavis & contributors + * selectize.js (v0.12.1) + * Copyright (c) 2013–2015 Brian Reavis & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this * file except in compliance with the License. You may obtain a copy of the License at: @@ -603,7 +628,9 @@ (function(root, factory) { if (typeof define === 'function' && define.amd) { - define(['jquery','sifter','microplugin'], factory); + define('selectize', ['jquery','sifter','microplugin'], factory); + } else if (typeof exports === 'object') { + module.exports = factory(require('jquery'), require('sifter'), require('microplugin')); } else { root.Selectize = factory(root.jQuery, root.Sifter, root.MicroPlugin); } @@ -689,8 +716,10 @@ var KEY_ESC = 27; var KEY_LEFT = 37; var KEY_UP = 38; + var KEY_P = 80; var KEY_RIGHT = 39; var KEY_DOWN = 40; + var KEY_N = 78; var KEY_BACKSPACE = 8; var KEY_DELETE = 46; var KEY_SHIFT = 16; @@ -701,6 +730,9 @@ var TAG_SELECT = 1; var TAG_INPUT = 2; + // for now, android support in general is too spotty to support validity + var SUPPORTS_VALIDITY_API = !/android/i.test(window.navigator.userAgent) && !!document.createElement('form').validity; + var isset = function(object) { return typeof object !== 'undefined'; }; @@ -719,10 +751,10 @@ * 1 -> '1' * * @param {string} value - * @returns {string} + * @returns {string|null} */ var hash_key = function(value) { - if (typeof value === 'undefined' || value === null) return ''; + if (typeof value === 'undefined' || value === null) return null; if (typeof value === 'boolean') return value ? '1' : '0'; return value + ''; }; @@ -786,25 +818,6 @@ }; }; - /** - * Builds a hash table out of an array of - * objects, using the specified `key` within - * each object. - * - * @param {string} key - * @param {mixed} objects - */ - var build_hash_table = function(key, objects) { - if (!$.isArray(objects)) return objects; - var i, n, table = {}; - for (i = 0, n = objects.length; i < n; i++) { - if (objects[i].hasOwnProperty(key)) { - table[objects[i][key]] = objects[i]; - } - } - return table; - }; - /** * Wraps `fn` so that it can only be invoked once. * @@ -947,6 +960,10 @@ * @returns {int} */ var measureString = function(str, $parent) { + if (!str) { + return 0; + } + var $test = $('').css({ position: 'absolute', top: -99999, @@ -980,13 +997,16 @@ * @param {object} $input */ var autoGrow = function($input) { - var update = function(e) { + var currentWidth = null; + + var update = function(e, options) { var value, keyCode, printable, placeholder, width; var shift, character, selection; e = e || window.event || {}; + options = options || {}; if (e.metaKey || e.altKey) return; - if ($input.data('grow') === false) return; + if (!options.force && $input.data('grow') === false) return; value = $input.val(); if (e.type && e.type.toLowerCase() === 'keydown') { @@ -1016,13 +1036,14 @@ } } - placeholder = $input.attr('placeholder') || ''; - if (!value.length && placeholder.length) { + placeholder = $input.attr('placeholder'); + if (!value && placeholder) { value = placeholder; } width = measureString(value, $input) + 4; - if (width !== $input.width()) { + if (width !== currentWidth) { + currentWidth = width; $input.width(width); $input.triggerHandler('resize'); } @@ -1038,13 +1059,16 @@ input.selectize = self; // detect rtl environment - dir = window.getComputedStyle ? window.getComputedStyle(input, null).getPropertyValue('direction') : input.currentStyle && input.currentStyle.direction; + var computedStyle = window.getComputedStyle && window.getComputedStyle(input, null); + dir = computedStyle ? computedStyle.getPropertyValue('direction') : input.currentStyle && input.currentStyle.direction; dir = dir || $input.parents('[dir]:first').attr('dir') || ''; // setup default state $.extend(self, { + order : 0, settings : settings, $input : $input, + tabIndex : $input.attr('tabindex') || '', tagType : input.tagName.toLowerCase() === 'select' ? TAG_SELECT : TAG_INPUT, rtl : /rtl/i.test(dir), @@ -1062,6 +1086,7 @@ isCmdDown : false, isCtrlDown : false, ignoreFocus : false, + ignoreBlur : false, ignoreHover : false, hasOptions : false, currentResults : null, @@ -1078,19 +1103,27 @@ userOptions : {}, items : [], renderCache : {}, - onSearchChange : debounce(self.onSearchChange, settings.loadThrottle) + onSearchChange : settings.loadThrottle === null ? self.onSearchChange : debounce(self.onSearchChange, settings.loadThrottle) }); // search system self.sifter = new Sifter(this.options, {diacritics: settings.diacritics}); // build options table - $.extend(self.options, build_hash_table(settings.valueField, settings.options)); - delete self.settings.options; + if (self.settings.options) { + for (i = 0, n = self.settings.options.length; i < n; i++) { + self.registerOption(self.settings.options[i]); + } + delete self.settings.options; + } // build optgroup table - $.extend(self.optgroups, build_hash_table(settings.optgroupValueField, settings.optgroups)); - delete self.settings.optgroups; + if (self.settings.optgroups) { + for (i = 0, n = self.settings.optgroups.length; i < n; i++) { + self.registerOptionGroup(self.settings.optgroups[i]); + } + delete self.settings.optgroups; + } // option-dependent defaults self.settings.mode = self.settings.mode || (self.settings.maxItems === 1 ? 'single' : 'multi'); @@ -1124,6 +1157,7 @@ var eventNS = self.eventNS; var $window = $(window); var $document = $(document); + var $input = self.$input; var $wrapper; var $control; @@ -1134,23 +1168,25 @@ var inputMode; var timeout_blur; var timeout_focus; - var tab_index; var classes; var classes_plugins; inputMode = self.settings.mode; - tab_index = self.$input.attr('tabindex') || ''; - classes = self.$input.attr('class') || ''; + classes = $input.attr('class') || ''; $wrapper = $('
    ').addClass(settings.wrapperClass).addClass(classes).addClass(inputMode); $control = $('
    ').addClass(settings.inputClass).addClass('items').appendTo($wrapper); - $control_input = $('').appendTo($control).attr('tabindex', tab_index); + $control_input = $('').appendTo($control).attr('tabindex', $input.is(':disabled') ? '-1' : self.tabIndex); $dropdown_parent = $(settings.dropdownParent || $wrapper); - $dropdown = $('
    ').addClass(settings.dropdownClass).addClass(classes).addClass(inputMode).hide().appendTo($dropdown_parent); + $dropdown = $('
    ').addClass(settings.dropdownClass).addClass(inputMode).hide().appendTo($dropdown_parent); $dropdown_content = $('
    ').addClass(settings.dropdownContentClass).appendTo($dropdown); + if(self.settings.copyClassesToDropdown) { + $dropdown.addClass(classes); + } + $wrapper.css({ - width: self.$input[0].style.width + width: $input[0].style.width }); if (self.plugins.names.length) { @@ -1160,13 +1196,27 @@ } if ((settings.maxItems === null || settings.maxItems > 1) && self.tagType === TAG_SELECT) { - self.$input.attr('multiple', 'multiple'); + $input.attr('multiple', 'multiple'); } if (self.settings.placeholder) { $control_input.attr('placeholder', settings.placeholder); } + // if splitOn was not passed in, construct it from the delimiter to allow pasting universally + if (!self.settings.splitOn && self.settings.delimiter) { + var delimiterEscaped = self.settings.delimiter.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + self.settings.splitOn = new RegExp('\\s*' + delimiterEscaped + '+\\s*'); + } + + if ($input.attr('autocorrect')) { + $control_input.attr('autocorrect', $input.attr('autocorrect')); + } + + if ($input.attr('autocapitalize')) { + $control_input.attr('autocapitalize', $input.attr('autocapitalize')); + } + self.$wrapper = $wrapper; self.$control = $control; self.$control_input = $control_input; @@ -1174,7 +1224,7 @@ self.$dropdown_content = $dropdown_content; $dropdown.on('mouseenter', '[data-selectable]', function() { return self.onOptionHover.apply(self, arguments); }); - $dropdown.on('mousedown', '[data-selectable]', function() { return self.onOptionSelect.apply(self, arguments); }); + $dropdown.on('mousedown click', '[data-selectable]', function() { return self.onOptionSelect.apply(self, arguments); }); watchChildEvent($control, 'mousedown', '*:not(input)', function() { return self.onItemSelect.apply(self, arguments); }); autoGrow($control_input); @@ -1190,7 +1240,8 @@ keypress : function() { return self.onKeyPress.apply(self, arguments); }, resize : function() { self.positionDropdown.apply(self, []); }, blur : function() { return self.onBlur.apply(self, arguments); }, - focus : function() { return self.onFocus.apply(self, arguments); } + focus : function() { self.ignoreBlur = false; return self.onFocus.apply(self, arguments); }, + paste : function() { return self.onPaste.apply(self, arguments); } }); $document.on('keydown' + eventNS, function(e) { @@ -1213,7 +1264,7 @@ } // blur on click outside if (!self.$control.has(e.target).length && e.target !== self.$control[0]) { - self.blur(); + self.blur(e.target); } } }); @@ -1230,11 +1281,11 @@ // store original children and tab index so that they can be // restored when the destroy() method is called. this.revertSettings = { - $children : self.$input.children().detach(), - tabindex : self.$input.attr('tabindex') + $children : $input.children().detach(), + tabindex : $input.attr('tabindex') }; - self.$input.attr('tabindex', -1).hide().after(self.$wrapper); + $input.attr('tabindex', -1).hide().after(self.$wrapper); if ($.isArray(settings.items)) { self.setValue(settings.items); @@ -1242,8 +1293,8 @@ } // feature detect for the validation API - if (self.$input[0].validity) { - self.$input.on('invalid' + eventNS, function(e) { + if (SUPPORTS_VALIDITY_API) { + $input.on('invalid' + eventNS, function(e) { e.preventDefault(); self.isInvalid = true; self.refreshState(); @@ -1256,17 +1307,21 @@ self.updatePlaceholder(); self.isSetup = true; - if (self.$input.is(':disabled')) { + if ($input.is(':disabled')) { self.disable(); } self.on('change', this.onChange); + + $input.data('selectize', self); + $input.addClass('selectized'); self.trigger('initialize'); // preload options - if (settings.preload) { + if (settings.preload === true) { self.onSearchChange(''); } + }, /** @@ -1304,17 +1359,23 @@ */ setupCallbacks: function() { var key, fn, callbacks = { - 'initialize' : 'onInitialize', - 'change' : 'onChange', - 'item_add' : 'onItemAdd', - 'item_remove' : 'onItemRemove', - 'clear' : 'onClear', - 'option_add' : 'onOptionAdd', - 'option_remove' : 'onOptionRemove', - 'option_clear' : 'onOptionClear', - 'dropdown_open' : 'onDropdownOpen', - 'dropdown_close' : 'onDropdownClose', - 'type' : 'onType' + 'initialize' : 'onInitialize', + 'change' : 'onChange', + 'item_add' : 'onItemAdd', + 'item_remove' : 'onItemRemove', + 'clear' : 'onClear', + 'option_add' : 'onOptionAdd', + 'option_remove' : 'onOptionRemove', + 'option_clear' : 'onOptionClear', + 'optgroup_add' : 'onOptionGroupAdd', + 'optgroup_remove' : 'onOptionGroupRemove', + 'optgroup_clear' : 'onOptionGroupClear', + 'dropdown_open' : 'onDropdownOpen', + 'dropdown_close' : 'onDropdownClose', + 'type' : 'onType', + 'load' : 'onLoad', + 'focus' : 'onFocus', + 'blur' : 'onBlur' }; for (key in callbacks) { @@ -1387,6 +1448,30 @@ this.$input.trigger('change'); }, + /** + * Triggered on paste. + * + * @param {object} e + * @returns {boolean} + */ + onPaste: function(e) { + var self = this; + if (self.isFull() || self.isInputHidden || self.isLocked) { + e.preventDefault(); + } else { + // If a regex or string is included, this will split the pasted + // input and create Items for each separate value + if (self.settings.splitOn) { + setTimeout(function() { + var splitInput = $.trim(self.$control_input.val() || '').split(self.settings.splitOn); + for (var i = 0, n = splitInput.length; i < n; i++) { + self.createItem(splitInput[i]); + } + }, 0); + } + } + }, + /** * Triggered on keypress. * @@ -1396,7 +1481,7 @@ onKeyPress: function(e) { if (this.isLocked) return e && e.preventDefault(); var character = String.fromCharCode(e.keyCode || e.which); - if (this.settings.create && character === this.settings.delimiter) { + if (this.settings.create && this.settings.mode === 'multi' && character === this.settings.delimiter) { this.createItem(); e.preventDefault(); return false; @@ -1428,8 +1513,14 @@ } break; case KEY_ESC: - self.close(); + if (self.isOpen) { + e.preventDefault(); + e.stopPropagation(); + self.close(); + } return; + case KEY_N: + if (!e.ctrlKey || e.altKey) break; case KEY_DOWN: if (!self.isOpen && self.hasOptions) { self.open(); @@ -1440,6 +1531,8 @@ } e.preventDefault(); return; + case KEY_P: + if (!e.ctrlKey || e.altKey) break; case KEY_UP: if (self.$activeOption) { self.ignoreHover = true; @@ -1451,8 +1544,8 @@ case KEY_RETURN: if (self.isOpen && self.$activeOption) { self.onOptionSelect({currentTarget: self.$activeOption}); + e.preventDefault(); } - e.preventDefault(); return; case KEY_LEFT: self.advanceSelection(-1, e); @@ -1461,6 +1554,15 @@ self.advanceSelection(1, e); return; case KEY_TAB: + if (self.settings.selectOnTab && self.isOpen && self.$activeOption) { + self.onOptionSelect({currentTarget: self.$activeOption}); + + // Default behaviour is to jump to the next field, we only want this + // if the current field doesn't accept any more entries + if (!self.isFull()) { + e.preventDefault(); + } + } if (self.settings.create && self.createItem()) { e.preventDefault(); } @@ -1470,7 +1572,8 @@ self.deleteSelection(e); return; } - if (self.isFull() || self.isInputHidden) { + + if ((self.isFull() || self.isInputHidden) && !(IS_MAC ? e.metaKey : e.ctrlKey)) { e.preventDefault(); return; } @@ -1522,8 +1625,8 @@ */ onFocus: function(e) { var self = this; + var wasFocused = self.isFocused; - self.isFocused = true; if (self.isDisabled) { self.blur(); e && e.preventDefault(); @@ -1531,8 +1634,11 @@ } if (self.ignoreFocus) return; + self.isFocused = true; if (self.settings.preload === 'focus') self.onSearchChange(''); + if (!wasFocused) self.trigger('focus'); + if (!self.$activeItems.length) { self.showInput(); self.setActiveItem(null); @@ -1546,23 +1652,43 @@ * Triggered on blur. * * @param {object} e - * @returns {boolean} + * @param {Element} dest */ - onBlur: function(e) { + onBlur: function(e, dest) { var self = this; + if (!self.isFocused) return; self.isFocused = false; - if (self.ignoreFocus) return; - if (self.settings.create && self.settings.createOnBlur) { - self.createItem(); + if (self.ignoreFocus) { + return; + } else if (!self.ignoreBlur && document.activeElement === self.$dropdown_content[0]) { + // necessary to prevent IE closing the dropdown when the scrollbar is clicked + self.ignoreBlur = true; + self.onFocus(e); + return; } - self.close(); - self.setTextboxValue(''); - self.setActiveItem(null); - self.setActiveOption(null); - self.setCaret(self.items.length); - self.refreshState(); + var deactivate = function() { + self.close(); + self.setTextboxValue(''); + self.setActiveItem(null); + self.setActiveOption(null); + self.setCaret(self.items.length); + self.refreshState(); + + // IE11 bug: element still marked as active + (dest || document.body).focus(); + + self.ignoreFocus = false; + self.trigger('blur'); + }; + + self.ignoreFocus = true; + if (self.settings.create && self.settings.createOnBlur) { + self.createItem(null, false, deactivate); + } else { + deactivate(); + } }, /** @@ -1594,14 +1720,20 @@ $target = $(e.currentTarget); if ($target.hasClass('create')) { - self.createItem(); + self.createItem(null, function() { + if (self.settings.closeAfterSelect) { + self.close(); + } + }); } else { value = $target.attr('data-value'); - if (value) { + if (typeof value !== 'undefined') { self.lastQuery = null; self.setTextboxValue(''); self.addItem(value); - if (!self.settings.hideSelected && e.type && /mouse/.test(e.type)) { + if (self.settings.closeAfterSelect) { + self.close(); + } else if (!self.settings.hideSelected && e.type && /mouse/.test(e.type)) { self.setActiveOption(self.getOption(value)); } } @@ -1634,7 +1766,7 @@ */ load: function(fn) { var self = this; - var $wrapper = self.$wrapper.addClass('loading'); + var $wrapper = self.$wrapper.addClass(self.settings.loadingClass); self.loading++; fn.apply(self, [function(results) { @@ -1644,7 +1776,7 @@ self.refreshOptions(self.isFocused && !self.isInputHidden); } if (!self.loading) { - $wrapper.removeClass('loading'); + $wrapper.removeClass(self.settings.loadingClass); } self.trigger('load', results); }]); @@ -1656,8 +1788,12 @@ * @param {string} value */ setTextboxValue: function(value) { - this.$control_input.val(value).triggerHandler('update'); - this.lastValue = value; + var $input = this.$control_input; + var changed = $input.val() !== value; + if (changed) { + $input.val(value).triggerHandler('update'); + this.lastValue = value; + } }, /** @@ -1681,13 +1817,12 @@ * * @param {mixed} value */ - setValue: function(value) { - debounce_events(this, ['change'], function() { - this.clear(); - var items = $.isArray(value) ? value : [value]; - for (var i = 0, n = items.length; i < n; i++) { - this.addItem(items[i]); - } + setValue: function(value, silent) { + var events = silent ? [] : ['change']; + + debounce_events(this, events, function() { + this.clear(silent); + this.addItems(value, silent); }); }, @@ -1799,12 +1934,15 @@ * Selects all items (CTRL + A). */ selectAll: function() { - this.$activeItems = Array.prototype.slice.apply(this.$control.children(':not(input)').addClass('active')); - if (this.$activeItems.length) { - this.hideInput(); - this.close(); + var self = this; + if (self.settings.mode === 'single') return; + + self.$activeItems = Array.prototype.slice.apply(self.$control.children(':not(input)').addClass('active')); + if (self.$activeItems.length) { + self.hideInput(); + self.close(); } - this.focus(); + self.focus(); }, /** @@ -1828,11 +1966,7 @@ }, /** - * Gives the control focus. If "trigger" is falsy, - * focus handlers won't be fired--causing the focus - * to happen silently in the background. - * - * @param {boolean} trigger + * Gives the control focus. */ focus: function() { var self = this; @@ -1848,9 +1982,12 @@ /** * Forces the control out of focus. + * + * @param {Element} dest */ - blur: function() { - this.$control_input.trigger('blur'); + blur: function(dest) { + this.$control_input[0].blur(); + this.onBlur(null, dest); }, /** @@ -1877,7 +2014,7 @@ var settings = this.settings; var sort = settings.sortField; if (typeof sort === 'string') { - sort = {field: sort}; + sort = [{field: sort}]; } return { @@ -1951,7 +2088,7 @@ } var self = this; - var query = self.$control_input.val(); + var query = $.trim(self.$control_input.val()); var results = self.search(query); var $dropdown_content = self.$dropdown_content; var active_before = self.$activeOption && hash_key(self.$activeOption.attr('data-value')); @@ -1964,15 +2101,7 @@ // render and group available options individually groups = {}; - - if (self.settings.optgroupOrder) { - groups_order = self.settings.optgroupOrder; - for (i = 0; i < groups_order.length; i++) { - groups[groups_order[i]] = []; - } - } else { - groups_order = []; - } + groups_order = []; for (i = 0; i < n; i++) { option = self.options[results.items[i].id]; @@ -1993,6 +2122,15 @@ } } + // sort optgroups + if (this.settings.lockOptgroupOrder) { + groups_order.sort(function(a, b) { + var a_order = self.optgroups[a].$order || 0; + var b_order = self.optgroups[b].$order || 0; + return a_order - b_order; + }); + } + // render optgroup headers & join groups html = []; for (i = 0, n = groups_order.length; i < n; i++) { @@ -2027,7 +2165,7 @@ } // add create option - has_create_option = self.settings.create && results.query.length; + has_create_option = self.canCreate(query); if (has_create_option) { $dropdown_content.prepend(self.render('option_create', {input: query})); $create = $($dropdown_content[0].childNodes[0]); @@ -2071,10 +2209,10 @@ * * this.addOption(data) * - * @param {object} data + * @param {object|array} data */ addOption: function(data) { - var i, n, optgroup, value, self = this; + var i, n, value, self = this; if ($.isArray(data)) { for (i = 0, n = data.length; i < n; i++) { @@ -2083,13 +2221,40 @@ return; } - value = hash_key(data[self.settings.valueField]); - if (!value || self.options.hasOwnProperty(value)) return; + if (value = self.registerOption(data)) { + self.userOptions[value] = true; + self.lastQuery = null; + self.trigger('option_add', value, data); + } + }, - self.userOptions[value] = true; - self.options[value] = data; - self.lastQuery = null; - self.trigger('option_add', value, data); + /** + * Registers an option to the pool of options. + * + * @param {object} data + * @return {boolean|string} + */ + registerOption: function(data) { + var key = hash_key(data[this.settings.valueField]); + if (!key || this.options.hasOwnProperty(key)) return false; + data.$order = data.$order || ++this.order; + this.options[key] = data; + return key; + }, + + /** + * Registers an option group to the pool of option groups. + * + * @param {object} data + * @return {boolean|string} + */ + registerOptionGroup: function(data) { + var key = hash_key(data[this.settings.optgroupValueField]); + if (!key) return false; + + data.$order = data.$order || ++this.order; + this.optgroups[key] = data; + return key; }, /** @@ -2100,8 +2265,32 @@ * @param {object} data */ addOptionGroup: function(id, data) { - this.optgroups[id] = data; - this.trigger('optgroup_add', id, data); + data[this.settings.optgroupValueField] = id; + if (id = this.registerOptionGroup(data)) { + this.trigger('optgroup_add', id, data); + } + }, + + /** + * Removes an existing option group. + * + * @param {string} id + */ + removeOptionGroup: function(id) { + if (this.optgroups.hasOwnProperty(id)) { + delete this.optgroups[id]; + this.renderCache = {}; + this.trigger('optgroup_remove', id); + } + }, + + /** + * Clears all existing option groups. + */ + clearOptionGroups: function() { + this.optgroups = {}; + this.renderCache = {}; + this.trigger('optgroup_clear'); }, /** @@ -2115,14 +2304,17 @@ updateOption: function(value, data) { var self = this; var $item, $item_new; - var value_new, index_item, cache_items, cache_options; + var value_new, index_item, cache_items, cache_options, order_old; value = hash_key(value); value_new = hash_key(data[self.settings.valueField]); // sanity checks + if (value === null) return; if (!self.options.hasOwnProperty(value)) return; - if (!value_new) throw new Error('Value must be set in option data'); + if (typeof value_new !== 'string') throw new Error('Value must be set in option data'); + + order_old = self.options[value].$order; // update references if (value_new !== value) { @@ -2132,17 +2324,18 @@ self.items.splice(index_item, 1, value_new); } } + data.$order = data.$order || order_old; self.options[value_new] = data; // invalidate render cache cache_items = self.renderCache['item']; cache_options = self.renderCache['option']; - if (isset(cache_items)) { + if (cache_items) { delete cache_items[value]; delete cache_items[value_new]; } - if (isset(cache_options)) { + if (cache_options) { delete cache_options[value]; delete cache_options[value_new]; } @@ -2155,6 +2348,9 @@ $item.replaceWith($item_new); } + // invalidate last query because we might have updated the sortField + self.lastQuery = null; + // update dropdown contents if (self.isOpen) { self.refreshOptions(false); @@ -2165,16 +2361,22 @@ * Removes a single option. * * @param {string} value + * @param {boolean} silent */ - removeOption: function(value) { + removeOption: function(value, silent) { var self = this; - value = hash_key(value); + + var cache_items = self.renderCache['item']; + var cache_options = self.renderCache['option']; + if (cache_items) delete cache_items[value]; + if (cache_options) delete cache_options[value]; + delete self.userOptions[value]; delete self.options[value]; self.lastQuery = null; self.trigger('option_remove', value); - self.removeItem(value); + self.removeItem(value, silent); }, /** @@ -2185,6 +2387,7 @@ self.loadedSearches = {}; self.userOptions = {}; + self.renderCache = {}; self.options = self.sifter.items = {}; self.lastQuery = null; self.trigger('option_clear'); @@ -2228,7 +2431,7 @@ getElementWithValue: function(value, $els) { value = hash_key(value); - if (value) { + if (typeof value !== 'undefined' && value !== null) { for (var i = 0, n = $els.length; i < n; i++) { if ($els[i].getAttribute('data-value') === value) { return $($els[i]); @@ -2250,18 +2453,36 @@ return this.getElementWithValue(value, this.$control.children()); }, + /** + * "Selects" multiple items at once. Adds them to the list + * at the current caret position. + * + * @param {string} value + * @param {boolean} silent + */ + addItems: function(values, silent) { + var items = $.isArray(values) ? values : [values]; + for (var i = 0, n = items.length; i < n; i++) { + this.isPending = (i < n - 1); + this.addItem(items[i], silent); + } + }, + /** * "Selects" an item. Adds it to the list * at the current caret position. * * @param {string} value + * @param {boolean} silent */ - addItem: function(value) { - debounce_events(this, ['change'], function() { - var $item, $option; + addItem: function(value, silent) { + var events = silent ? [] : ['change']; + + debounce_events(this, events, function() { + var $item, $option, $options; var self = this; var inputMode = self.settings.mode; - var i, active, options, value_next; + var i, active, value_next, wasFull; value = hash_key(value); if (self.items.indexOf(value) !== -1) { @@ -2270,27 +2491,32 @@ } if (!self.options.hasOwnProperty(value)) return; - if (inputMode === 'single') self.clear(); + if (inputMode === 'single') self.clear(silent); if (inputMode === 'multi' && self.isFull()) return; $item = $(self.render('item', self.options[value])); + wasFull = self.isFull(); self.items.splice(self.caretPos, 0, value); self.insertAtCaret($item); - self.refreshState(); + if (!self.isPending || (!wasFull && self.isFull())) { + self.refreshState(); + } if (self.isSetup) { - options = self.$dropdown_content.find('[data-selectable]'); - - // update menu / remove the option - $option = self.getOption(value); - value_next = self.getAdjacentOption($option, 1).attr('data-value'); - self.refreshOptions(self.isFocused && inputMode !== 'single'); - if (value_next) { - self.setActiveOption(self.getOption(value_next)); + $options = self.$dropdown_content.find('[data-selectable]'); + + // update menu / remove the option (if this is not one item being added as part of series) + if (!self.isPending) { + $option = self.getOption(value); + value_next = self.getAdjacentOption($option, 1).attr('data-value'); + self.refreshOptions(self.isFocused && inputMode !== 'single'); + if (value_next) { + self.setActiveOption(self.getOption(value_next)); + } } // hide the menu if the maximum number of items have been selected or no options are left - if (!options.length || (self.settings.maxItems !== null && self.items.length >= self.settings.maxItems)) { + if (!$options.length || self.isFull()) { self.close(); } else { self.positionDropdown(); @@ -2298,7 +2524,7 @@ self.updatePlaceholder(); self.trigger('item_add', value, $item); - self.updateOriginalInput(); + self.updateOriginalInput({silent: silent}); } }); }, @@ -2309,7 +2535,7 @@ * * @param {string} value */ - removeItem: function(value) { + removeItem: function(value, silent) { var self = this; var $item, i, idx; @@ -2327,7 +2553,7 @@ self.items.splice(i, 1); self.lastQuery = null; if (!self.settings.persist && self.userOptions.hasOwnProperty(value)) { - self.removeOption(value); + self.removeOption(value, silent); } if (i < self.caretPos) { @@ -2336,9 +2562,9 @@ self.refreshState(); self.updatePlaceholder(); - self.updateOriginalInput(); + self.updateOriginalInput({silent: silent}); self.positionDropdown(); - self.trigger('item_remove', value); + self.trigger('item_remove', value, $item); } }, @@ -2350,13 +2576,28 @@ * Once this completes, it will be added * to the item list. * + * @param {string} value + * @param {boolean} [triggerDropdown] + * @param {function} [callback] * @return {boolean} */ - createItem: function() { + createItem: function(input, triggerDropdown) { var self = this; - var input = $.trim(self.$control_input.val() || ''); var caret = self.caretPos; - if (!input.length) return false; + input = input || $.trim(self.$control_input.val() || ''); + + var callback = arguments[arguments.length - 1]; + if (typeof callback !== 'function') callback = function() {}; + + if (typeof triggerDropdown !== 'boolean') { + triggerDropdown = true; + } + + if (!self.canCreate(input)) { + callback(); + return false; + } + self.lock(); var setup = (typeof self.settings.create === 'function') ? this.settings.create : function(input) { @@ -2369,15 +2610,16 @@ var create = once(function(data) { self.unlock(); - if (!data || typeof data !== 'object') return; + if (!data || typeof data !== 'object') return callback(); var value = hash_key(data[self.settings.valueField]); - if (!value) return; + if (typeof value !== 'string') return callback(); self.setTextboxValue(''); self.addOption(data); self.setCaret(caret); self.addItem(value); - self.refreshOptions(self.settings.mode !== 'single'); + self.refreshOptions(triggerDropdown && self.settings.mode !== 'single'); + callback(data); }); var output = setup.apply(this, [input, create]); @@ -2395,9 +2637,7 @@ this.lastQuery = null; if (this.isSetup) { - for (var i = 0; i < this.items.length; i++) { - this.addItem(this.items); - } + this.addItem(this.items); } this.refreshState(); @@ -2409,10 +2649,11 @@ * and CSS classes. */ refreshState: function() { - var self = this; - var invalid = self.isRequired && !self.items.length; - if (!invalid) self.isInvalid = false; - self.$control_input.prop('required', invalid); + var invalid, self = this; + if (self.isRequired) { + if (self.items.length) self.isInvalid = false; + self.$control_input.prop('required', invalid); + } self.refreshClasses(); }, @@ -2456,13 +2697,15 @@ * Refreshes the original * element to reflect the current state. */ - updateOriginalInput: function() { - var i, n, options, self = this; + updateOriginalInput: function(opts) { + var i, n, options, label, self = this; + opts = opts || {}; - if (self.$input[0].tagName.toLowerCase() === 'select') { + if (self.tagType === TAG_SELECT) { options = []; for (i = 0, n = self.items.length; i < n; i++) { - options.push(''); + label = self.options[self.items[i]][self.settings.labelField] || ''; + options.push(''); } if (!options.length && !this.$input.attr('multiple')) { options.push(''); @@ -2470,10 +2713,13 @@ self.$input.html(options.join('')); } else { self.$input.val(self.getValue()); + self.$input.attr('value',self.$input.val()); } if (self.isSetup) { - self.trigger('change', self.$input.val()); + if (!opts.silent) { + self.trigger('change', self.$input.val()); + } } }, @@ -2490,7 +2736,7 @@ } else { $input.attr('placeholder', this.settings.placeholder); } - $input.triggerHandler('update'); + $input.triggerHandler('update', {force: true}); }, /** @@ -2548,16 +2794,20 @@ /** * Resets / clears all selected items * from the control. + * + * @param {boolean} silent */ - clear: function() { + clear: function(silent) { var self = this; if (!self.items.length) return; self.$control.children(':not(input)').remove(); self.items = []; + self.lastQuery = null; self.setCaret(0); + self.setActiveItem(null); self.updatePlaceholder(); - self.updateOriginalInput(); + self.updateOriginalInput({silent: silent}); self.refreshState(); self.showInput(); self.trigger('clear'); @@ -2633,6 +2883,7 @@ } self.showInput(); + self.positionDropdown(); self.refreshOptions(true); // select previous option @@ -2723,17 +2974,19 @@ i = Math.max(0, Math.min(self.items.length, i)); } - // the input must be moved by leaving it in place and moving the - // siblings, due to the fact that focus cannot be restored once lost - // on mobile webkit devices - var j, n, fn, $children, $child; - $children = self.$control.children(':not(input)'); - for (j = 0, n = $children.length; j < n; j++) { - $child = $($children[j]).detach(); - if (j < i) { - self.$control_input.before($child); - } else { - self.$control.append($child); + if(!self.isPending) { + // the input must be moved by leaving it in place and moving the + // siblings, due to the fact that focus cannot be restored once lost + // on mobile webkit devices + var j, n, fn, $children, $child; + $children = self.$control.children(':not(input)'); + for (j = 0, n = $children.length; j < n; j++) { + $child = $($children[j]).detach(); + if (j < i) { + self.$control_input.before($child); + } else { + self.$control.append($child); + } } } @@ -2765,6 +3018,7 @@ disable: function() { var self = this; self.$input.prop('disabled', true); + self.$control_input.prop('disabled', true).prop('tabindex', -1); self.isDisabled = true; self.lock(); }, @@ -2776,6 +3030,7 @@ enable: function() { var self = this; self.$input.prop('disabled', false); + self.$control_input.prop('disabled', false).prop('tabindex', self.tabIndex); self.isDisabled = false; self.unlock(); }, @@ -2799,9 +3054,13 @@ .html('') .append(revertSettings.$children) .removeAttr('tabindex') + .removeClass('selectized') .attr({tabindex: revertSettings.tabindex}) .show(); + self.$control_input.removeData('grow'); + self.$input.removeData('selectize'); + $(window).off(eventNS); $(document).off(eventNS); $(document.body).off(eventNS); @@ -2822,7 +3081,7 @@ var html = ''; var cache = false; var self = this; - var regex_tag = /^[\t ]*<([a-z][a-z0-9\-_]*(?:\:[a-z][a-z0-9\-_]*)?)/i; + var regex_tag = /^[\t \r\n]*<([a-z][a-z0-9\-_]*(?:\:[a-z][a-z0-9\-_]*)?)/i; if (templateName === 'option' || templateName === 'item') { value = hash_key(data[self.settings.valueField]); @@ -2860,6 +3119,39 @@ } return html; + }, + + /** + * Clears the render cache for a template. If + * no template is given, clears all render + * caches. + * + * @param {string} templateName + */ + clearCache: function(templateName) { + var self = this; + if (typeof templateName === 'undefined') { + self.renderCache = {}; + } else { + delete self.renderCache[templateName]; + } + }, + + /** + * Determines whether or not to display the + * create item prompt, given a user input. + * + * @param {string} input + * @return {boolean} + */ + canCreate: function(input) { + var self = this; + if (!self.settings.create) return false; + var filter = self.settings.createFilter; + return input.length + && (typeof filter !== 'function' || filter.apply(self, [input])) + && (typeof filter !== 'string' || new RegExp(filter).test(input)) + && (!(filter instanceof RegExp) || filter.test(input)); } }); @@ -2867,22 +3159,31 @@ Selectize.count = 0; Selectize.defaults = { + options: [], + optgroups: [], + plugins: [], delimiter: ',', + splitOn: null, // regexp or string for splitting up values from a paste command persist: true, diacritics: true, create: false, createOnBlur: false, + createFilter: null, highlight: true, openOnFocus: true, maxOptions: 1000, maxItems: null, hideSelected: null, addPrecedence: false, + selectOnTab: false, preload: false, + allowEmptyOption: false, + closeAfterSelect: false, scrollDuration: 60, loadThrottle: 300, + loadingClass: 'loading', dataAttr: 'data-data', optgroupField: 'optgroup', @@ -2890,7 +3191,7 @@ labelField: 'text', optgroupLabelField: 'label', optgroupValueField: 'value', - optgroupOrder: null, + lockOptgroupOrder: false, sortField: '$order', searchField: ['text'], @@ -2904,21 +3205,26 @@ dropdownParent: null, + copyClassesToDropdown: true, + /* - load : null, // function(query, callback) { ... } - score : null, // function(search) { ... } - onInitialize : null, // function() { ... } - onChange : null, // function(value) { ... } - onItemAdd : null, // function(value, $item) { ... } - onItemRemove : null, // function(value) { ... } - onClear : null, // function() { ... } - onOptionAdd : null, // function(value, data) { ... } - onOptionRemove : null, // function(value) { ... } - onOptionClear : null, // function() { ... } - onDropdownOpen : null, // function($dropdown) { ... } - onDropdownClose : null, // function($dropdown) { ... } - onType : null, // function(str) { ... } - onDelete : null, // function(values) { ... } + load : null, // function(query, callback) { ... } + score : null, // function(search) { ... } + onInitialize : null, // function() { ... } + onChange : null, // function(value) { ... } + onItemAdd : null, // function(value, $item) { ... } + onItemRemove : null, // function(value) { ... } + onClear : null, // function() { ... } + onOptionAdd : null, // function(value, data) { ... } + onOptionRemove : null, // function(value) { ... } + onOptionClear : null, // function() { ... } + onOptionGroupAdd : null, // function(id, data) { ... } + onOptionGroupRemove : null, // function(id) { ... } + onOptionGroupClear : null, // function() { ... } + onDropdownOpen : null, // function($dropdown) { ... } + onDropdownClose : null, // function($dropdown) { ... } + onType : null, // function(str) { ... } + onDelete : null, // function(values) { ... } */ render: { @@ -2932,6 +3238,7 @@ } }; + $.fn.selectize = function(settings_user) { var defaults = $.fn.selectize.defaults; var settings = $.extend({}, defaults, settings_user); @@ -2949,19 +3256,27 @@ * @param {object} settings_element */ var init_textbox = function($input, settings_element) { - var i, n, values, option, value = $.trim($input.val() || ''); - if (!value.length) return; + var i, n, values, option; - values = value.split(settings.delimiter); - for (i = 0, n = values.length; i < n; i++) { - option = {}; - option[field_label] = values[i]; - option[field_value] = values[i]; + var data_raw = $input.attr(attr_data); - settings_element.options[values[i]] = option; + if (!data_raw) { + var value = $.trim($input.val() || ''); + if (!settings.allowEmptyOption && !value.length) return; + values = value.split(settings.delimiter); + for (i = 0, n = values.length; i < n; i++) { + option = {}; + option[field_label] = values[i]; + option[field_value] = values[i]; + settings_element.options.push(option); + } + settings_element.items = values; + } else { + settings_element.options = JSON.parse(data_raw); + for (i = 0, n = settings_element.options.length; i < n; i++) { + settings_element.items.push(settings_element.options[i][field_value]); + } } - - settings_element.items = values; }; /** @@ -2973,6 +3288,7 @@ var init_select = function($input, settings_element) { var i, n, tagName, $children, order = 0; var options = settings_element.options; + var optionsMap = {}; var readData = function($el) { var data = attr_data && $el.attr(attr_data); @@ -2983,37 +3299,36 @@ }; var addOption = function($option, group) { - var value, option; - $option = $($option); - value = $option.attr('value') || ''; - if (!value.length) return; + var value = hash_key($option.attr('value')); + if (!value && !settings.allowEmptyOption) return; // if the option already exists, it's probably been // duplicated in another optgroup. in this case, push // the current group to the "optgroup" property on the // existing option so that it's rendered in both places. - if (options.hasOwnProperty(value)) { + if (optionsMap.hasOwnProperty(value)) { if (group) { - if (!options[value].optgroup) { - options[value].optgroup = group; - } else if (!$.isArray(options[value].optgroup)) { - options[value].optgroup = [options[value].optgroup, group]; + var arr = optionsMap[value][field_optgroup]; + if (!arr) { + optionsMap[value][field_optgroup] = group; + } else if (!$.isArray(arr)) { + optionsMap[value][field_optgroup] = [arr, group]; } else { - options[value].optgroup.push(group); + arr.push(group); } } return; } - option = readData($option) || {}; + var option = readData($option) || {}; option[field_label] = option[field_label] || $option.text(); option[field_value] = option[field_value] || value; option[field_optgroup] = option[field_optgroup] || group; - option.$order = ++order; - options[value] = option; + optionsMap[value] = option; + options.push(option); if ($option.is(':selected')) { settings_element.items.push(value); @@ -3030,7 +3345,7 @@ optgroup = readData($optgroup) || {}; optgroup[field_optgroup_label] = id; optgroup[field_optgroup_value] = id; - settings_element.optgroups[id] = optgroup; + settings_element.optgroups.push(optgroup); } $options = $('option', $optgroup); @@ -3058,10 +3373,15 @@ var instance; var $input = $(this); var tag_name = this.tagName.toLowerCase(); + var placeholder = $input.attr('placeholder') || $input.attr('data-placeholder'); + if (!placeholder && !settings.allowEmptyOption) { + placeholder = $input.children('option[value=""]').text(); + } + var settings_element = { - 'placeholder' : $input.children('option[value=""]').text() || $input.attr('placeholder'), - 'options' : {}, - 'optgroups' : {}, + 'placeholder' : placeholder, + 'options' : [], + 'optgroups' : [], 'items' : [] }; @@ -3072,12 +3392,14 @@ } instance = new Selectize($input, $.extend(true, {}, defaults, settings_element, settings_user)); - $input.data('selectize', instance); - $input.addClass('selectized'); }); }; $.fn.selectize.defaults = Selectize.defaults; + $.fn.selectize.support = { + validity: SUPPORTS_VALIDITY_API + }; + Selectize.define('drag_drop', function(options) { if (!$.fn.sortable) throw new Error('The "drag_drop" plugin requires jQuery UI "sortable".'); @@ -3207,6 +3529,22 @@ }; })(); + var getScrollbarWidth = function() { + var div; + var width = getScrollbarWidth.width; + var doc = document; + + if (typeof width === 'undefined') { + div = doc.createElement('div'); + div.innerHTML = '
    '; + div = div.firstChild; + doc.body.appendChild(div); + width = getScrollbarWidth.width = div.offsetWidth - div.clientWidth; + doc.body.removeChild(div); + } + return width; + }; + var equalizeSizes = function() { var i, n, height_max, width, width_last, width_parent, $optgroups; @@ -3223,7 +3561,7 @@ } if (options.equalizeWidth) { - width_parent = self.$dropdown_content.innerWidth(); + width_parent = self.$dropdown_content.innerWidth() - getScrollbarWidth(); width = Math.round(width_parent / n); $optgroups.css({width: width}); if (n > 1) { @@ -3284,7 +3622,7 @@ e.preventDefault(); if (self.isLocked) return; - var $item = $(e.target).parent(); + var $item = $(e.currentTarget).parent(); self.setActiveItem($item); if (self.deleteSelection()) { self.setCaret(self.items.length); @@ -3303,7 +3641,7 @@ return option[this.settings.labelField]; }; - this.onKeyDown = (function(e) { + this.onKeyDown = (function() { var original = self.onKeyDown; return function(e) { var index, option; @@ -3323,6 +3661,7 @@ }; })(); }); + return Selectize; })); \ No newline at end of file diff --git a/xadmin/static/xadmin/vendor/selectize/selectize.legacy.css b/xadmin/static/xadmin/vendor/selectize/selectize.legacy.css index fa85c09bf..0dccdb6cc 100644 --- a/xadmin/static/xadmin/vendor/selectize/selectize.legacy.css +++ b/xadmin/static/xadmin/vendor/selectize/selectize.legacy.css @@ -1,6 +1,6 @@ /** - * selectize.legacy.css (v0.8.4) - Default Theme - * Copyright (c) 2013 Brian Reavis & contributors + * selectize.legacy.css (v0.12.1) - Default Theme + * Copyright (c) 2013–2015 Brian Reavis & contributors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this * file except in compliance with the License. You may obtain a copy of the License at: @@ -13,354 +13,312 @@ * * @author Brian Reavis */ - .selectize-control.plugin-drag_drop.multi > .selectize-input > div.ui-sortable-placeholder { + visibility: visible !important; background: #f2f2f2 !important; background: rgba(0, 0, 0, 0.06) !important; border: 0 none !important; - visibility: visible !important; -webkit-box-shadow: inset 0 0 12px 4px #ffffff; - box-shadow: inset 0 0 12px 4px #ffffff; + box-shadow: inset 0 0 12px 4px #ffffff; } - .selectize-control.plugin-drag_drop .ui-sortable-placeholder::after { content: '!'; visibility: hidden; } - .selectize-control.plugin-drag_drop .ui-sortable-helper { -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } - .selectize-dropdown-header { position: relative; padding: 7px 10px; - background: #f8f8f8; border-bottom: 1px solid #d0d0d0; + background: #f8f8f8; -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; } - .selectize-dropdown-header-close { position: absolute; - top: 50%; right: 10px; - margin-top: -12px; - font-size: 20px !important; - line-height: 20px; + top: 50%; color: #303030; opacity: 0.4; + margin-top: -12px; + line-height: 20px; + font-size: 20px !important; } - .selectize-dropdown-header-close:hover { color: #000000; } - .selectize-dropdown.plugin-optgroup_columns .optgroup { - float: left; - border-top: 0 none; border-right: 1px solid #f2f2f2; + border-top: 0 none; + float: left; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } - .selectize-dropdown.plugin-optgroup_columns .optgroup:last-child { border-right: 0 none; } - .selectize-dropdown.plugin-optgroup_columns .optgroup:before { display: none; } - .selectize-dropdown.plugin-optgroup_columns .optgroup-header { border-top: 0 none; } - .selectize-control.plugin-remove_button [data-value] { position: relative; padding-right: 24px !important; } - .selectize-control.plugin-remove_button [data-value] .remove { + z-index: 1; + /* fixes ie bug (see #392) */ position: absolute; top: 0; right: 0; bottom: 0; - display: inline-block; width: 17px; - padding: 1px 0 0 0; - font-size: 12px; + text-align: center; font-weight: bold; + font-size: 12px; color: inherit; - text-align: center; text-decoration: none; vertical-align: middle; + display: inline-block; + padding: 1px 0 0 0; border-left: 1px solid #74b21e; -webkit-border-radius: 0 2px 2px 0; - -moz-border-radius: 0 2px 2px 0; - border-radius: 0 2px 2px 0; + -moz-border-radius: 0 2px 2px 0; + border-radius: 0 2px 2px 0; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } - .selectize-control.plugin-remove_button [data-value] .remove:hover { background: rgba(0, 0, 0, 0.05); } - .selectize-control.plugin-remove_button [data-value].active .remove { border-left-color: #6f9839; } - .selectize-control.plugin-remove_button .disabled [data-value] .remove:hover { background: none; } - .selectize-control.plugin-remove_button .disabled [data-value] .remove { border-left-color: #b4b4b4; } - .selectize-control { position: relative; } - .selectize-dropdown, .selectize-input, .selectize-input input { + color: #303030; font-family: inherit; font-size: 13px; - -webkit-font-smoothing: inherit; line-height: 20px; - color: #303030; + -webkit-font-smoothing: inherit; } - .selectize-input, .selectize-control.single .selectize-input.input-active { - display: inline-block; - cursor: text; background: #ffffff; + cursor: text; + display: inline-block; } - .selectize-input { - position: relative; - z-index: 1; + border: 1px solid #d0d0d0; + padding: 10px 10px; display: inline-block; width: 100%; - padding: 10px 10px; overflow: hidden; - border: 1px solid #d0d0d0; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + position: relative; + z-index: 1; -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; } - .selectize-control.multi .selectize-input.has-items { padding: 8px 10px 4px; } - .selectize-input.full { background-color: #f2f2f2; } - .selectize-input.disabled, .selectize-input.disabled * { cursor: default !important; } - .selectize-input.focus { -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15); } - .selectize-input.dropdown-active { -webkit-border-radius: 3px 3px 0 0; - -moz-border-radius: 3px 3px 0 0; - border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; } - .selectize-input > * { + vertical-align: baseline; display: -moz-inline-stack; display: inline-block; - *display: inline; - vertical-align: baseline; zoom: 1; + *display: inline; } - .selectize-control.multi .selectize-input > div { - padding: 1px 5px; - margin: 0 4px 4px 0; - color: #3d5d18; cursor: pointer; + margin: 0 4px 4px 0; + padding: 1px 5px; background: #b8e76f; + color: #3d5d18; border: 1px solid #74b21e; } - .selectize-control.multi .selectize-input > div.active { - color: #303030; background: #92c836; + color: #303030; border: 1px solid #6f9839; } - .selectize-control.multi .selectize-input.disabled > div, .selectize-control.multi .selectize-input.disabled > div.active { color: #878787; background: #f8f8f8; border: 1px solid #b4b4b4; } - .selectize-input > input { - max-width: 100% !important; - max-height: none !important; - min-height: 0 !important; + display: inline-block !important; padding: 0 !important; + min-height: 0 !important; + max-height: none !important; + max-width: 100% !important; margin: 0 2px 0 0 !important; - line-height: inherit !important; text-indent: 0 !important; - background: none !important; border: 0 none !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; + background: none !important; + line-height: inherit !important; -webkit-user-select: auto !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; +} +.selectize-input > input::-ms-clear { + display: none; } - .selectize-input > input:focus { outline: none !important; } - .selectize-input::after { + content: ' '; display: block; clear: left; - content: ' '; } - .selectize-input.dropdown-active::before { + content: ' '; + display: block; position: absolute; - right: 0; + background: #f0f0f0; + height: 1px; bottom: 0; left: 0; - display: block; - height: 1px; - background: #f0f0f0; - content: ' '; + right: 0; } - .selectize-dropdown { position: absolute; z-index: 10; - margin: -1px 0 0 0; - background: #ffffff; border: 1px solid #d0d0d0; + background: #ffffff; + margin: -1px 0 0 0; border-top: 0 none; - -webkit-border-radius: 0 0 3px 3px; - -moz-border-radius: 0 0 3px 3px; - border-radius: 0 0 3px 3px; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -webkit-border-radius: 0 0 3px 3px; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; } - .selectize-dropdown [data-selectable] { - overflow: hidden; cursor: pointer; + overflow: hidden; } - .selectize-dropdown [data-selectable] .highlight { background: rgba(255, 237, 40, 0.4); -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; } - .selectize-dropdown [data-selectable], .selectize-dropdown .optgroup-header { padding: 7px 10px; } - .selectize-dropdown .optgroup:first-child .optgroup-header { border-top: 0 none; } - .selectize-dropdown .optgroup-header { color: #303030; - cursor: default; background: #f8f8f8; + cursor: default; } - .selectize-dropdown .active { - color: #303030; background-color: #fffceb; + color: #303030; } - .selectize-dropdown .active.create { color: #303030; } - .selectize-dropdown .create { color: rgba(48, 48, 48, 0.5); } - .selectize-dropdown-content { - max-height: 200px; - overflow-x: hidden; overflow-y: auto; + overflow-x: hidden; + max-height: 200px; } - .selectize-control.single .selectize-input, .selectize-control.single .selectize-input input { cursor: pointer; } - .selectize-control.single .selectize-input.input-active, .selectize-control.single .selectize-input.input-active input { cursor: text; } - .selectize-control.single .selectize-input:after { + content: ' '; + display: block; position: absolute; top: 50%; right: 15px; - display: block; + margin-top: -3px; width: 0; height: 0; - margin-top: -3px; - border-color: #808080 transparent transparent transparent; border-style: solid; border-width: 5px 5px 0 5px; - content: ' '; + border-color: #808080 transparent transparent transparent; } - .selectize-control.single .selectize-input.dropdown-active:after { margin-top: -4px; - border-color: transparent transparent #808080 transparent; border-width: 0 5px 5px 5px; + border-color: transparent transparent #808080 transparent; } - .selectize-control.rtl.single .selectize-input:after { - right: auto; left: 15px; + right: auto; } - .selectize-control.rtl .selectize-input > input { margin: 0 4px 0 -2px !important; } - .selectize-control .selectize-input.disabled { - background-color: #fafafa; opacity: 0.5; + background-color: #fafafa; } - .selectize-control.multi .selectize-input [data-value] { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; background-color: #b2e567; background-image: -moz-linear-gradient(top, #b8e76f, #a9e25c); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b8e76f), to(#a9e25c)); @@ -368,14 +326,10 @@ background-image: -o-linear-gradient(top, #b8e76f, #a9e25c); background-image: linear-gradient(to bottom, #b8e76f, #a9e25c); background-repeat: repeat-x; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffb8e76f', endColorstr='#ffa9e25c', GradientType=0); -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); } - .selectize-control.multi .selectize-input [data-value].active { background-color: #88c332; background-image: -moz-linear-gradient(top, #92c836, #7abc2c); @@ -386,8 +340,9 @@ background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff92c836', endColorstr='#ff7abc2c', GradientType=0); } - .selectize-control.single .selectize-input { + -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,0.8), 0 2px 0 #e0e0e0, 0 3px 0 #c8c8c8, 0 4px 1px rgba(0,0,0,0.1); + box-shadow: inset 0 1px 0 rgba(255,255,255,0.8), 0 2px 0 #e0e0e0, 0 3px 0 #c8c8c8, 0 4px 1px rgba(0,0,0,0.1); background-color: #f3f3f3; background-image: -moz-linear-gradient(top, #f5f5f5, #efefef); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#efefef)); @@ -396,18 +351,14 @@ background-image: linear-gradient(to bottom, #f5f5f5, #efefef); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffefefef', GradientType=0); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8), 0 2px 0 #e0e0e0, 0 3px 0 #c8c8c8, 0 4px 1px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8), 0 2px 0 #e0e0e0, 0 3px 0 #c8c8c8, 0 4px 1px rgba(0, 0, 0, 0.1); } - .selectize-control.single .selectize-input, .selectize-dropdown.single { border-color: #b8b8b8; } - .selectize-dropdown .optgroup-header { - font-size: 0.8em; font-weight: bold; - border-top: 1px solid #f0f0f0; + font-size: 0.8em; border-bottom: 1px solid #f0f0f0; -} \ No newline at end of file + border-top: 1px solid #f0f0f0; +} diff --git a/xadmin/static/xadmin/vendor/selectize/selectize.min.js b/xadmin/static/xadmin/vendor/selectize/selectize.min.js index 622fcacc3..fe955bc00 100644 --- a/xadmin/static/xadmin/vendor/selectize/selectize.min.js +++ b/xadmin/static/xadmin/vendor/selectize/selectize.min.js @@ -1,3 +1,3 @@ -/*! selectize.js - v0.8.4 | https://github.com/brianreavis/selectize.js | Apache License (v2) */ -!function(a,b){"function"==typeof define&&define.amd?define(b):"object"==typeof exports?module.exports=b():a.Sifter=b()}(this,function(){var a=function(a,b){this.items=a,this.settings=b||{diacritics:!0}};a.prototype.tokenize=function(a){if(a=d(String(a||"").toLowerCase()),!a||!a.length)return[];var b,c,f,h,i=[],j=a.split(/ +/);for(b=0,c=j.length;c>b;b++){if(f=e(j[b]),this.settings.diacritics)for(h in g)g.hasOwnProperty(h)&&(f=f.replace(new RegExp(h,"g"),g[h]));i.push({string:j[b],regex:new RegExp(f,"i")})}return i},a.prototype.iterator=function(a,b){var c;c=f(a)?Array.prototype.forEach||function(a){for(var b=0,c=this.length;c>b;b++)a(this[b],b,this)}:function(a){for(var b in this)this.hasOwnProperty(b)&&a(this[b],b,this)},c.apply(a,[b])},a.prototype.getScoreFunction=function(a,b){var c,d,e,f;c=this,a=c.prepareSearch(a,b),e=a.tokens,d=a.options.fields,f=e.length;var g=function(a,b){var c,d;return a?(a=String(a||""),d=a.search(b.regex),-1===d?0:(c=b.string.length/a.length,0===d&&(c+=.5),c)):0},h=function(){var a=d.length;return a?1===a?function(a,b){return g(b[d[0]],a)}:function(b,c){for(var e=0,f=0;a>e;e++)f+=g(c[d[e]],b);return f/a}:function(){return 0}}();return f?1===f?function(a){return h(e[0],a)}:"and"===a.options.conjunction?function(a){for(var b,c=0,d=0;f>c;c++){if(b=h(e[c],a),0>=b)return 0;d+=b}return d/f}:function(a){for(var b=0,c=0;f>b;b++)c+=h(e[b],a);return c/f}:function(){return 0}},a.prototype.getSortFunction=function(a,c){var d,e,f,g,h,i,j,k,l,m,n;if(f=this,a=f.prepareSearch(a,c),n=!a.query&&c.sort_empty||c.sort,l=function(a,b){return"$score"===a?b.score:f.items[b.id][a]},h=[],n)for(d=0,e=n.length;e>d;d++)(a.query||"$score"!==n[d].field)&&h.push(n[d]);if(a.query){for(m=!0,d=0,e=h.length;e>d;d++)if("$score"===h[d].field){m=!1;break}m&&h.unshift({field:"$score",direction:"desc"})}else for(d=0,e=h.length;e>d;d++)if("$score"===h[d].field){h.splice(d,1);break}for(k=[],d=0,e=h.length;e>d;d++)k.push("desc"===h[d].direction?-1:1);return i=h.length,i?1===i?(g=h[0].field,j=k[0],function(a,c){return j*b(l(g,a),l(g,c))}):function(a,c){var d,e,f;for(d=0;i>d;d++)if(f=h[d].field,e=k[d]*b(l(f,a),l(f,c)))return e;return 0}:null},a.prototype.prepareSearch=function(a,b){if("object"==typeof a)return a;b=c({},b);var d=b.fields,e=b.sort,g=b.sort_empty;return d&&!f(d)&&(b.fields=[d]),e&&!f(e)&&(b.sort=[e]),g&&!f(g)&&(b.sort_empty=[g]),{options:b,query:String(a||"").toLowerCase(),tokens:this.tokenize(a),total:0,items:[]}},a.prototype.search=function(a,b){var c,d,e,f,g=this;return d=this.prepareSearch(a,b),b=d.options,a=d.query,f=b.score||g.getScoreFunction(d),a.length?g.iterator(g.items,function(a,e){c=f(a),(b.filter===!1||c>0)&&d.items.push({score:c,id:e})}):g.iterator(g.items,function(a,b){d.items.push({score:1,id:b})}),e=g.getSortFunction(d,b),e&&d.items.sort(e),d.total=d.items.length,"number"==typeof b.limit&&(d.items=d.items.slice(0,b.limit)),d};var b=function(a,b){return"number"==typeof a&&"number"==typeof b?a>b?1:b>a?-1:0:(a=String(a||"").toLowerCase(),b=String(b||"").toLowerCase(),a>b?1:b>a?-1:0)},c=function(a){var b,c,d,e;for(b=1,c=arguments.length;c>b;b++)if(e=arguments[b])for(d in e)e.hasOwnProperty(d)&&(a[d]=e[d]);return a},d=function(a){return(a+"").replace(/^\s+|\s+$|/g,"")},e=function(a){return(a+"").replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")},f=Array.isArray||$&&$.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)},g={a:"[aÀÁÂÃÄÅàáâãäå]",c:"[cÇçćĆčČ]",d:"[dđĐ]",e:"[eÈÉÊËèéêë]",i:"[iÌÍÎÏìíîï]",n:"[nÑñ]",o:"[oÒÓÔÕÕÖØòóôõöø]",s:"[sŠš]",u:"[uÙÚÛÜùúûü]",y:"[yŸÿý]",z:"[zŽž]"};return a}),function(a,b){"function"==typeof define&&define.amd?define(b):"object"==typeof exports?module.exports=b():a.MicroPlugin=b()}(this,function(){var a={};a.mixin=function(a){a.plugins={},a.prototype.initializePlugins=function(a){var c,d,e,f=this,g=[];if(f.plugins={names:[],settings:{},requested:{},loaded:{}},b.isArray(a))for(c=0,d=a.length;d>c;c++)"string"==typeof a[c]?g.push(a[c]):(f.plugins.settings[a[c].name]=a[c].options,g.push(a[c].name));else if(a)for(e in a)a.hasOwnProperty(e)&&(f.plugins.settings[e]=a[e],g.push(e));for(;g.length;)f.require(g.shift())},a.prototype.loadPlugin=function(b){var c=this,d=c.plugins,e=a.plugins[b];if(!a.plugins.hasOwnProperty(b))throw new Error('Unable to find "'+b+'" plugin');d.requested[b]=!0,d.loaded[b]=e.fn.apply(c,[c.plugins.settings[b]||{}]),d.names.push(b)},a.prototype.require=function(a){var b=this,c=b.plugins;if(!b.plugins.loaded.hasOwnProperty(a)){if(c.requested[a])throw new Error('Plugin has circular dependency ("'+a+'")');b.loadPlugin(a)}return c.loaded[a]},a.define=function(b,c){a.plugins[b]={name:b,fn:c}}};var b={isArray:Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)}};return a}),function(a,b){"function"==typeof define&&define.amd?define(["jquery","sifter","microplugin"],b):a.Selectize=b(a.jQuery,a.Sifter,a.MicroPlugin)}(this,function(a,b,c){"use strict";var d=function(a,b){if("string"!=typeof b||b.length){var c="string"==typeof b?new RegExp(b,"i"):b,d=function(a){var b=0;if(3===a.nodeType){var e=a.data.search(c);if(e>=0&&a.data.length>0){var f=a.data.match(c),g=document.createElement("span");g.className="highlight";var h=a.splitText(e);h.splitText(f[0].length);var i=h.cloneNode(!0);g.appendChild(i),h.parentNode.replaceChild(g,h),b=1}}else if(1===a.nodeType&&a.childNodes&&!/(script|style)/i.test(a.tagName))for(var j=0;j/g,">").replace(/"/g,""")},y=function(a){return(a+"").replace(/\$/g,"$$$$")},z={};z.before=function(a,b,c){var d=a[b];a[b]=function(){return c.apply(a,arguments),d.apply(a,arguments)}},z.after=function(a,b,c){var d=a[b];a[b]=function(){var b=d.apply(a,arguments);return c.apply(a,arguments),b}};var A=function(b,c){if(!a.isArray(c))return c;var d,e,f={};for(d=0,e=c.length;e>d;d++)c[d].hasOwnProperty(b)&&(f[c[d][b]]=c[d]);return f},B=function(a){var b=!1;return function(){b||(b=!0,a.apply(this,arguments))}},C=function(a,b){var c;return function(){var d=this,e=arguments;window.clearTimeout(c),c=window.setTimeout(function(){a.apply(d,e)},b)}},D=function(a,b,c){var d,e=a.trigger,f={};a.trigger=function(){var c=arguments[0];return-1===b.indexOf(c)?e.apply(a,arguments):(f[c]=arguments,void 0)},c.apply(a,[]),a.trigger=e;for(d in f)f.hasOwnProperty(d)&&e.apply(a,f[d])},E=function(a,b,c,d){a.on(b,c,function(b){for(var c=b.target;c&&c.parentNode!==a[0];)c=c.parentNode;return b.currentTarget=c,d.apply(this,[b])})},F=function(a){var b={};if("selectionStart"in a)b.start=a.selectionStart,b.length=a.selectionEnd-b.start;else if(document.selection){a.focus();var c=document.selection.createRange(),d=document.selection.createRange().text.length;c.moveStart("character",-a.value.length),b.start=c.text.length-d,b.length=d}return b},G=function(a,b,c){var d,e,f={};if(c)for(d=0,e=c.length;e>d;d++)f[c[d]]=a.css(c[d]);else f=a.css();b.css(f)},H=function(b,c){var d=a("").css({position:"absolute",top:-99999,left:-99999,width:"auto",padding:0,whiteSpace:"pre"}).text(b).appendTo("body");G(c,d,["letterSpacing","fontSize","fontFamily","fontWeight","textTransform"]);var e=d.width();return d.remove(),e},I=function(a){var b=function(b){var c,d,e,f,g,h,i,j;b=b||window.event||{},b.metaKey||b.altKey||a.data("grow")!==!1&&(c=a.val(),b.type&&"keydown"===b.type.toLowerCase()&&(d=b.keyCode,e=d>=97&&122>=d||d>=65&&90>=d||d>=48&&57>=d||32===d,d===o||d===n?(j=F(a[0]),j.length?c=c.substring(0,j.start)+c.substring(j.start+j.length):d===n&&j.start?c=c.substring(0,j.start-1)+c.substring(j.start+1):d===o&&"undefined"!=typeof j.start&&(c=c.substring(0,j.start)+c.substring(j.start+1))):e&&(h=b.shiftKey,i=String.fromCharCode(b.keyCode),i=h?i.toUpperCase():i.toLowerCase(),c+=i)),f=a.attr("placeholder")||"",!c.length&&f.length&&(c=f),g=H(c,a)+4,g!==a.width()&&(a.width(g),a.triggerHandler("resize")))};a.on("keydown keyup update blur",b),b()},J=function(c,d){var e,f,g=this;f=c[0],f.selectize=g,e=window.getComputedStyle?window.getComputedStyle(f,null).getPropertyValue("direction"):f.currentStyle&&f.currentStyle.direction,e=e||c.parents("[dir]:first").attr("dir")||"",a.extend(g,{settings:d,$input:c,tagType:"select"===f.tagName.toLowerCase()?t:u,rtl:/rtl/i.test(e),eventNS:".selectize"+ ++J.count,highlightedValue:null,isOpen:!1,isDisabled:!1,isRequired:c.is("[required]"),isInvalid:!1,isLocked:!1,isFocused:!1,isInputHidden:!1,isSetup:!1,isShiftDown:!1,isCmdDown:!1,isCtrlDown:!1,ignoreFocus:!1,ignoreHover:!1,hasOptions:!1,currentResults:null,lastValue:"",caretPos:0,loading:0,loadedSearches:{},$activeOption:null,$activeItems:[],optgroups:{},options:{},userOptions:{},items:[],renderCache:{},onSearchChange:C(g.onSearchChange,d.loadThrottle)}),g.sifter=new b(this.options,{diacritics:d.diacritics}),a.extend(g.options,A(d.valueField,d.options)),delete g.settings.options,a.extend(g.optgroups,A(d.optgroupValueField,d.optgroups)),delete g.settings.optgroups,g.settings.mode=g.settings.mode||(1===g.settings.maxItems?"single":"multi"),"boolean"!=typeof g.settings.hideSelected&&(g.settings.hideSelected="multi"===g.settings.mode),g.initializePlugins(g.settings.plugins),g.setupCallbacks(),g.setupTemplates(),g.setup()};return e.mixin(J),c.mixin(J),a.extend(J.prototype,{setup:function(){var b,c,d,e,g,h,i,j,k,l,m=this,n=m.settings,o=m.eventNS,s=a(window),u=a(document);i=m.settings.mode,j=m.$input.attr("tabindex")||"",k=m.$input.attr("class")||"",b=a("
    ").addClass(n.wrapperClass).addClass(k).addClass(i),c=a("
    ").addClass(n.inputClass).addClass("items").appendTo(b),d=a('').appendTo(c).attr("tabindex",j),h=a(n.dropdownParent||b),e=a("
    ").addClass(n.dropdownClass).addClass(k).addClass(i).hide().appendTo(h),g=a("
    ").addClass(n.dropdownContentClass).appendTo(e),b.css({width:m.$input[0].style.width}),m.plugins.names.length&&(l="plugin-"+m.plugins.names.join(" plugin-"),b.addClass(l),e.addClass(l)),(null===n.maxItems||n.maxItems>1)&&m.tagType===t&&m.$input.attr("multiple","multiple"),m.settings.placeholder&&d.attr("placeholder",n.placeholder),m.$wrapper=b,m.$control=c,m.$control_input=d,m.$dropdown=e,m.$dropdown_content=g,e.on("mouseenter","[data-selectable]",function(){return m.onOptionHover.apply(m,arguments)}),e.on("mousedown","[data-selectable]",function(){return m.onOptionSelect.apply(m,arguments)}),E(c,"mousedown","*:not(input)",function(){return m.onItemSelect.apply(m,arguments)}),I(d),c.on({mousedown:function(){return m.onMouseDown.apply(m,arguments)},click:function(){return m.onClick.apply(m,arguments)}}),d.on({mousedown:function(a){a.stopPropagation()},keydown:function(){return m.onKeyDown.apply(m,arguments)},keyup:function(){return m.onKeyUp.apply(m,arguments)},keypress:function(){return m.onKeyPress.apply(m,arguments)},resize:function(){m.positionDropdown.apply(m,[])},blur:function(){return m.onBlur.apply(m,arguments)},focus:function(){return m.onFocus.apply(m,arguments)}}),u.on("keydown"+o,function(a){m.isCmdDown=a[f?"metaKey":"ctrlKey"],m.isCtrlDown=a[f?"altKey":"ctrlKey"],m.isShiftDown=a.shiftKey}),u.on("keyup"+o,function(a){a.keyCode===r&&(m.isCtrlDown=!1),a.keyCode===p&&(m.isShiftDown=!1),a.keyCode===q&&(m.isCmdDown=!1)}),u.on("mousedown"+o,function(a){if(m.isFocused){if(a.target===m.$dropdown[0]||a.target.parentNode===m.$dropdown[0])return!1;m.$control.has(a.target).length||a.target===m.$control[0]||m.blur()}}),s.on(["scroll"+o,"resize"+o].join(" "),function(){m.isOpen&&m.positionDropdown.apply(m,arguments)}),s.on("mousemove"+o,function(){m.ignoreHover=!1}),this.revertSettings={$children:m.$input.children().detach(),tabindex:m.$input.attr("tabindex")},m.$input.attr("tabindex",-1).hide().after(m.$wrapper),a.isArray(n.items)&&(m.setValue(n.items),delete n.items),m.$input[0].validity&&m.$input.on("invalid"+o,function(a){a.preventDefault(),m.isInvalid=!0,m.refreshState()}),m.updateOriginalInput(),m.refreshItems(),m.refreshState(),m.updatePlaceholder(),m.isSetup=!0,m.$input.is(":disabled")&&m.disable(),m.on("change",this.onChange),m.trigger("initialize"),n.preload&&m.onSearchChange("")},setupTemplates:function(){var b=this,c=b.settings.labelField,d=b.settings.optgroupLabelField,e={optgroup:function(a){return'
    '+a.html+"
    "},optgroup_header:function(a,b){return'
    '+b(a[d])+"
    "},option:function(a,b){return'
    '+b(a[c])+"
    "},item:function(a,b){return'
    '+b(a[c])+"
    "},option_create:function(a,b){return'
    Add '+b(a.input)+"
    "}};b.settings.render=a.extend({},e,b.settings.render)},setupCallbacks:function(){var a,b,c={initialize:"onInitialize",change:"onChange",item_add:"onItemAdd",item_remove:"onItemRemove",clear:"onClear",option_add:"onOptionAdd",option_remove:"onOptionRemove",option_clear:"onOptionClear",dropdown_open:"onDropdownOpen",dropdown_close:"onDropdownClose",type:"onType"};for(a in c)c.hasOwnProperty(a)&&(b=this.settings[c[a]],b&&this.on(a,b))},onClick:function(a){var b=this;b.isFocused||(b.focus(),a.preventDefault())},onMouseDown:function(b){var c=this,d=b.isDefaultPrevented();if(a(b.target),c.isFocused){if(b.target!==c.$control_input[0])return"single"===c.settings.mode?c.isOpen?c.close():c.open():d||c.setActiveItem(null),!1}else d||window.setTimeout(function(){c.focus()},0)},onChange:function(){this.$input.trigger("change")},onKeyPress:function(a){if(this.isLocked)return a&&a.preventDefault();var b=String.fromCharCode(a.keyCode||a.which);return this.settings.create&&b===this.settings.delimiter?(this.createItem(),a.preventDefault(),!1):void 0},onKeyDown:function(a){a.target===this.$control_input[0];var b=this;if(b.isLocked)return a.keyCode!==s&&a.preventDefault(),void 0;switch(a.keyCode){case g:if(b.isCmdDown)return b.selectAll(),void 0;break;case i:return b.close(),void 0;case m:if(!b.isOpen&&b.hasOptions)b.open();else if(b.$activeOption){b.ignoreHover=!0;var c=b.getAdjacentOption(b.$activeOption,1);c.length&&b.setActiveOption(c,!0,!0)}return a.preventDefault(),void 0;case k:if(b.$activeOption){b.ignoreHover=!0;var d=b.getAdjacentOption(b.$activeOption,-1);d.length&&b.setActiveOption(d,!0,!0)}return a.preventDefault(),void 0;case h:return b.isOpen&&b.$activeOption&&b.onOptionSelect({currentTarget:b.$activeOption}),a.preventDefault(),void 0;case j:return b.advanceSelection(-1,a),void 0;case l:return b.advanceSelection(1,a),void 0;case s:return b.settings.create&&b.createItem()&&a.preventDefault(),void 0;case n:case o:return b.deleteSelection(a),void 0}return b.isFull()||b.isInputHidden?(a.preventDefault(),void 0):void 0},onKeyUp:function(a){var b=this;if(b.isLocked)return a&&a.preventDefault();var c=b.$control_input.val()||"";b.lastValue!==c&&(b.lastValue=c,b.onSearchChange(c),b.refreshOptions(),b.trigger("type",c))},onSearchChange:function(a){var b=this,c=b.settings.load;c&&(b.loadedSearches.hasOwnProperty(a)||(b.loadedSearches[a]=!0,b.load(function(d){c.apply(b,[a,d])})))},onFocus:function(a){var b=this;return b.isFocused=!0,b.isDisabled?(b.blur(),a&&a.preventDefault(),!1):(b.ignoreFocus||("focus"===b.settings.preload&&b.onSearchChange(""),b.$activeItems.length||(b.showInput(),b.setActiveItem(null),b.refreshOptions(!!b.settings.openOnFocus)),b.refreshState()),void 0)},onBlur:function(){var a=this;a.isFocused=!1,a.ignoreFocus||(a.settings.create&&a.settings.createOnBlur&&a.createItem(),a.close(),a.setTextboxValue(""),a.setActiveItem(null),a.setActiveOption(null),a.setCaret(a.items.length),a.refreshState())},onOptionHover:function(a){this.ignoreHover||this.setActiveOption(a.currentTarget,!1)},onOptionSelect:function(b){var c,d,e=this;b.preventDefault&&(b.preventDefault(),b.stopPropagation()),d=a(b.currentTarget),d.hasClass("create")?e.createItem():(c=d.attr("data-value"),c&&(e.lastQuery=null,e.setTextboxValue(""),e.addItem(c),!e.settings.hideSelected&&b.type&&/mouse/.test(b.type)&&e.setActiveOption(e.getOption(c))))},onItemSelect:function(a){var b=this;b.isLocked||"multi"===b.settings.mode&&(a.preventDefault(),b.setActiveItem(a.currentTarget,a))},load:function(a){var b=this,c=b.$wrapper.addClass("loading");b.loading++,a.apply(b,[function(a){b.loading=Math.max(b.loading-1,0),a&&a.length&&(b.addOption(a),b.refreshOptions(b.isFocused&&!b.isInputHidden)),b.loading||c.removeClass("loading"),b.trigger("load",a)}])},setTextboxValue:function(a){this.$control_input.val(a).triggerHandler("update"),this.lastValue=a},getValue:function(){return this.tagType===t&&this.$input.attr("multiple")?this.items:this.items.join(this.settings.delimiter)},setValue:function(b){D(this,["change"],function(){this.clear();for(var c=a.isArray(b)?b:[b],d=0,e=c.length;e>d;d++)this.addItem(c[d])})},setActiveItem:function(b,c){var d,e,f,g,h,i,j,k,l=this;if("single"!==l.settings.mode){if(b=a(b),!b.length)return a(l.$activeItems).removeClass("active"),l.$activeItems=[],l.isFocused&&l.showInput(),void 0;if(d=c&&c.type.toLowerCase(),"mousedown"===d&&l.isShiftDown&&l.$activeItems.length){for(k=l.$control.children(".active:last"),g=Array.prototype.indexOf.apply(l.$control[0].childNodes,[k[0]]),h=Array.prototype.indexOf.apply(l.$control[0].childNodes,[b[0]]),g>h&&(j=g,g=h,h=j),e=g;h>=e;e++)i=l.$control[0].childNodes[e],-1===l.$activeItems.indexOf(i)&&(a(i).addClass("active"),l.$activeItems.push(i));c.preventDefault()}else"mousedown"===d&&l.isCtrlDown||"keydown"===d&&this.isShiftDown?b.hasClass("active")?(f=l.$activeItems.indexOf(b[0]),l.$activeItems.splice(f,1),b.removeClass("active")):l.$activeItems.push(b.addClass("active")[0]):(a(l.$activeItems).removeClass("active"),l.$activeItems=[b.addClass("active")[0]]);l.hideInput(),this.isFocused||l.focus()}},setActiveOption:function(b,c,d){var e,f,g,h,i,j=this;j.$activeOption&&j.$activeOption.removeClass("active"),j.$activeOption=null,b=a(b),b.length&&(j.$activeOption=b.addClass("active"),(c||!v(c))&&(e=j.$dropdown_content.height(),f=j.$activeOption.outerHeight(!0),c=j.$dropdown_content.scrollTop()||0,g=j.$activeOption.offset().top-j.$dropdown_content.offset().top+c,h=g,i=g-e+f,g+f>e+c?j.$dropdown_content.stop().animate({scrollTop:i},d?j.settings.scrollDuration:0):c>g&&j.$dropdown_content.stop().animate({scrollTop:h},d?j.settings.scrollDuration:0)))},selectAll:function(){this.$activeItems=Array.prototype.slice.apply(this.$control.children(":not(input)").addClass("active")),this.$activeItems.length&&(this.hideInput(),this.close()),this.focus()},hideInput:function(){var a=this;a.setTextboxValue(""),a.$control_input.css({opacity:0,position:"absolute",left:a.rtl?1e4:-1e4}),a.isInputHidden=!0},showInput:function(){this.$control_input.css({opacity:1,position:"relative",left:0}),this.isInputHidden=!1},focus:function(){var a=this;a.isDisabled||(a.ignoreFocus=!0,a.$control_input[0].focus(),window.setTimeout(function(){a.ignoreFocus=!1,a.onFocus()},0))},blur:function(){this.$control_input.trigger("blur")},getScoreFunction:function(a){return this.sifter.getScoreFunction(a,this.getSearchOptions())},getSearchOptions:function(){var a=this.settings,b=a.sortField;return"string"==typeof b&&(b={field:b}),{fields:a.searchField,conjunction:a.searchConjunction,sort:b}},search:function(b){var c,d,e,f=this,g=f.settings,h=this.getSearchOptions();if(g.score&&(e=f.settings.score.apply(this,[b]),"function"!=typeof e))throw new Error('Selectize "score" setting must be a function that returns a function');if(b!==f.lastQuery?(f.lastQuery=b,d=f.sifter.search(b,a.extend(h,{score:e})),f.currentResults=d):d=a.extend(!0,{},f.currentResults),g.hideSelected)for(c=d.items.length-1;c>=0;c--)-1!==f.items.indexOf(w(d.items[c].id))&&d.items.splice(c,1);return d},refreshOptions:function(b){var c,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s;"undefined"==typeof b&&(b=!0);var t=this,u=t.$control_input.val(),v=t.search(u),x=t.$dropdown_content,y=t.$activeOption&&w(t.$activeOption.attr("data-value"));if(g=v.items.length,"number"==typeof t.settings.maxOptions&&(g=Math.min(g,t.settings.maxOptions)),h={},t.settings.optgroupOrder)for(i=t.settings.optgroupOrder,c=0;cc;c++)for(j=t.options[v.items[c].id],k=t.render("option",j),l=j[t.settings.optgroupField]||"",m=a.isArray(l)?l:[l],e=0,f=m&&m.length;f>e;e++)l=m[e],t.optgroups.hasOwnProperty(l)||(l=""),h.hasOwnProperty(l)||(h[l]=[],i.push(l)),h[l].push(k);for(n=[],c=0,g=i.length;g>c;c++)l=i[c],t.optgroups.hasOwnProperty(l)&&h[l].length?(o=t.render("optgroup_header",t.optgroups[l])||"",o+=h[l].join(""),n.push(t.render("optgroup",a.extend({},t.optgroups[l],{html:o})))):n.push(h[l].join(""));if(x.html(n.join("")),t.settings.highlight&&v.query.length&&v.tokens.length)for(c=0,g=v.tokens.length;g>c;c++)d(x,v.tokens[c].regex);if(!t.settings.hideSelected)for(c=0,g=t.items.length;g>c;c++)t.getOption(t.items[c]).addClass("selected");p=t.settings.create&&v.query.length,p&&(x.prepend(t.render("option_create",{input:u})),s=a(x[0].childNodes[0])),t.hasOptions=v.items.length>0||p,t.hasOptions?(v.items.length>0?(r=y&&t.getOption(y),r&&r.length?q=r:"single"===t.settings.mode&&t.items.length&&(q=t.getOption(t.items[0])),q&&q.length||(q=s&&!t.settings.addPrecedence?t.getAdjacentOption(s,1):x.find("[data-selectable]:first"))):q=s,t.setActiveOption(q),b&&!t.isOpen&&t.open()):(t.setActiveOption(null),b&&t.isOpen&&t.close())},addOption:function(b){var c,d,e,f=this;if(a.isArray(b))for(c=0,d=b.length;d>c;c++)f.addOption(b[c]);else e=w(b[f.settings.valueField]),e&&!f.options.hasOwnProperty(e)&&(f.userOptions[e]=!0,f.options[e]=b,f.lastQuery=null,f.trigger("option_add",e,b))},addOptionGroup:function(a,b){this.optgroups[a]=b,this.trigger("optgroup_add",a,b)},updateOption:function(b,c){var d,e,f,g,h,i,j=this;if(b=w(b),f=w(c[j.settings.valueField]),j.options.hasOwnProperty(b)){if(!f)throw new Error("Value must be set in option data");f!==b&&(delete j.options[b],g=j.items.indexOf(b),-1!==g&&j.items.splice(g,1,f)),j.options[f]=c,h=j.renderCache.item,i=j.renderCache.option,v(h)&&(delete h[b],delete h[f]),v(i)&&(delete i[b],delete i[f]),-1!==j.items.indexOf(f)&&(d=j.getItem(b),e=a(j.render("item",c)),d.hasClass("active")&&e.addClass("active"),d.replaceWith(e)),j.isOpen&&j.refreshOptions(!1)}},removeOption:function(a){var b=this;a=w(a),delete b.userOptions[a],delete b.options[a],b.lastQuery=null,b.trigger("option_remove",a),b.removeItem(a)},clearOptions:function(){var a=this;a.loadedSearches={},a.userOptions={},a.options=a.sifter.items={},a.lastQuery=null,a.trigger("option_clear"),a.clear()},getOption:function(a){return this.getElementWithValue(a,this.$dropdown_content.find("[data-selectable]"))},getAdjacentOption:function(b,c){var d=this.$dropdown.find("[data-selectable]"),e=d.index(b)+c;return e>=0&&ed;d++)if(c[d].getAttribute("data-value")===b)return a(c[d]);return a()},getItem:function(a){return this.getElementWithValue(a,this.$control.children())},addItem:function(b){D(this,["change"],function(){var c,d,e,f,g=this,h=g.settings.mode;return b=w(b),-1!==g.items.indexOf(b)?("single"===h&&g.close(),void 0):(g.options.hasOwnProperty(b)&&("single"===h&&g.clear(),"multi"===h&&g.isFull()||(c=a(g.render("item",g.options[b])),g.items.splice(g.caretPos,0,b),g.insertAtCaret(c),g.refreshState(),g.isSetup&&(e=g.$dropdown_content.find("[data-selectable]"),d=g.getOption(b),f=g.getAdjacentOption(d,1).attr("data-value"),g.refreshOptions(g.isFocused&&"single"!==h),f&&g.setActiveOption(g.getOption(f)),!e.length||null!==g.settings.maxItems&&g.items.length>=g.settings.maxItems?g.close():g.positionDropdown(),g.updatePlaceholder(),g.trigger("item_add",b,c),g.updateOriginalInput()))),void 0)})},removeItem:function(a){var b,c,d,e=this;b="object"==typeof a?a:e.getItem(a),a=w(b.attr("data-value")),c=e.items.indexOf(a),-1!==c&&(b.remove(),b.hasClass("active")&&(d=e.$activeItems.indexOf(b[0]),e.$activeItems.splice(d,1)),e.items.splice(c,1),e.lastQuery=null,!e.settings.persist&&e.userOptions.hasOwnProperty(a)&&e.removeOption(a),c0),b.$control_input.data("grow",!c&&!d)},isFull:function(){return null!==this.settings.maxItems&&this.items.length>=this.settings.maxItems},updateOriginalInput:function(){var a,b,c,d=this;if("select"===d.$input[0].tagName.toLowerCase()){for(c=[],a=0,b=d.items.length;b>a;a++)c.push('');c.length||this.$input.attr("multiple")||c.push(''),d.$input.html(c.join(""))}else d.$input.val(d.getValue());d.isSetup&&d.trigger("change",d.$input.val())},updatePlaceholder:function(){if(this.settings.placeholder){var a=this.$control_input;this.items.length?a.removeAttr("placeholder"):a.attr("placeholder",this.settings.placeholder),a.triggerHandler("update")}},open:function(){var a=this;a.isLocked||a.isOpen||"multi"===a.settings.mode&&a.isFull()||(a.focus(),a.isOpen=!0,a.refreshState(),a.$dropdown.css({visibility:"hidden",display:"block"}),a.positionDropdown(),a.$dropdown.css({visibility:"visible"}),a.trigger("dropdown_open",a.$dropdown))},close:function(){var a=this,b=a.isOpen;"single"===a.settings.mode&&a.items.length&&a.hideInput(),a.isOpen=!1,a.$dropdown.hide(),a.setActiveOption(null),a.refreshState(),b&&a.trigger("dropdown_close",a.$dropdown)},positionDropdown:function(){var a=this.$control,b="body"===this.settings.dropdownParent?a.offset():a.position();b.top+=a.outerHeight(!0),this.$dropdown.css({width:a.outerWidth(),top:b.top,left:b.left})},clear:function(){var a=this;a.items.length&&(a.$control.children(":not(input)").remove(),a.items=[],a.setCaret(0),a.updatePlaceholder(),a.updateOriginalInput(),a.refreshState(),a.showInput(),a.trigger("clear"))},insertAtCaret:function(b){var c=Math.min(this.caretPos,this.items.length);0===c?this.$control.prepend(b):a(this.$control[0].childNodes[c]).before(b),this.setCaret(c+1)},deleteSelection:function(b){var c,d,e,f,g,h,i,j,k,l=this;if(e=b&&b.keyCode===n?-1:1,f=F(l.$control_input[0]),l.$activeOption&&!l.settings.hideSelected&&(i=l.getAdjacentOption(l.$activeOption,-1).attr("data-value")),g=[],l.$activeItems.length){for(k=l.$control.children(".active:"+(e>0?"last":"first")),h=l.$control.children(":not(input)").index(k),e>0&&h++,c=0,d=l.$activeItems.length;d>c;c++)g.push(a(l.$activeItems[c]).attr("data-value"));b&&(b.preventDefault(),b.stopPropagation())}else(l.isFocused||"single"===l.settings.mode)&&l.items.length&&(0>e&&0===f.start&&0===f.length?g.push(l.items[l.caretPos-1]):e>0&&f.start===l.$control_input.val().length&&g.push(l.items[l.caretPos]));if(!g.length||"function"==typeof l.settings.onDelete&&l.settings.onDelete.apply(l,[g])===!1)return!1;for("undefined"!=typeof h&&l.setCaret(h);g.length;)l.removeItem(g.pop());return l.showInput(),l.refreshOptions(!0),i&&(j=l.getOption(i),j.length&&l.setActiveOption(j)),!0},advanceSelection:function(a,b){var c,d,e,f,g,h,i=this;0!==a&&(i.rtl&&(a*=-1),c=a>0?"last":"first",d=F(i.$control_input[0]),i.isFocused&&!i.isInputHidden?(f=i.$control_input.val().length,g=0>a?0===d.start&&0===d.length:d.start===f,g&&!f&&i.advanceCaret(a,b)):(h=i.$control.children(".active:"+c),h.length&&(e=i.$control.children(":not(input)").index(h),i.setActiveItem(null),i.setCaret(a>0?e+1:e))))},advanceCaret:function(a,b){var c,d,e=this;0!==a&&(c=a>0?"next":"prev",e.isShiftDown?(d=e.$control_input[c](),d.length&&(e.hideInput(),e.setActiveItem(d),b&&b.preventDefault())):e.setCaret(e.caretPos+a))},setCaret:function(b){var c=this;b="single"===c.settings.mode?c.items.length:Math.max(0,Math.min(c.items.length,b));var d,e,f,g;for(f=c.$control.children(":not(input)"),d=0,e=f.length;e>d;d++)g=a(f[d]).detach(),b>d?c.$control_input.before(g):c.$control.append(g);c.caretPos=b},lock:function(){this.close(),this.isLocked=!0,this.refreshState()},unlock:function(){this.isLocked=!1,this.refreshState()},disable:function(){var a=this;a.$input.prop("disabled",!0),a.isDisabled=!0,a.lock()},enable:function(){var a=this;a.$input.prop("disabled",!1),a.isDisabled=!1,a.unlock()},destroy:function(){var b=this,c=b.eventNS,d=b.revertSettings;b.trigger("destroy"),b.off(),b.$wrapper.remove(),b.$dropdown.remove(),b.$input.html("").append(d.$children).removeAttr("tabindex").attr({tabindex:d.tabindex}).show(),a(window).off(c),a(document).off(c),a(document.body).off(c),delete b.$input[0].selectize},render:function(a,b){var c,d,e="",f=!1,g=this,h=/^[\t ]*<([a-z][a-z0-9\-_]*(?:\:[a-z][a-z0-9\-_]*)?)/i;return("option"===a||"item"===a)&&(c=w(b[g.settings.valueField]),f=!!c),f&&(v(g.renderCache[a])||(g.renderCache[a]={}),g.renderCache[a].hasOwnProperty(c))?g.renderCache[a][c]:(e=g.settings.render[a].apply(this,[b,x]),("option"===a||"option_create"===a)&&(e=e.replace(h,"<$1 data-selectable")),"optgroup"===a&&(d=b[g.settings.optgroupValueField]||"",e=e.replace(h,'<$1 data-group="'+y(x(d))+'"')),("option"===a||"item"===a)&&(e=e.replace(h,'<$1 data-value="'+y(x(c||""))+'"')),f&&(g.renderCache[a][c]=e),e)}}),J.count=0,J.defaults={plugins:[],delimiter:",",persist:!0,diacritics:!0,create:!1,createOnBlur:!1,highlight:!0,openOnFocus:!0,maxOptions:1e3,maxItems:null,hideSelected:null,addPrecedence:!1,preload:!1,scrollDuration:60,loadThrottle:300,dataAttr:"data-data",optgroupField:"optgroup",valueField:"value",labelField:"text",optgroupLabelField:"label",optgroupValueField:"value",optgroupOrder:null,sortField:"$order",searchField:["text"],searchConjunction:"and",mode:null,wrapperClass:"selectize-control",inputClass:"selectize-input",dropdownClass:"selectize-dropdown",dropdownContentClass:"selectize-dropdown-content",dropdownParent:null,render:{}},a.fn.selectize=function(b){var c=a.fn.selectize.defaults,d=a.extend({},c,b),e=d.dataAttr,f=d.labelField,g=d.valueField,h=d.optgroupField,i=d.optgroupLabelField,j=d.optgroupValueField,k=function(b,c){var e,h,i,j,k=a.trim(b.val()||""); -if(k.length){for(i=k.split(d.delimiter),e=0,h=i.length;h>e;e++)j={},j[f]=i[e],j[g]=i[e],c.options[i[e]]=j;c.items=i}},l=function(b,c){var d,k,l,m,n=0,o=c.options,p=function(a){var b=e&&a.attr(e);return"string"==typeof b&&b.length?JSON.parse(b):null},q=function(b,d){var e,i;if(b=a(b),e=b.attr("value")||"",e.length){if(o.hasOwnProperty(e))return d&&(o[e].optgroup?a.isArray(o[e].optgroup)?o[e].optgroup.push(d):o[e].optgroup=[o[e].optgroup,d]:o[e].optgroup=d),void 0;i=p(b)||{},i[f]=i[f]||b.text(),i[g]=i[g]||e,i[h]=i[h]||d,i.$order=++n,o[e]=i,b.is(":selected")&&c.items.push(e)}},r=function(b){var d,e,f,g,h;for(b=a(b),f=b.attr("label"),f&&(g=p(b)||{},g[i]=f,g[j]=f,c.optgroups[f]=g),h=a("option",b),d=0,e=h.length;e>d;d++)q(h[d],f)};for(c.maxItems=b.attr("multiple")?null:1,m=b.children(),d=0,k=m.length;k>d;d++)l=m[d].tagName.toLowerCase(),"optgroup"===l?r(m[d]):"option"===l&&q(m[d])};return this.each(function(){if(!this.selectize){var d,e=a(this),f=this.tagName.toLowerCase(),g={placeholder:e.children('option[value=""]').text()||e.attr("placeholder"),options:{},optgroups:{},items:[]};"select"===f?l(e,g):k(e,g),d=new J(e,a.extend(!0,{},c,g,b)),e.data("selectize",d),e.addClass("selectized")}})},a.fn.selectize.defaults=J.defaults,J.define("drag_drop",function(){if(!a.fn.sortable)throw new Error('The "drag_drop" plugin requires jQuery UI "sortable".');if("multi"===this.settings.mode){var b=this;b.lock=function(){var a=b.lock;return function(){var c=b.$control.data("sortable");return c&&c.disable(),a.apply(b,arguments)}}(),b.unlock=function(){var a=b.unlock;return function(){var c=b.$control.data("sortable");return c&&c.enable(),a.apply(b,arguments)}}(),b.setup=function(){var c=b.setup;return function(){c.apply(this,arguments);var d=b.$control.sortable({items:"[data-value]",forcePlaceholderSize:!0,disabled:b.isLocked,start:function(a,b){b.placeholder.css("width",b.helper.css("width")),d.css({overflow:"visible"})},stop:function(){d.css({overflow:"hidden"});var c=b.$activeItems?b.$activeItems.slice():null,e=[];d.children("[data-value]").each(function(){e.push(a(this).attr("data-value"))}),b.setValue(e),b.setActiveItem(c)}})}}()}}),J.define("dropdown_header",function(b){var c=this;b=a.extend({title:"Untitled",headerClass:"selectize-dropdown-header",titleRowClass:"selectize-dropdown-header-title",labelClass:"selectize-dropdown-header-label",closeClass:"selectize-dropdown-header-close",html:function(a){return'
    '+'
    '+''+a.title+""+'×'+"
    "+"
    "}},b),c.setup=function(){var d=c.setup;return function(){d.apply(c,arguments),c.$dropdown_header=a(b.html(b)),c.$dropdown.prepend(c.$dropdown_header)}}()}),J.define("optgroup_columns",function(b){var c=this;b=a.extend({equalizeWidth:!0,equalizeHeight:!0},b),this.getAdjacentOption=function(b,c){var d=b.closest("[data-group]").find("[data-selectable]"),e=d.index(b)+c;return e>=0&&ed;d++)f=Math.max(f,j.eq(d).height());j.css({height:f})}b.equalizeWidth&&(i=c.$dropdown_content.innerWidth(),g=Math.round(i/e),j.css({width:g}),e>1&&(h=i-g*(e-1),j.eq(e-1).css({width:h})))}};(b.equalizeHeight||b.equalizeWidth)&&(z.after(this,"positionDropdown",d),z.after(this,"refreshOptions",d))}),J.define("remove_button",function(b){if("single"!==this.settings.mode){b=a.extend({label:"×",title:"Remove",className:"remove",append:!0},b);var c=this,d=''+b.label+"",e=function(a,b){var c=a.search(/(<\/[^>]+>\s*)$/);return a.substring(0,c)+b+a.substring(c)};this.setup=function(){var f=c.setup;return function(){if(b.append){var g=c.settings.render.item;c.settings.render.item=function(){return e(g.apply(this,arguments),d)}}f.apply(this,arguments),this.$control.on("click","."+b.className,function(b){if(b.preventDefault(),!c.isLocked){var d=a(b.target).parent();c.setActiveItem(d),c.deleteSelection()&&c.setCaret(c.items.length)}})}}()}}),J.define("restore_on_backspace",function(a){var b=this;a.text=a.text||function(a){return a[this.settings.labelField]},this.onKeyDown=function(){var c=b.onKeyDown;return function(b){var d,e;return b.keyCode===n&&""===this.$control_input.val()&&!this.$activeItems.length&&(d=this.caretPos-1,d>=0&&db;b++){if(f=e(j[b]),this.settings.diacritics)for(h in g)g.hasOwnProperty(h)&&(f=f.replace(new RegExp(h,"g"),g[h]));i.push({string:j[b],regex:new RegExp(f,"i")})}return i},a.prototype.iterator=function(a,b){var c;c=f(a)?Array.prototype.forEach||function(a){for(var b=0,c=this.length;c>b;b++)a(this[b],b,this)}:function(a){for(var b in this)this.hasOwnProperty(b)&&a(this[b],b,this)},c.apply(a,[b])},a.prototype.getScoreFunction=function(a,b){var c,d,e,f;c=this,a=c.prepareSearch(a,b),e=a.tokens,d=a.options.fields,f=e.length;var g=function(a,b){var c,d;return a?(a=String(a||""),d=a.search(b.regex),-1===d?0:(c=b.string.length/a.length,0===d&&(c+=.5),c)):0},h=function(){var a=d.length;return a?1===a?function(a,b){return g(b[d[0]],a)}:function(b,c){for(var e=0,f=0;a>e;e++)f+=g(c[d[e]],b);return f/a}:function(){return 0}}();return f?1===f?function(a){return h(e[0],a)}:"and"===a.options.conjunction?function(a){for(var b,c=0,d=0;f>c;c++){if(b=h(e[c],a),0>=b)return 0;d+=b}return d/f}:function(a){for(var b=0,c=0;f>b;b++)c+=h(e[b],a);return c/f}:function(){return 0}},a.prototype.getSortFunction=function(a,c){var d,e,f,g,h,i,j,k,l,m,n;if(f=this,a=f.prepareSearch(a,c),n=!a.query&&c.sort_empty||c.sort,l=function(a,b){return"$score"===a?b.score:f.items[b.id][a]},h=[],n)for(d=0,e=n.length;e>d;d++)(a.query||"$score"!==n[d].field)&&h.push(n[d]);if(a.query){for(m=!0,d=0,e=h.length;e>d;d++)if("$score"===h[d].field){m=!1;break}m&&h.unshift({field:"$score",direction:"desc"})}else for(d=0,e=h.length;e>d;d++)if("$score"===h[d].field){h.splice(d,1);break}for(k=[],d=0,e=h.length;e>d;d++)k.push("desc"===h[d].direction?-1:1);return i=h.length,i?1===i?(g=h[0].field,j=k[0],function(a,c){return j*b(l(g,a),l(g,c))}):function(a,c){var d,e,f;for(d=0;i>d;d++)if(f=h[d].field,e=k[d]*b(l(f,a),l(f,c)))return e;return 0}:null},a.prototype.prepareSearch=function(a,b){if("object"==typeof a)return a;b=c({},b);var d=b.fields,e=b.sort,g=b.sort_empty;return d&&!f(d)&&(b.fields=[d]),e&&!f(e)&&(b.sort=[e]),g&&!f(g)&&(b.sort_empty=[g]),{options:b,query:String(a||"").toLowerCase(),tokens:this.tokenize(a),total:0,items:[]}},a.prototype.search=function(a,b){var c,d,e,f,g=this;return d=this.prepareSearch(a,b),b=d.options,a=d.query,f=b.score||g.getScoreFunction(d),a.length?g.iterator(g.items,function(a,e){c=f(a),(b.filter===!1||c>0)&&d.items.push({score:c,id:e})}):g.iterator(g.items,function(a,b){d.items.push({score:1,id:b})}),e=g.getSortFunction(d,b),e&&d.items.sort(e),d.total=d.items.length,"number"==typeof b.limit&&(d.items=d.items.slice(0,b.limit)),d};var b=function(a,b){return"number"==typeof a&&"number"==typeof b?a>b?1:b>a?-1:0:(a=h(String(a||"")),b=h(String(b||"")),a>b?1:b>a?-1:0)},c=function(a){var b,c,d,e;for(b=1,c=arguments.length;c>b;b++)if(e=arguments[b])for(d in e)e.hasOwnProperty(d)&&(a[d]=e[d]);return a},d=function(a){return(a+"").replace(/^\s+|\s+$|/g,"")},e=function(a){return(a+"").replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")},f=Array.isArray||$&&$.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)},g={a:"[aÀÁÂÃÄÅàáâãäåĀāąĄ]",c:"[cÇçćĆčČ]",d:"[dđĐďĎ]",e:"[eÈÉÊËèéêëěĚĒēęĘ]",i:"[iÌÍÎÏìíîïĪī]",l:"[lłŁ]",n:"[nÑñňŇńŃ]",o:"[oÒÓÔÕÕÖØòóôõöøŌō]",r:"[rřŘ]",s:"[sŠšśŚ]",t:"[tťŤ]",u:"[uÙÚÛÜùúûüůŮŪū]",y:"[yŸÿýÝ]",z:"[zŽžżŻźŹ]"},h=function(){var a,b,c,d,e="",f={};for(c in g)if(g.hasOwnProperty(c))for(d=g[c].substring(2,g[c].length-1),e+=d,a=0,b=d.length;b>a;a++)f[d.charAt(a)]=c;var h=new RegExp("["+e+"]","g");return function(a){return a.replace(h,function(a){return f[a]}).toLowerCase()}}();return a}),function(a,b){"function"==typeof define&&define.amd?define("microplugin",b):"object"==typeof exports?module.exports=b():a.MicroPlugin=b()}(this,function(){var a={};a.mixin=function(a){a.plugins={},a.prototype.initializePlugins=function(a){var c,d,e,f=this,g=[];if(f.plugins={names:[],settings:{},requested:{},loaded:{}},b.isArray(a))for(c=0,d=a.length;d>c;c++)"string"==typeof a[c]?g.push(a[c]):(f.plugins.settings[a[c].name]=a[c].options,g.push(a[c].name));else if(a)for(e in a)a.hasOwnProperty(e)&&(f.plugins.settings[e]=a[e],g.push(e));for(;g.length;)f.require(g.shift())},a.prototype.loadPlugin=function(b){var c=this,d=c.plugins,e=a.plugins[b];if(!a.plugins.hasOwnProperty(b))throw new Error('Unable to find "'+b+'" plugin');d.requested[b]=!0,d.loaded[b]=e.fn.apply(c,[c.plugins.settings[b]||{}]),d.names.push(b)},a.prototype.require=function(a){var b=this,c=b.plugins;if(!b.plugins.loaded.hasOwnProperty(a)){if(c.requested[a])throw new Error('Plugin has circular dependency ("'+a+'")');b.loadPlugin(a)}return c.loaded[a]},a.define=function(b,c){a.plugins[b]={name:b,fn:c}}};var b={isArray:Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)}};return a}),function(a,b){"function"==typeof define&&define.amd?define("selectize",["jquery","sifter","microplugin"],b):"object"==typeof exports?module.exports=b(require("jquery"),require("sifter"),require("microplugin")):a.Selectize=b(a.jQuery,a.Sifter,a.MicroPlugin)}(this,function(a,b,c){"use strict";var d=function(a,b){if("string"!=typeof b||b.length){var c="string"==typeof b?new RegExp(b,"i"):b,d=function(a){var b=0;if(3===a.nodeType){var e=a.data.search(c);if(e>=0&&a.data.length>0){var f=a.data.match(c),g=document.createElement("span");g.className="highlight";var h=a.splitText(e),i=(h.splitText(f[0].length),h.cloneNode(!0));g.appendChild(i),h.parentNode.replaceChild(g,h),b=1}}else if(1===a.nodeType&&a.childNodes&&!/(script|style)/i.test(a.tagName))for(var j=0;j/g,">").replace(/"/g,""")},B=function(a){return(a+"").replace(/\$/g,"$$$$")},C={};C.before=function(a,b,c){var d=a[b];a[b]=function(){return c.apply(a,arguments),d.apply(a,arguments)}},C.after=function(a,b,c){var d=a[b];a[b]=function(){var b=d.apply(a,arguments);return c.apply(a,arguments),b}};var D=function(a){var b=!1;return function(){b||(b=!0,a.apply(this,arguments))}},E=function(a,b){var c;return function(){var d=this,e=arguments;window.clearTimeout(c),c=window.setTimeout(function(){a.apply(d,e)},b)}},F=function(a,b,c){var d,e=a.trigger,f={};a.trigger=function(){var c=arguments[0];return-1===b.indexOf(c)?e.apply(a,arguments):void(f[c]=arguments)},c.apply(a,[]),a.trigger=e;for(d in f)f.hasOwnProperty(d)&&e.apply(a,f[d])},G=function(a,b,c,d){a.on(b,c,function(b){for(var c=b.target;c&&c.parentNode!==a[0];)c=c.parentNode;return b.currentTarget=c,d.apply(this,[b])})},H=function(a){var b={};if("selectionStart"in a)b.start=a.selectionStart,b.length=a.selectionEnd-b.start;else if(document.selection){a.focus();var c=document.selection.createRange(),d=document.selection.createRange().text.length;c.moveStart("character",-a.value.length),b.start=c.text.length-d,b.length=d}return b},I=function(a,b,c){var d,e,f={};if(c)for(d=0,e=c.length;e>d;d++)f[c[d]]=a.css(c[d]);else f=a.css();b.css(f)},J=function(b,c){if(!b)return 0;var d=a("").css({position:"absolute",top:-99999,left:-99999,width:"auto",padding:0,whiteSpace:"pre"}).text(b).appendTo("body");I(c,d,["letterSpacing","fontSize","fontFamily","fontWeight","textTransform"]);var e=d.width();return d.remove(),e},K=function(a){var b=null,c=function(c,d){var e,f,g,h,i,j,k,l;c=c||window.event||{},d=d||{},c.metaKey||c.altKey||(d.force||a.data("grow")!==!1)&&(e=a.val(),c.type&&"keydown"===c.type.toLowerCase()&&(f=c.keyCode,g=f>=97&&122>=f||f>=65&&90>=f||f>=48&&57>=f||32===f,f===q||f===p?(l=H(a[0]),l.length?e=e.substring(0,l.start)+e.substring(l.start+l.length):f===p&&l.start?e=e.substring(0,l.start-1)+e.substring(l.start+1):f===q&&"undefined"!=typeof l.start&&(e=e.substring(0,l.start)+e.substring(l.start+1))):g&&(j=c.shiftKey,k=String.fromCharCode(c.keyCode),k=j?k.toUpperCase():k.toLowerCase(),e+=k)),h=a.attr("placeholder"),!e&&h&&(e=h),i=J(e,a)+4,i!==b&&(b=i,a.width(i),a.triggerHandler("resize")))};a.on("keydown keyup update blur",c),c()},L=function(c,d){var e,f,g,h,i=this;h=c[0],h.selectize=i;var j=window.getComputedStyle&&window.getComputedStyle(h,null);if(g=j?j.getPropertyValue("direction"):h.currentStyle&&h.currentStyle.direction,g=g||c.parents("[dir]:first").attr("dir")||"",a.extend(i,{order:0,settings:d,$input:c,tabIndex:c.attr("tabindex")||"",tagType:"select"===h.tagName.toLowerCase()?v:w,rtl:/rtl/i.test(g),eventNS:".selectize"+ ++L.count,highlightedValue:null,isOpen:!1,isDisabled:!1,isRequired:c.is("[required]"),isInvalid:!1,isLocked:!1,isFocused:!1,isInputHidden:!1,isSetup:!1,isShiftDown:!1,isCmdDown:!1,isCtrlDown:!1,ignoreFocus:!1,ignoreBlur:!1,ignoreHover:!1,hasOptions:!1,currentResults:null,lastValue:"",caretPos:0,loading:0,loadedSearches:{},$activeOption:null,$activeItems:[],optgroups:{},options:{},userOptions:{},items:[],renderCache:{},onSearchChange:null===d.loadThrottle?i.onSearchChange:E(i.onSearchChange,d.loadThrottle)}),i.sifter=new b(this.options,{diacritics:d.diacritics}),i.settings.options){for(e=0,f=i.settings.options.length;f>e;e++)i.registerOption(i.settings.options[e]);delete i.settings.options}if(i.settings.optgroups){for(e=0,f=i.settings.optgroups.length;f>e;e++)i.registerOptionGroup(i.settings.optgroups[e]);delete i.settings.optgroups}i.settings.mode=i.settings.mode||(1===i.settings.maxItems?"single":"multi"),"boolean"!=typeof i.settings.hideSelected&&(i.settings.hideSelected="multi"===i.settings.mode),i.initializePlugins(i.settings.plugins),i.setupCallbacks(),i.setupTemplates(),i.setup()};return e.mixin(L),c.mixin(L),a.extend(L.prototype,{setup:function(){var b,c,d,e,g,h,i,j,k,l=this,m=l.settings,n=l.eventNS,o=a(window),p=a(document),q=l.$input;if(i=l.settings.mode,j=q.attr("class")||"",b=a("
    ").addClass(m.wrapperClass).addClass(j).addClass(i),c=a("
    ").addClass(m.inputClass).addClass("items").appendTo(b),d=a('').appendTo(c).attr("tabindex",q.is(":disabled")?"-1":l.tabIndex),h=a(m.dropdownParent||b),e=a("
    ").addClass(m.dropdownClass).addClass(i).hide().appendTo(h),g=a("
    ").addClass(m.dropdownContentClass).appendTo(e),l.settings.copyClassesToDropdown&&e.addClass(j),b.css({width:q[0].style.width}),l.plugins.names.length&&(k="plugin-"+l.plugins.names.join(" plugin-"),b.addClass(k),e.addClass(k)),(null===m.maxItems||m.maxItems>1)&&l.tagType===v&&q.attr("multiple","multiple"),l.settings.placeholder&&d.attr("placeholder",m.placeholder),!l.settings.splitOn&&l.settings.delimiter){var u=l.settings.delimiter.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&");l.settings.splitOn=new RegExp("\\s*"+u+"+\\s*")}q.attr("autocorrect")&&d.attr("autocorrect",q.attr("autocorrect")),q.attr("autocapitalize")&&d.attr("autocapitalize",q.attr("autocapitalize")),l.$wrapper=b,l.$control=c,l.$control_input=d,l.$dropdown=e,l.$dropdown_content=g,e.on("mouseenter","[data-selectable]",function(){return l.onOptionHover.apply(l,arguments)}),e.on("mousedown click","[data-selectable]",function(){return l.onOptionSelect.apply(l,arguments)}),G(c,"mousedown","*:not(input)",function(){return l.onItemSelect.apply(l,arguments)}),K(d),c.on({mousedown:function(){return l.onMouseDown.apply(l,arguments)},click:function(){return l.onClick.apply(l,arguments)}}),d.on({mousedown:function(a){a.stopPropagation()},keydown:function(){return l.onKeyDown.apply(l,arguments)},keyup:function(){return l.onKeyUp.apply(l,arguments)},keypress:function(){return l.onKeyPress.apply(l,arguments)},resize:function(){l.positionDropdown.apply(l,[])},blur:function(){return l.onBlur.apply(l,arguments)},focus:function(){return l.ignoreBlur=!1,l.onFocus.apply(l,arguments)},paste:function(){return l.onPaste.apply(l,arguments)}}),p.on("keydown"+n,function(a){l.isCmdDown=a[f?"metaKey":"ctrlKey"],l.isCtrlDown=a[f?"altKey":"ctrlKey"],l.isShiftDown=a.shiftKey}),p.on("keyup"+n,function(a){a.keyCode===t&&(l.isCtrlDown=!1),a.keyCode===r&&(l.isShiftDown=!1),a.keyCode===s&&(l.isCmdDown=!1)}),p.on("mousedown"+n,function(a){if(l.isFocused){if(a.target===l.$dropdown[0]||a.target.parentNode===l.$dropdown[0])return!1;l.$control.has(a.target).length||a.target===l.$control[0]||l.blur(a.target)}}),o.on(["scroll"+n,"resize"+n].join(" "),function(){l.isOpen&&l.positionDropdown.apply(l,arguments)}),o.on("mousemove"+n,function(){l.ignoreHover=!1}),this.revertSettings={$children:q.children().detach(),tabindex:q.attr("tabindex")},q.attr("tabindex",-1).hide().after(l.$wrapper),a.isArray(m.items)&&(l.setValue(m.items),delete m.items),x&&q.on("invalid"+n,function(a){a.preventDefault(),l.isInvalid=!0,l.refreshState()}),l.updateOriginalInput(),l.refreshItems(),l.refreshState(),l.updatePlaceholder(),l.isSetup=!0,q.is(":disabled")&&l.disable(),l.on("change",this.onChange),q.data("selectize",l),q.addClass("selectized"),l.trigger("initialize"),m.preload===!0&&l.onSearchChange("")},setupTemplates:function(){var b=this,c=b.settings.labelField,d=b.settings.optgroupLabelField,e={optgroup:function(a){return'
    '+a.html+"
    "},optgroup_header:function(a,b){return'
    '+b(a[d])+"
    "},option:function(a,b){return'
    '+b(a[c])+"
    "},item:function(a,b){return'
    '+b(a[c])+"
    "},option_create:function(a,b){return'
    Add '+b(a.input)+"
    "}};b.settings.render=a.extend({},e,b.settings.render)},setupCallbacks:function(){var a,b,c={initialize:"onInitialize",change:"onChange",item_add:"onItemAdd",item_remove:"onItemRemove",clear:"onClear",option_add:"onOptionAdd",option_remove:"onOptionRemove",option_clear:"onOptionClear",optgroup_add:"onOptionGroupAdd",optgroup_remove:"onOptionGroupRemove",optgroup_clear:"onOptionGroupClear",dropdown_open:"onDropdownOpen",dropdown_close:"onDropdownClose",type:"onType",load:"onLoad",focus:"onFocus",blur:"onBlur"};for(a in c)c.hasOwnProperty(a)&&(b=this.settings[c[a]],b&&this.on(a,b))},onClick:function(a){var b=this;b.isFocused||(b.focus(),a.preventDefault())},onMouseDown:function(b){{var c=this,d=b.isDefaultPrevented();a(b.target)}if(c.isFocused){if(b.target!==c.$control_input[0])return"single"===c.settings.mode?c.isOpen?c.close():c.open():d||c.setActiveItem(null),!1}else d||window.setTimeout(function(){c.focus()},0)},onChange:function(){this.$input.trigger("change")},onPaste:function(b){var c=this;c.isFull()||c.isInputHidden||c.isLocked?b.preventDefault():c.settings.splitOn&&setTimeout(function(){for(var b=a.trim(c.$control_input.val()||"").split(c.settings.splitOn),d=0,e=b.length;e>d;d++)c.createItem(b[d])},0)},onKeyPress:function(a){if(this.isLocked)return a&&a.preventDefault();var b=String.fromCharCode(a.keyCode||a.which);return this.settings.create&&"multi"===this.settings.mode&&b===this.settings.delimiter?(this.createItem(),a.preventDefault(),!1):void 0},onKeyDown:function(a){var b=(a.target===this.$control_input[0],this);if(b.isLocked)return void(a.keyCode!==u&&a.preventDefault());switch(a.keyCode){case g:if(b.isCmdDown)return void b.selectAll();break;case i:return void(b.isOpen&&(a.preventDefault(),a.stopPropagation(),b.close()));case o:if(!a.ctrlKey||a.altKey)break;case n:if(!b.isOpen&&b.hasOptions)b.open();else if(b.$activeOption){b.ignoreHover=!0;var c=b.getAdjacentOption(b.$activeOption,1);c.length&&b.setActiveOption(c,!0,!0)}return void a.preventDefault();case l:if(!a.ctrlKey||a.altKey)break;case k:if(b.$activeOption){b.ignoreHover=!0;var d=b.getAdjacentOption(b.$activeOption,-1);d.length&&b.setActiveOption(d,!0,!0)}return void a.preventDefault();case h:return void(b.isOpen&&b.$activeOption&&(b.onOptionSelect({currentTarget:b.$activeOption}),a.preventDefault()));case j:return void b.advanceSelection(-1,a);case m:return void b.advanceSelection(1,a);case u:return b.settings.selectOnTab&&b.isOpen&&b.$activeOption&&(b.onOptionSelect({currentTarget:b.$activeOption}),b.isFull()||a.preventDefault()),void(b.settings.create&&b.createItem()&&a.preventDefault());case p:case q:return void b.deleteSelection(a)}return!b.isFull()&&!b.isInputHidden||(f?a.metaKey:a.ctrlKey)?void 0:void a.preventDefault()},onKeyUp:function(a){var b=this;if(b.isLocked)return a&&a.preventDefault();var c=b.$control_input.val()||"";b.lastValue!==c&&(b.lastValue=c,b.onSearchChange(c),b.refreshOptions(),b.trigger("type",c))},onSearchChange:function(a){var b=this,c=b.settings.load;c&&(b.loadedSearches.hasOwnProperty(a)||(b.loadedSearches[a]=!0,b.load(function(d){c.apply(b,[a,d])})))},onFocus:function(a){var b=this,c=b.isFocused;return b.isDisabled?(b.blur(),a&&a.preventDefault(),!1):void(b.ignoreFocus||(b.isFocused=!0,"focus"===b.settings.preload&&b.onSearchChange(""),c||b.trigger("focus"),b.$activeItems.length||(b.showInput(),b.setActiveItem(null),b.refreshOptions(!!b.settings.openOnFocus)),b.refreshState()))},onBlur:function(a,b){var c=this;if(c.isFocused&&(c.isFocused=!1,!c.ignoreFocus)){if(!c.ignoreBlur&&document.activeElement===c.$dropdown_content[0])return c.ignoreBlur=!0,void c.onFocus(a);var d=function(){c.close(),c.setTextboxValue(""),c.setActiveItem(null),c.setActiveOption(null),c.setCaret(c.items.length),c.refreshState(),(b||document.body).focus(),c.ignoreFocus=!1,c.trigger("blur")};c.ignoreFocus=!0,c.settings.create&&c.settings.createOnBlur?c.createItem(null,!1,d):d()}},onOptionHover:function(a){this.ignoreHover||this.setActiveOption(a.currentTarget,!1)},onOptionSelect:function(b){var c,d,e=this;b.preventDefault&&(b.preventDefault(),b.stopPropagation()),d=a(b.currentTarget),d.hasClass("create")?e.createItem(null,function(){e.settings.closeAfterSelect&&e.close()}):(c=d.attr("data-value"),"undefined"!=typeof c&&(e.lastQuery=null,e.setTextboxValue(""),e.addItem(c),e.settings.closeAfterSelect?e.close():!e.settings.hideSelected&&b.type&&/mouse/.test(b.type)&&e.setActiveOption(e.getOption(c))))},onItemSelect:function(a){var b=this;b.isLocked||"multi"===b.settings.mode&&(a.preventDefault(),b.setActiveItem(a.currentTarget,a))},load:function(a){var b=this,c=b.$wrapper.addClass(b.settings.loadingClass);b.loading++,a.apply(b,[function(a){b.loading=Math.max(b.loading-1,0),a&&a.length&&(b.addOption(a),b.refreshOptions(b.isFocused&&!b.isInputHidden)),b.loading||c.removeClass(b.settings.loadingClass),b.trigger("load",a)}])},setTextboxValue:function(a){var b=this.$control_input,c=b.val()!==a;c&&(b.val(a).triggerHandler("update"),this.lastValue=a)},getValue:function(){return this.tagType===v&&this.$input.attr("multiple")?this.items:this.items.join(this.settings.delimiter)},setValue:function(a,b){var c=b?[]:["change"];F(this,c,function(){this.clear(b),this.addItems(a,b)})},setActiveItem:function(b,c){var d,e,f,g,h,i,j,k,l=this;if("single"!==l.settings.mode){if(b=a(b),!b.length)return a(l.$activeItems).removeClass("active"),l.$activeItems=[],void(l.isFocused&&l.showInput());if(d=c&&c.type.toLowerCase(),"mousedown"===d&&l.isShiftDown&&l.$activeItems.length){for(k=l.$control.children(".active:last"),g=Array.prototype.indexOf.apply(l.$control[0].childNodes,[k[0]]),h=Array.prototype.indexOf.apply(l.$control[0].childNodes,[b[0]]),g>h&&(j=g,g=h,h=j),e=g;h>=e;e++)i=l.$control[0].childNodes[e],-1===l.$activeItems.indexOf(i)&&(a(i).addClass("active"),l.$activeItems.push(i));c.preventDefault()}else"mousedown"===d&&l.isCtrlDown||"keydown"===d&&this.isShiftDown?b.hasClass("active")?(f=l.$activeItems.indexOf(b[0]),l.$activeItems.splice(f,1),b.removeClass("active")):l.$activeItems.push(b.addClass("active")[0]):(a(l.$activeItems).removeClass("active"),l.$activeItems=[b.addClass("active")[0]]);l.hideInput(),this.isFocused||l.focus()}},setActiveOption:function(b,c,d){var e,f,g,h,i,j=this;j.$activeOption&&j.$activeOption.removeClass("active"),j.$activeOption=null,b=a(b),b.length&&(j.$activeOption=b.addClass("active"),(c||!y(c))&&(e=j.$dropdown_content.height(),f=j.$activeOption.outerHeight(!0),c=j.$dropdown_content.scrollTop()||0,g=j.$activeOption.offset().top-j.$dropdown_content.offset().top+c,h=g,i=g-e+f,g+f>e+c?j.$dropdown_content.stop().animate({scrollTop:i},d?j.settings.scrollDuration:0):c>g&&j.$dropdown_content.stop().animate({scrollTop:h},d?j.settings.scrollDuration:0)))},selectAll:function(){var a=this;"single"!==a.settings.mode&&(a.$activeItems=Array.prototype.slice.apply(a.$control.children(":not(input)").addClass("active")),a.$activeItems.length&&(a.hideInput(),a.close()),a.focus())},hideInput:function(){var a=this;a.setTextboxValue(""),a.$control_input.css({opacity:0,position:"absolute",left:a.rtl?1e4:-1e4}),a.isInputHidden=!0},showInput:function(){this.$control_input.css({opacity:1,position:"relative",left:0}),this.isInputHidden=!1},focus:function(){var a=this;a.isDisabled||(a.ignoreFocus=!0,a.$control_input[0].focus(),window.setTimeout(function(){a.ignoreFocus=!1,a.onFocus()},0))},blur:function(a){this.$control_input[0].blur(),this.onBlur(null,a)},getScoreFunction:function(a){return this.sifter.getScoreFunction(a,this.getSearchOptions())},getSearchOptions:function(){var a=this.settings,b=a.sortField;return"string"==typeof b&&(b=[{field:b}]),{fields:a.searchField,conjunction:a.searchConjunction,sort:b}},search:function(b){var c,d,e,f=this,g=f.settings,h=this.getSearchOptions();if(g.score&&(e=f.settings.score.apply(this,[b]),"function"!=typeof e))throw new Error('Selectize "score" setting must be a function that returns a function');if(b!==f.lastQuery?(f.lastQuery=b,d=f.sifter.search(b,a.extend(h,{score:e})),f.currentResults=d):d=a.extend(!0,{},f.currentResults),g.hideSelected)for(c=d.items.length-1;c>=0;c--)-1!==f.items.indexOf(z(d.items[c].id))&&d.items.splice(c,1);return d},refreshOptions:function(b){var c,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s;"undefined"==typeof b&&(b=!0);var t=this,u=a.trim(t.$control_input.val()),v=t.search(u),w=t.$dropdown_content,x=t.$activeOption&&z(t.$activeOption.attr("data-value"));for(g=v.items.length,"number"==typeof t.settings.maxOptions&&(g=Math.min(g,t.settings.maxOptions)),h={},i=[],c=0;g>c;c++)for(j=t.options[v.items[c].id],k=t.render("option",j),l=j[t.settings.optgroupField]||"",m=a.isArray(l)?l:[l],e=0,f=m&&m.length;f>e;e++)l=m[e],t.optgroups.hasOwnProperty(l)||(l=""),h.hasOwnProperty(l)||(h[l]=[],i.push(l)),h[l].push(k);for(this.settings.lockOptgroupOrder&&i.sort(function(a,b){var c=t.optgroups[a].$order||0,d=t.optgroups[b].$order||0;return c-d}),n=[],c=0,g=i.length;g>c;c++)l=i[c],t.optgroups.hasOwnProperty(l)&&h[l].length?(o=t.render("optgroup_header",t.optgroups[l])||"",o+=h[l].join(""),n.push(t.render("optgroup",a.extend({},t.optgroups[l],{html:o})))):n.push(h[l].join(""));if(w.html(n.join("")),t.settings.highlight&&v.query.length&&v.tokens.length)for(c=0,g=v.tokens.length;g>c;c++)d(w,v.tokens[c].regex);if(!t.settings.hideSelected)for(c=0,g=t.items.length;g>c;c++)t.getOption(t.items[c]).addClass("selected");p=t.canCreate(u),p&&(w.prepend(t.render("option_create",{input:u})),s=a(w[0].childNodes[0])),t.hasOptions=v.items.length>0||p,t.hasOptions?(v.items.length>0?(r=x&&t.getOption(x),r&&r.length?q=r:"single"===t.settings.mode&&t.items.length&&(q=t.getOption(t.items[0])),q&&q.length||(q=s&&!t.settings.addPrecedence?t.getAdjacentOption(s,1):w.find("[data-selectable]:first"))):q=s,t.setActiveOption(q),b&&!t.isOpen&&t.open()):(t.setActiveOption(null),b&&t.isOpen&&t.close())},addOption:function(b){var c,d,e,f=this;if(a.isArray(b))for(c=0,d=b.length;d>c;c++)f.addOption(b[c]);else(e=f.registerOption(b))&&(f.userOptions[e]=!0,f.lastQuery=null,f.trigger("option_add",e,b))},registerOption:function(a){var b=z(a[this.settings.valueField]);return!b||this.options.hasOwnProperty(b)?!1:(a.$order=a.$order||++this.order,this.options[b]=a,b)},registerOptionGroup:function(a){var b=z(a[this.settings.optgroupValueField]);return b?(a.$order=a.$order||++this.order,this.optgroups[b]=a,b):!1},addOptionGroup:function(a,b){b[this.settings.optgroupValueField]=a,(a=this.registerOptionGroup(b))&&this.trigger("optgroup_add",a,b)},removeOptionGroup:function(a){this.optgroups.hasOwnProperty(a)&&(delete this.optgroups[a],this.renderCache={},this.trigger("optgroup_remove",a))},clearOptionGroups:function(){this.optgroups={},this.renderCache={},this.trigger("optgroup_clear")},updateOption:function(b,c){var d,e,f,g,h,i,j,k=this;if(b=z(b),f=z(c[k.settings.valueField]),null!==b&&k.options.hasOwnProperty(b)){if("string"!=typeof f)throw new Error("Value must be set in option data");j=k.options[b].$order,f!==b&&(delete k.options[b],g=k.items.indexOf(b),-1!==g&&k.items.splice(g,1,f)),c.$order=c.$order||j,k.options[f]=c,h=k.renderCache.item,i=k.renderCache.option,h&&(delete h[b],delete h[f]),i&&(delete i[b],delete i[f]),-1!==k.items.indexOf(f)&&(d=k.getItem(b),e=a(k.render("item",c)),d.hasClass("active")&&e.addClass("active"),d.replaceWith(e)),k.lastQuery=null,k.isOpen&&k.refreshOptions(!1)}},removeOption:function(a,b){var c=this;a=z(a);var d=c.renderCache.item,e=c.renderCache.option;d&&delete d[a],e&&delete e[a],delete c.userOptions[a],delete c.options[a],c.lastQuery=null,c.trigger("option_remove",a),c.removeItem(a,b)},clearOptions:function(){var a=this;a.loadedSearches={},a.userOptions={},a.renderCache={},a.options=a.sifter.items={},a.lastQuery=null,a.trigger("option_clear"),a.clear()},getOption:function(a){return this.getElementWithValue(a,this.$dropdown_content.find("[data-selectable]"))},getAdjacentOption:function(b,c){var d=this.$dropdown.find("[data-selectable]"),e=d.index(b)+c;return e>=0&&ed;d++)if(c[d].getAttribute("data-value")===b)return a(c[d]);return a()},getItem:function(a){return this.getElementWithValue(a,this.$control.children())},addItems:function(b,c){for(var d=a.isArray(b)?b:[b],e=0,f=d.length;f>e;e++)this.isPending=f-1>e,this.addItem(d[e],c)},addItem:function(b,c){var d=c?[]:["change"];F(this,d,function(){var d,e,f,g,h,i=this,j=i.settings.mode;return b=z(b),-1!==i.items.indexOf(b)?void("single"===j&&i.close()):void(i.options.hasOwnProperty(b)&&("single"===j&&i.clear(c),"multi"===j&&i.isFull()||(d=a(i.render("item",i.options[b])),h=i.isFull(),i.items.splice(i.caretPos,0,b),i.insertAtCaret(d),(!i.isPending||!h&&i.isFull())&&i.refreshState(),i.isSetup&&(f=i.$dropdown_content.find("[data-selectable]"),i.isPending||(e=i.getOption(b),g=i.getAdjacentOption(e,1).attr("data-value"),i.refreshOptions(i.isFocused&&"single"!==j),g&&i.setActiveOption(i.getOption(g))),!f.length||i.isFull()?i.close():i.positionDropdown(),i.updatePlaceholder(),i.trigger("item_add",b,d),i.updateOriginalInput({silent:c})))))})},removeItem:function(a,b){var c,d,e,f=this;c="object"==typeof a?a:f.getItem(a),a=z(c.attr("data-value")),d=f.items.indexOf(a),-1!==d&&(c.remove(),c.hasClass("active")&&(e=f.$activeItems.indexOf(c[0]),f.$activeItems.splice(e,1)),f.items.splice(d,1),f.lastQuery=null,!f.settings.persist&&f.userOptions.hasOwnProperty(a)&&f.removeOption(a,b),d0),b.$control_input.data("grow",!c&&!d)},isFull:function(){return null!==this.settings.maxItems&&this.items.length>=this.settings.maxItems},updateOriginalInput:function(a){var b,c,d,e,f=this;if(a=a||{},f.tagType===v){for(d=[],b=0,c=f.items.length;c>b;b++)e=f.options[f.items[b]][f.settings.labelField]||"",d.push('");d.length||this.$input.attr("multiple")||d.push(''),f.$input.html(d.join(""))}else f.$input.val(f.getValue()),f.$input.attr("value",f.$input.val());f.isSetup&&(a.silent||f.trigger("change",f.$input.val()))},updatePlaceholder:function(){if(this.settings.placeholder){var a=this.$control_input;this.items.length?a.removeAttr("placeholder"):a.attr("placeholder",this.settings.placeholder),a.triggerHandler("update",{force:!0})}},open:function(){var a=this;a.isLocked||a.isOpen||"multi"===a.settings.mode&&a.isFull()||(a.focus(),a.isOpen=!0,a.refreshState(),a.$dropdown.css({visibility:"hidden",display:"block"}),a.positionDropdown(),a.$dropdown.css({visibility:"visible"}),a.trigger("dropdown_open",a.$dropdown))},close:function(){var a=this,b=a.isOpen;"single"===a.settings.mode&&a.items.length&&a.hideInput(),a.isOpen=!1,a.$dropdown.hide(),a.setActiveOption(null),a.refreshState(),b&&a.trigger("dropdown_close",a.$dropdown)},positionDropdown:function(){var a=this.$control,b="body"===this.settings.dropdownParent?a.offset():a.position();b.top+=a.outerHeight(!0),this.$dropdown.css({width:a.outerWidth(),top:b.top,left:b.left})},clear:function(a){var b=this;b.items.length&&(b.$control.children(":not(input)").remove(),b.items=[],b.lastQuery=null,b.setCaret(0),b.setActiveItem(null),b.updatePlaceholder(),b.updateOriginalInput({silent:a}),b.refreshState(),b.showInput(),b.trigger("clear"))},insertAtCaret:function(b){var c=Math.min(this.caretPos,this.items.length);0===c?this.$control.prepend(b):a(this.$control[0].childNodes[c]).before(b),this.setCaret(c+1)},deleteSelection:function(b){var c,d,e,f,g,h,i,j,k,l=this;if(e=b&&b.keyCode===p?-1:1,f=H(l.$control_input[0]),l.$activeOption&&!l.settings.hideSelected&&(i=l.getAdjacentOption(l.$activeOption,-1).attr("data-value")),g=[],l.$activeItems.length){for(k=l.$control.children(".active:"+(e>0?"last":"first")),h=l.$control.children(":not(input)").index(k),e>0&&h++,c=0,d=l.$activeItems.length;d>c;c++)g.push(a(l.$activeItems[c]).attr("data-value")); +b&&(b.preventDefault(),b.stopPropagation())}else(l.isFocused||"single"===l.settings.mode)&&l.items.length&&(0>e&&0===f.start&&0===f.length?g.push(l.items[l.caretPos-1]):e>0&&f.start===l.$control_input.val().length&&g.push(l.items[l.caretPos]));if(!g.length||"function"==typeof l.settings.onDelete&&l.settings.onDelete.apply(l,[g])===!1)return!1;for("undefined"!=typeof h&&l.setCaret(h);g.length;)l.removeItem(g.pop());return l.showInput(),l.positionDropdown(),l.refreshOptions(!0),i&&(j=l.getOption(i),j.length&&l.setActiveOption(j)),!0},advanceSelection:function(a,b){var c,d,e,f,g,h,i=this;0!==a&&(i.rtl&&(a*=-1),c=a>0?"last":"first",d=H(i.$control_input[0]),i.isFocused&&!i.isInputHidden?(f=i.$control_input.val().length,g=0>a?0===d.start&&0===d.length:d.start===f,g&&!f&&i.advanceCaret(a,b)):(h=i.$control.children(".active:"+c),h.length&&(e=i.$control.children(":not(input)").index(h),i.setActiveItem(null),i.setCaret(a>0?e+1:e))))},advanceCaret:function(a,b){var c,d,e=this;0!==a&&(c=a>0?"next":"prev",e.isShiftDown?(d=e.$control_input[c](),d.length&&(e.hideInput(),e.setActiveItem(d),b&&b.preventDefault())):e.setCaret(e.caretPos+a))},setCaret:function(b){var c=this;if(b="single"===c.settings.mode?c.items.length:Math.max(0,Math.min(c.items.length,b)),!c.isPending){var d,e,f,g;for(f=c.$control.children(":not(input)"),d=0,e=f.length;e>d;d++)g=a(f[d]).detach(),b>d?c.$control_input.before(g):c.$control.append(g)}c.caretPos=b},lock:function(){this.close(),this.isLocked=!0,this.refreshState()},unlock:function(){this.isLocked=!1,this.refreshState()},disable:function(){var a=this;a.$input.prop("disabled",!0),a.$control_input.prop("disabled",!0).prop("tabindex",-1),a.isDisabled=!0,a.lock()},enable:function(){var a=this;a.$input.prop("disabled",!1),a.$control_input.prop("disabled",!1).prop("tabindex",a.tabIndex),a.isDisabled=!1,a.unlock()},destroy:function(){var b=this,c=b.eventNS,d=b.revertSettings;b.trigger("destroy"),b.off(),b.$wrapper.remove(),b.$dropdown.remove(),b.$input.html("").append(d.$children).removeAttr("tabindex").removeClass("selectized").attr({tabindex:d.tabindex}).show(),b.$control_input.removeData("grow"),b.$input.removeData("selectize"),a(window).off(c),a(document).off(c),a(document.body).off(c),delete b.$input[0].selectize},render:function(a,b){var c,d,e="",f=!1,g=this,h=/^[\t \r\n]*<([a-z][a-z0-9\-_]*(?:\:[a-z][a-z0-9\-_]*)?)/i;return("option"===a||"item"===a)&&(c=z(b[g.settings.valueField]),f=!!c),f&&(y(g.renderCache[a])||(g.renderCache[a]={}),g.renderCache[a].hasOwnProperty(c))?g.renderCache[a][c]:(e=g.settings.render[a].apply(this,[b,A]),("option"===a||"option_create"===a)&&(e=e.replace(h,"<$1 data-selectable")),"optgroup"===a&&(d=b[g.settings.optgroupValueField]||"",e=e.replace(h,'<$1 data-group="'+B(A(d))+'"')),("option"===a||"item"===a)&&(e=e.replace(h,'<$1 data-value="'+B(A(c||""))+'"')),f&&(g.renderCache[a][c]=e),e)},clearCache:function(a){var b=this;"undefined"==typeof a?b.renderCache={}:delete b.renderCache[a]},canCreate:function(a){var b=this;if(!b.settings.create)return!1;var c=b.settings.createFilter;return!(!a.length||"function"==typeof c&&!c.apply(b,[a])||"string"==typeof c&&!new RegExp(c).test(a)||c instanceof RegExp&&!c.test(a))}}),L.count=0,L.defaults={options:[],optgroups:[],plugins:[],delimiter:",",splitOn:null,persist:!0,diacritics:!0,create:!1,createOnBlur:!1,createFilter:null,highlight:!0,openOnFocus:!0,maxOptions:1e3,maxItems:null,hideSelected:null,addPrecedence:!1,selectOnTab:!1,preload:!1,allowEmptyOption:!1,closeAfterSelect:!1,scrollDuration:60,loadThrottle:300,loadingClass:"loading",dataAttr:"data-data",optgroupField:"optgroup",valueField:"value",labelField:"text",optgroupLabelField:"label",optgroupValueField:"value",lockOptgroupOrder:!1,sortField:"$order",searchField:["text"],searchConjunction:"and",mode:null,wrapperClass:"selectize-control",inputClass:"selectize-input",dropdownClass:"selectize-dropdown",dropdownContentClass:"selectize-dropdown-content",dropdownParent:null,copyClassesToDropdown:!0,render:{}},a.fn.selectize=function(b){var c=a.fn.selectize.defaults,d=a.extend({},c,b),e=d.dataAttr,f=d.labelField,g=d.valueField,h=d.optgroupField,i=d.optgroupLabelField,j=d.optgroupValueField,k=function(b,c){var h,i,j,k,l=b.attr(e);if(l)for(c.options=JSON.parse(l),h=0,i=c.options.length;i>h;h++)c.items.push(c.options[h][g]);else{var m=a.trim(b.val()||"");if(!d.allowEmptyOption&&!m.length)return;for(j=m.split(d.delimiter),h=0,i=j.length;i>h;h++)k={},k[f]=j[h],k[g]=j[h],c.options.push(k);c.items=j}},l=function(b,c){var k,l,m,n,o=c.options,p={},q=function(a){var b=e&&a.attr(e);return"string"==typeof b&&b.length?JSON.parse(b):null},r=function(b,e){b=a(b);var i=z(b.attr("value"));if(i||d.allowEmptyOption)if(p.hasOwnProperty(i)){if(e){var j=p[i][h];j?a.isArray(j)?j.push(e):p[i][h]=[j,e]:p[i][h]=e}}else{var k=q(b)||{};k[f]=k[f]||b.text(),k[g]=k[g]||i,k[h]=k[h]||e,p[i]=k,o.push(k),b.is(":selected")&&c.items.push(i)}},s=function(b){var d,e,f,g,h;for(b=a(b),f=b.attr("label"),f&&(g=q(b)||{},g[i]=f,g[j]=f,c.optgroups.push(g)),h=a("option",b),d=0,e=h.length;e>d;d++)r(h[d],f)};for(c.maxItems=b.attr("multiple")?null:1,n=b.children(),k=0,l=n.length;l>k;k++)m=n[k].tagName.toLowerCase(),"optgroup"===m?s(n[k]):"option"===m&&r(n[k])};return this.each(function(){if(!this.selectize){var e,f=a(this),g=this.tagName.toLowerCase(),h=f.attr("placeholder")||f.attr("data-placeholder");h||d.allowEmptyOption||(h=f.children('option[value=""]').text());var i={placeholder:h,options:[],optgroups:[],items:[]};"select"===g?l(f,i):k(f,i),e=new L(f,a.extend(!0,{},c,i,b))}})},a.fn.selectize.defaults=L.defaults,a.fn.selectize.support={validity:x},L.define("drag_drop",function(){if(!a.fn.sortable)throw new Error('The "drag_drop" plugin requires jQuery UI "sortable".');if("multi"===this.settings.mode){var b=this;b.lock=function(){var a=b.lock;return function(){var c=b.$control.data("sortable");return c&&c.disable(),a.apply(b,arguments)}}(),b.unlock=function(){var a=b.unlock;return function(){var c=b.$control.data("sortable");return c&&c.enable(),a.apply(b,arguments)}}(),b.setup=function(){var c=b.setup;return function(){c.apply(this,arguments);var d=b.$control.sortable({items:"[data-value]",forcePlaceholderSize:!0,disabled:b.isLocked,start:function(a,b){b.placeholder.css("width",b.helper.css("width")),d.css({overflow:"visible"})},stop:function(){d.css({overflow:"hidden"});var c=b.$activeItems?b.$activeItems.slice():null,e=[];d.children("[data-value]").each(function(){e.push(a(this).attr("data-value"))}),b.setValue(e),b.setActiveItem(c)}})}}()}}),L.define("dropdown_header",function(b){var c=this;b=a.extend({title:"Untitled",headerClass:"selectize-dropdown-header",titleRowClass:"selectize-dropdown-header-title",labelClass:"selectize-dropdown-header-label",closeClass:"selectize-dropdown-header-close",html:function(a){return'
    '+a.title+'×
    '}},b),c.setup=function(){var d=c.setup;return function(){d.apply(c,arguments),c.$dropdown_header=a(b.html(b)),c.$dropdown.prepend(c.$dropdown_header)}}()}),L.define("optgroup_columns",function(b){var c=this;b=a.extend({equalizeWidth:!0,equalizeHeight:!0},b),this.getAdjacentOption=function(b,c){var d=b.closest("[data-group]").find("[data-selectable]"),e=d.index(b)+c;return e>=0&&e
    ',a=a.firstChild,c.body.appendChild(a),b=d.width=a.offsetWidth-a.clientWidth,c.body.removeChild(a)),b},e=function(){var e,f,g,h,i,j,k;if(k=a("[data-group]",c.$dropdown_content),f=k.length,f&&c.$dropdown_content.width()){if(b.equalizeHeight){for(g=0,e=0;f>e;e++)g=Math.max(g,k.eq(e).height());k.css({height:g})}b.equalizeWidth&&(j=c.$dropdown_content.innerWidth()-d(),h=Math.round(j/f),k.css({width:h}),f>1&&(i=j-h*(f-1),k.eq(f-1).css({width:i})))}};(b.equalizeHeight||b.equalizeWidth)&&(C.after(this,"positionDropdown",e),C.after(this,"refreshOptions",e))}),L.define("remove_button",function(b){if("single"!==this.settings.mode){b=a.extend({label:"×",title:"Remove",className:"remove",append:!0},b);var c=this,d=''+b.label+"",e=function(a,b){var c=a.search(/(<\/[^>]+>\s*)$/);return a.substring(0,c)+b+a.substring(c)};this.setup=function(){var f=c.setup;return function(){if(b.append){var g=c.settings.render.item;c.settings.render.item=function(){return e(g.apply(this,arguments),d)}}f.apply(this,arguments),this.$control.on("click","."+b.className,function(b){if(b.preventDefault(),!c.isLocked){var d=a(b.currentTarget).parent();c.setActiveItem(d),c.deleteSelection()&&c.setCaret(c.items.length)}})}}()}}),L.define("restore_on_backspace",function(a){var b=this;a.text=a.text||function(a){return a[this.settings.labelField]},this.onKeyDown=function(){var c=b.onKeyDown;return function(b){var d,e;return b.keyCode===p&&""===this.$control_input.val()&&!this.$activeItems.length&&(d=this.caretPos-1,d>=0&&d - {% if field.label and not field|is_checkbox and form_show_labels %} - - {% endif %} - -
    - {% if field|is_checkbox %} - - {% else %} - {% crispy_field field %} - {% include 'bootstrap3/layout/help_text_and_errors.html' %} - {% endif %} -
    - -{% endif %} diff --git a/xadmin/templates/xadmin/500.html b/xadmin/templates/xadmin/500.html index b437c1aed..ee94582c2 100644 --- a/xadmin/templates/xadmin/500.html +++ b/xadmin/templates/xadmin/500.html @@ -1,6 +1,6 @@ {% extends base_template %} {% load i18n %} -{% load url from future %} + {% block breadcrumbs %}
  • -{% endif %} \ No newline at end of file +{% endif %} +{% endautoescape %} diff --git a/xadmin/templates/xadmin/blocks/model_list.nav_form.search_form.html b/xadmin/templates/xadmin/blocks/model_list.nav_form.search_form.html index 222e74aed..01fd9724d 100644 --- a/xadmin/templates/xadmin/blocks/model_list.nav_form.search_form.html +++ b/xadmin/templates/xadmin/blocks/model_list.nav_form.search_form.html @@ -5,7 +5,7 @@ {% if cl.search_query %} x {% endif %} - + {{ search_form_params|safe }} diff --git a/xadmin/templates/xadmin/blocks/model_list.results_bottom.actions.html b/xadmin/templates/xadmin/blocks/model_list.results_bottom.actions.html index 37c568af0..ef863317c 100644 --- a/xadmin/templates/xadmin/blocks/model_list.results_bottom.actions.html +++ b/xadmin/templates/xadmin/blocks/model_list.results_bottom.actions.html @@ -16,9 +16,9 @@ {% if actions_selection_counter %} {% if cl.result_count != cl.result_list|length %} - + {% endif %} - {% endif %} + diff --git a/xadmin/templates/xadmin/blocks/model_list.top_toolbar.importexport.export.html b/xadmin/templates/xadmin/blocks/model_list.top_toolbar.importexport.export.html new file mode 100644 index 000000000..07d301d3d --- /dev/null +++ b/xadmin/templates/xadmin/blocks/model_list.top_toolbar.importexport.export.html @@ -0,0 +1,47 @@ +{% load i18n %} +
    + + {% trans "Export" %} + + +
    \ No newline at end of file diff --git a/xadmin/templates/xadmin/blocks/model_list.top_toolbar.importexport.import.html b/xadmin/templates/xadmin/blocks/model_list.top_toolbar.importexport.import.html new file mode 100644 index 000000000..ee358aedc --- /dev/null +++ b/xadmin/templates/xadmin/blocks/model_list.top_toolbar.importexport.import.html @@ -0,0 +1,6 @@ +{% load i18n %} + \ No newline at end of file diff --git a/xadmin/templates/xadmin/blocks/model_list.top_toolbar.saveorder.html b/xadmin/templates/xadmin/blocks/model_list.top_toolbar.saveorder.html new file mode 100644 index 000000000..6c85f2e22 --- /dev/null +++ b/xadmin/templates/xadmin/blocks/model_list.top_toolbar.saveorder.html @@ -0,0 +1,6 @@ +{% load i18n %} + diff --git a/xadmin/templates/xadmin/edit_inline/base.html b/xadmin/templates/xadmin/edit_inline/base.html index 62ee0cc29..343c352d8 100644 --- a/xadmin/templates/xadmin/edit_inline/base.html +++ b/xadmin/templates/xadmin/edit_inline/base.html @@ -30,8 +30,9 @@ {% block box_extra %} {% if not formset.formset.detail_page %} - + {% endif %} {% endblock box_extra %} \ No newline at end of file diff --git a/xadmin/templates/xadmin/filters/fk_search.html b/xadmin/templates/xadmin/filters/fk_search.html index 7876980bd..6255e9eb9 100644 --- a/xadmin/templates/xadmin/filters/fk_search.html +++ b/xadmin/templates/xadmin/filters/fk_search.html @@ -9,9 +9,17 @@

    {{ form_params|safe }} - + {% if spec.used_params %} diff --git a/xadmin/templates/xadmin/import_export/export_action.html b/xadmin/templates/xadmin/import_export/export_action.html new file mode 100644 index 000000000..7907fa7e2 --- /dev/null +++ b/xadmin/templates/xadmin/import_export/export_action.html @@ -0,0 +1,46 @@ +{% extends 'xadmin/base_site.html' %} +{% load i18n %} +{% load admin_urls %} +{% load import_export_tags %} + +{% block breadcrumbs_last %} +{% trans "Export" %} +{% endblock %} +{% load xadmin_tags %} + +{% block breadcrumbs %} + +{% endblock %} +{% block nav_title %} + {{title}} +{% endblock %} + +{% block content %} + + {% csrf_token %} + +
    + {% for field in form %} +
    + {{ field.errors }} + + {{ field.label_tag }} + + {{ field }} + + {% if field.field.help_text %} +

    {{ field.field.help_text|safe }}

    + {% endif %} +
    + {% endfor %} +
    + +
    + +
    +
    +{% endblock %} diff --git a/xadmin/templates/xadmin/import_export/import.html b/xadmin/templates/xadmin/import_export/import.html new file mode 100644 index 000000000..ce6276d45 --- /dev/null +++ b/xadmin/templates/xadmin/import_export/import.html @@ -0,0 +1,123 @@ +{% extends 'xadmin/base_site.html' %} +{% load i18n %} +{% load admin_urls %} +{% load import_export_tags %} + +{% trans "Import" %} +{% load xadmin_tags %} + +{% block breadcrumbs %} + +{% endblock %} +{% block nav_title %} + {{title}} +{% endblock %} + +{% block content %} +{% if confirm_form %} +
    + {% csrf_token %} + {{ confirm_form.as_p }} +

    + {% trans "Below is a preview of data to be imported. If you are satisfied with the results, click 'Confirm import'" %} +

    +
    + +
    +
    + +{% else %} +
    + {% csrf_token %} + +

    + {% trans "This importer will import the following fields: " %} + {{ fields|join:", " }} +

    + +
    + {% for field in form %} +
    + {{ field.errors }} + + {{ field.label_tag }} + + {{ field }} + + {% if field.field.help_text %} +

    {{ field.field.help_text|safe }}

    + {% endif %} +
    + {% endfor %} +
    + +
    + +
    +
    +{% endif %} + +{% if result %} + + {% if result.has_errors %} +

    {% trans "Errors" %}

    +
      + {% for error in result.base_errors %} +
    • + {{ error.error }} +
      {{ error.traceback|linebreaks }}
      +
    • + {% endfor %} + {% for line, errors in result.row_errors %} + {% for error in errors %} +
    • + {% trans "Line number" %}: {{ line }} - {{ error.error }} +
      {{ error.row.values|join:", " }}
      +
      {{ error.traceback|linebreaks }}
      +
    • + {% endfor %} + {% endfor %} +
    + {% else %} + +

    + {% trans "Preview" %} +

    + + + + + {% for field in result.diff_headers %} + + {% endfor %} + + + {% for row in result.rows %} + + + {% for field in row.diff %} + + {% endfor %} + + {% endfor %} +
    {{ field }}
    + {% if row.import_type == 'new' %} + {% trans "New" %} + {% elif row.import_type == 'skip' %} + {% trans "Skipped" %} + {% elif row.import_type == 'delete' %} + {% trans "Delete" %} + {% elif row.import_type == 'update' %} + {% trans "Update" %} + {% endif %} + + {{ field }} +
    + {% endif %} + + {% endif %} +{% endblock %} diff --git a/xadmin/templates/xadmin/includes/sitemenu_accordion.html b/xadmin/templates/xadmin/includes/sitemenu_accordion.html index dde88a954..df80f12f1 100644 --- a/xadmin/templates/xadmin/includes/sitemenu_accordion.html +++ b/xadmin/templates/xadmin/includes/sitemenu_accordion.html @@ -1,6 +1,6 @@ {% extends 'xadmin/includes/sitemenu_default.html' %} {% load i18n xadmin_tags %} -{% load url from future %} + {% block navbar_md %}