├── .coveragerc ├── .editorconfig ├── .flake8 ├── .gitignore ├── .landscape.yml ├── .travis.yml ├── LICENSE ├── MANIFEST.in ├── README ├── README.rst ├── docs ├── Makefile ├── _ext │ ├── __init__.py │ ├── exts.py │ └── fields.py ├── _theme │ └── djangodocs │ │ ├── genindex.html │ │ ├── layout.html │ │ ├── modindex.html │ │ ├── search.html │ │ ├── static │ │ ├── default.css │ │ ├── djangodocs.css │ │ ├── docicons-behindscenes.png │ │ ├── docicons-note.png │ │ ├── docicons-philosophy.png │ │ ├── homepage.css │ │ └── reset-fonts-grids.css │ │ └── theme.conf ├── api │ ├── index.rst │ ├── password_policies.conf.rst │ ├── password_policies.context_processors.rst │ ├── password_policies.forms.fields.rst │ ├── password_policies.forms.rst │ ├── password_policies.forms.validators.rst │ ├── password_policies.managers.rst │ ├── password_policies.middleware.rst │ ├── password_policies.models.rst │ └── password_policies.views.rst ├── conf.py ├── contents.rst ├── index.rst ├── license.rst └── topics │ ├── contributing.rst │ ├── custom.validation.rst │ ├── force.password.change.rst │ ├── install.rst │ ├── internationalization.rst │ ├── overview.rst │ ├── password.history.rst │ ├── security.rst │ ├── setup.rst │ ├── support.rst │ └── testing.rst ├── password_policies ├── __init__.py ├── admin.py ├── conf.py ├── context_processors.py ├── forms │ ├── __init__.py │ ├── admin.py │ ├── fields.py │ └── validators.py ├── locale │ ├── ar │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── az │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── bg │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── bn │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── bs │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ca │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── cs │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── cy │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── da │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── de │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── el │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── en │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── en_GB │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── es │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── es_AR │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── es_MX │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── es_NI │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── et │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── eu │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── fa │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── fi │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── fr │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── fy_NL │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ga │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── gl │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── he │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── hi │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── hr │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── hu │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── id │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── is │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── it │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ja │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ka │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── km │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── kn │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ko │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── lt │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── lv │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── mk │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ml │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── mn │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── nb │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── nl │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── nn │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── no │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── pa │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── pl │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── pt │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── pt_BR │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ro │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ru │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── sk │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── sl │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── sq │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── sr │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── sr_Latn │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── sv │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ta │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── te │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── th │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── tr │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── uk │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ur │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── vi │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── zh_CN │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ └── zh_TW │ │ └── LC_MESSAGES │ │ ├── django.mo │ │ └── django.po ├── managers.py ├── middleware.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── south_migrations │ ├── 0001_initial.py │ └── __init__.py ├── tests │ ├── __init__.py │ ├── lib.py │ ├── templates │ │ ├── 403.html │ │ └── registration │ │ │ ├── password_change_done.html │ │ │ ├── password_change_form.html │ │ │ ├── password_reset_complete.html │ │ │ ├── password_reset_confirm.html │ │ │ ├── password_reset_done.html │ │ │ ├── password_reset_email.html │ │ │ ├── password_reset_email.txt │ │ │ ├── password_reset_form.html │ │ │ └── password_reset_subject.txt │ ├── test_forms.py │ ├── test_middleware.py │ ├── test_models.py │ ├── test_settings.py │ ├── test_utils.py │ ├── test_views.py │ ├── urls.py │ └── views.py ├── urls.py ├── utils.py └── views.py ├── requirements.txt ├── setup.py ├── tests.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | include = password_policies/* 3 | omit = password_policies/tests/* 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.{py,rst,ini}] 12 | indent_style = space 13 | indent_size = 4 14 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = E501 3 | exclude = .git,__pycache__,docs,old,build,dist 4 | max-complexity = 10 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | *.py[cod] 3 | 4 | # C extensions 5 | *.so 6 | 7 | # Packages 8 | *.egg 9 | *.egg-info 10 | dist 11 | build 12 | eggs 13 | parts 14 | bin 15 | var 16 | sdist 17 | develop-eggs 18 | .installed.cfg 19 | lib 20 | lib64 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | 30 | # Translations 31 | *.mo 32 | 33 | # Mr Developer 34 | .mr.developer.cfg 35 | .project 36 | .pydevproject 37 | 38 | #Netbeans 39 | nbproject 40 | 41 | .eggs 42 | 43 | ### SublimeText ### 44 | # cache files for sublime text 45 | *.tmlanguage.cache 46 | *.tmPreferences.cache 47 | *.stTheme.cache 48 | 49 | # workspace files are user-specific 50 | *.sublime-workspace 51 | 52 | # project files should be checked into the repository, unless a significant 53 | # proportion of contributors will probably not be using SublimeText 54 | *.sublime-project 55 | 56 | # sftp configuration file 57 | sftp-config.json 58 | 59 | # Package control specific files 60 | Package Control.last-run 61 | Package Control.ca-list 62 | Package Control.ca-bundle 63 | Package Control.system-ca-bundle 64 | Package Control.cache/ 65 | Package Control.ca-certs/ 66 | bh_unicode_properties.cache 67 | 68 | # Sublime-github package stores a github token in this file 69 | # https://packagecontrol.io/packages/sublime-github 70 | GitHub.sublime-settings 71 | -------------------------------------------------------------------------------- /.landscape.yml: -------------------------------------------------------------------------------- 1 | strictness: high 2 | doc-warnings: yes 3 | test-warnings: yes 4 | max-line-length: 120 5 | uses: 6 | - django 7 | ignore-paths: 8 | - docs 9 | pylint: 10 | disable: 11 | - missing-docstring 12 | - no-self-use 13 | - unused-argument 14 | pep8: 15 | disable: 16 | - N802 17 | pep257: 18 | disable: 19 | - D100 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | sudo: false 3 | python: 4 | - "2.7" 5 | - "3.3" 6 | - "3.4" 7 | - "3.5" 8 | env: 9 | - DJANGO="django>=1.7,<1.8" 10 | - DJANGO="django>=1.8,<1.9" 11 | - DJANGO="django>=1.9,<1.10" 12 | install: 13 | - pip install -q $DJANGO 14 | - pip install pep8 15 | - pip install coveralls 16 | - pip install django-easysettings 17 | - pip install -q -e . 18 | matrix: 19 | exclude: 20 | - python: "3.3" 21 | env: DJANGO="django>=1.9,<1.10" 22 | - python: "3.5" 23 | env: DJANGO="django>=1.7,<1.8" 24 | before_script: 25 | - "pep8 --ignore=E501,E225 password_policies" 26 | script: 27 | - coverage run tests.py 28 | after_success: 29 | coveralls 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, "Tarak Blah" 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 3. Neither the name of the author nor the names of contributors 13 | may be used to endorse or promote products derived from this software 14 | without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include password_policies/fixtures * 2 | recursive-include password_policies/locale * 3 | recursive-include password_policies/tests/templates * 4 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | django-password-policies 2 | ======================== 3 | 4 | |travis| |coverage| |landscape| |requires| |latest-version| |downloads| 5 | 6 | ``django-password-policies`` is an application for the `Django`_ framework that 7 | provides unicode-aware password policies on password changes and resets and a 8 | mechanism to force password changes. 9 | 10 | .. |travis| image:: https://travis-ci.org/tarak/django-password-policies.svg?branch=master 11 | :target: https://travis-ci.org/tarak/django-password-policies 12 | .. |coverage| image:: https://coveralls.io/repos/tarak/django-password-policies/badge.svg?branch=master 13 | :target: https://coveralls.io/r/tarak/django-password-policies?branch=master 14 | .. |landscape| image:: https://landscape.io/github/tarak/django-password-policies/master/landscape.svg?style=flat 15 | :target: https://landscape.io/github/tarak/django-password-policies/master 16 | :alt: Code Health 17 | .. |requires| image:: https://requires.io/github/tarak/django-password-policies/requirements.svg?branch=master 18 | :target: https://requires.io/github/tarak/django-password-policies/requirements/?branch=master 19 | :alt: Requirements Status 20 | .. |latest-version| image:: https://img.shields.io/pypi/v/django-password-policies.svg 21 | :alt: Latest version on PyPI 22 | :target: https://pypi.python.org/pypi/django-password-policies 23 | .. |downloads| image:: https://img.shields.io/pypi/dm/django-password-policies.svg 24 | :alt: Monthly downloads from PyPI 25 | :target: https://pypi.python.org/pypi/django-password-policies 26 | 27 | .. _requirements: 28 | 29 | Requirements 30 | ============= 31 | 32 | This application requires 33 | 34 | * `Django`_ 1.7 or newer 35 | * `django-easysettings`_ 36 | * `pytz`_ 37 | 38 | .. _documentation: 39 | 40 | Documentation 41 | ============= 42 | 43 | A detailled documentation is available on `the project's GitHub Pages`_. 44 | 45 | .. _`the project's GitHub Pages`: http://tarak.github.com/django-password-policies 46 | .. _`Django`: https://www.djangoproject.com/ 47 | .. _`django-easysettings`: https://github.com/SmileyChris/django-easysettings 48 | .. _`pytz`: http://pythonhosted.org/pytz/ 49 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | django-password-policies 2 | ======================== 3 | 4 | |travis| |coverage| |landscape| |requires| |latest-version| |downloads| 5 | 6 | ``django-password-policies`` is an application for the `Django`_ framework that 7 | provides unicode-aware password policies on password changes and resets and a 8 | mechanism to force password changes. 9 | 10 | .. |travis| image:: https://travis-ci.org/tarak/django-password-policies.svg?branch=master 11 | :target: https://travis-ci.org/tarak/django-password-policies 12 | .. |coverage| image:: https://coveralls.io/repos/tarak/django-password-policies/badge.svg?branch=master 13 | :target: https://coveralls.io/r/tarak/django-password-policies?branch=master 14 | .. |landscape| image:: https://landscape.io/github/tarak/django-password-policies/master/landscape.svg?style=flat 15 | :target: https://landscape.io/github/tarak/django-password-policies/master 16 | :alt: Code Health 17 | .. |requires| image:: https://requires.io/github/tarak/django-password-policies/requirements.svg?branch=master 18 | :target: https://requires.io/github/tarak/django-password-policies/requirements/?branch=master 19 | :alt: Requirements Status 20 | .. |latest-version| image:: https://img.shields.io/pypi/v/django-password-policies.svg 21 | :alt: Latest version on PyPI 22 | :target: https://pypi.python.org/pypi/django-password-policies 23 | .. |downloads| image:: https://img.shields.io/pypi/dm/django-password-policies.svg 24 | :alt: Monthly downloads from PyPI 25 | :target: https://pypi.python.org/pypi/django-password-policies 26 | 27 | .. _requirements: 28 | 29 | Requirements 30 | ============= 31 | 32 | This application requires 33 | 34 | * `Django`_ 1.7 or newer 35 | * `django-easysettings`_ 36 | 37 | .. _documentation: 38 | 39 | Documentation 40 | ============= 41 | 42 | A detailled documentation is available on `the project's GitHub Pages`_. 43 | 44 | .. _`the project's GitHub Pages`: http://tarak.github.com/django-password-policies 45 | .. _`Django`: https://www.djangoproject.com/ 46 | .. _`django-easysettings`: https://github.com/SmileyChris/django-easysettings 47 | -------------------------------------------------------------------------------- /docs/_ext/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/_theme/djangodocs/genindex.html: -------------------------------------------------------------------------------- 1 | {% extends "basic/genindex.html" %} 2 | 3 | {% block bodyclass %}{% endblock %} 4 | {% block sidebarwrapper %}{% endblock %} -------------------------------------------------------------------------------- /docs/_theme/djangodocs/modindex.html: -------------------------------------------------------------------------------- 1 | {% extends "basic/modindex.html" %} 2 | {% block bodyclass %}{% endblock %} 3 | {% block sidebarwrapper %}{% endblock %} -------------------------------------------------------------------------------- /docs/_theme/djangodocs/search.html: -------------------------------------------------------------------------------- 1 | {% extends "basic/search.html" %} 2 | {% block bodyclass %}{% endblock %} 3 | {% block sidebarwrapper %}{% endblock %} -------------------------------------------------------------------------------- /docs/_theme/djangodocs/static/default.css: -------------------------------------------------------------------------------- 1 | @import url(reset-fonts-grids.css); 2 | @import url(djangodocs.css); 3 | @import url(homepage.css); -------------------------------------------------------------------------------- /docs/_theme/djangodocs/static/docicons-behindscenes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/docs/_theme/djangodocs/static/docicons-behindscenes.png -------------------------------------------------------------------------------- /docs/_theme/djangodocs/static/docicons-note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/docs/_theme/djangodocs/static/docicons-note.png -------------------------------------------------------------------------------- /docs/_theme/djangodocs/static/docicons-philosophy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/docs/_theme/djangodocs/static/docicons-philosophy.png -------------------------------------------------------------------------------- /docs/_theme/djangodocs/static/homepage.css: -------------------------------------------------------------------------------- 1 | #index p.rubric { font-size:150%; font-weight:normal; margin-bottom:.2em; color:#487858; } 2 | 3 | #index div.section dt { font-weight: normal; } 4 | 5 | #index #s-getting-help { float: right; width: 35em; background: #E1ECE2; padding: 1em; margin: 2em 0 2em 2em; } 6 | #index #s-getting-help h2 { margin: 0; } 7 | 8 | #index #s-django-documentation div.section div.section h3 { margin: 0; } 9 | #index #s-django-documentation div.section div.section { background: #E1ECE2; padding: 1em; margin: 2em 0 2em 40.3em; } 10 | #index #s-django-documentation div.section div.section a.reference { white-space: nowrap; } 11 | 12 | #index #s-using-django dl, 13 | #index #s-add-on-contrib-applications dl, 14 | #index #s-solving-specific-problems dl, 15 | #index #s-reference dl 16 | { float: left; width: 41em; } 17 | 18 | #index #s-add-on-contrib-applications, 19 | #index #s-solving-specific-problems, 20 | #index #s-reference, 21 | #index #s-and-all-the-rest 22 | { clear: left; } -------------------------------------------------------------------------------- /docs/_theme/djangodocs/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | stylesheet = default.css 4 | pygments_style = trac 5 | -------------------------------------------------------------------------------- /docs/api/index.rst: -------------------------------------------------------------------------------- 1 | .. _api: 2 | 3 | API Reference 4 | ============= 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | 9 | password_policies.conf 10 | password_policies.context_processors 11 | password_policies.forms.fields 12 | password_policies.forms 13 | password_policies.managers 14 | password_policies.middleware 15 | password_policies.models 16 | password_policies.forms.validators 17 | password_policies.views 18 | -------------------------------------------------------------------------------- /docs/api/password_policies.conf.rst: -------------------------------------------------------------------------------- 1 | .. _api-settings: 2 | 3 | Settings 4 | ======== 5 | 6 | ``django-password-policies`` uses settings to customize the behaviour 7 | of this application. While it provides useful defaults all of the following 8 | attributes can be set individually for each project by adding the attribute 9 | and its new value to the project's settings file: 10 | 11 | .. automodule:: password_policies.conf 12 | 13 | .. settings:: Settings 14 | 15 | ``Settings`` 16 | ------------ 17 | 18 | .. autoclass:: password_policies.conf.Settings 19 | :members: 20 | :show-inheritance: 21 | -------------------------------------------------------------------------------- /docs/api/password_policies.context_processors.rst: -------------------------------------------------------------------------------- 1 | .. _api-password_status: 2 | 3 | Context processors 4 | ================== 5 | 6 | ``django-password-policies`` provides a context processor that adds password 7 | related variables to a context: 8 | 9 | .. automodule:: password_policies.context_processors 10 | 11 | .. context_processors:: password_status 12 | 13 | ``password_status`` 14 | ------------------- 15 | 16 | .. autofunction:: password_policies.context_processors.password_status 17 | -------------------------------------------------------------------------------- /docs/api/password_policies.forms.fields.rst: -------------------------------------------------------------------------------- 1 | .. _api-fields: 2 | 3 | =========== 4 | Form fields 5 | =========== 6 | 7 | django-password-policies provides a form field to validate new passwords: 8 | 9 | .. automodule:: password_policies.forms.fields 10 | 11 | .. formfield:: PasswordPoliciesField 12 | 13 | ``PasswordPoliciesField`` 14 | ------------------------- 15 | 16 | .. autoclass:: password_policies.forms.fields.PasswordPoliciesField 17 | :members: 18 | :member-order: bysource 19 | -------------------------------------------------------------------------------- /docs/api/password_policies.forms.rst: -------------------------------------------------------------------------------- 1 | .. _api-forms: 2 | 3 | Forms 4 | ===== 5 | 6 | ``django-password-policies`` ships two :class:`django.forms.Form` classes that 7 | handles the validation of new passwords: 8 | 9 | .. automodule:: password_policies.forms 10 | 11 | .. form:: PasswordPoliciesForm 12 | 13 | ``PasswordPoliciesForm`` 14 | ------------------------ 15 | 16 | .. autoclass:: password_policies.forms.PasswordPoliciesForm 17 | :members: 18 | :special-members: 19 | :member-order: bysource 20 | 21 | .. form:: PasswordPoliciesChangeForm 22 | 23 | ``PasswordPoliciesChangeForm`` 24 | ------------------------------ 25 | 26 | .. autoclass:: password_policies.forms.PasswordPoliciesChangeForm 27 | :members: 28 | :show-inheritance: 29 | :member-order: bysource 30 | 31 | .. form:: PasswordPoliciesRegistrationForm 32 | 33 | ``PasswordPoliciesRegistrationForm`` 34 | ------------------------------------ 35 | 36 | .. autoclass:: password_policies.forms.PasswordPoliciesRegistrationForm 37 | :members: 38 | :special-members: 39 | :member-order: bysource 40 | 41 | .. form:: PasswordResetForm 42 | 43 | ``PasswordResetForm`` 44 | ------------------------------ 45 | 46 | .. autoclass:: password_policies.forms.PasswordResetForm 47 | :members: 48 | :member-order: bysource 49 | -------------------------------------------------------------------------------- /docs/api/password_policies.managers.rst: -------------------------------------------------------------------------------- 1 | .. _api-managers: 2 | 3 | Managers 4 | ======== 5 | 6 | The :class:`~password_policies.models.PasswordHistory` model has a custom manager 7 | that has the following helper functions: 8 | 9 | .. automodule:: password_policies.managers 10 | 11 | .. manager:: PasswordHistoryManager 12 | 13 | ``PasswordHistoryManager`` 14 | ----------------------------- 15 | 16 | .. autoclass:: password_policies.managers.PasswordHistoryManager 17 | :members: 18 | :member-order: bysource 19 | -------------------------------------------------------------------------------- /docs/api/password_policies.middleware.rst: -------------------------------------------------------------------------------- 1 | .. _api-middleware: 2 | 3 | Middleware 4 | ========== 5 | 6 | .. automodule:: password_policies.middleware 7 | 8 | 9 | .. middleware:: PasswordChangeMiddleware 10 | 11 | ``PasswordChangeMiddleware`` 12 | ---------------------------- 13 | 14 | .. autoclass:: password_policies.middleware.PasswordChangeMiddleware 15 | :members: 16 | -------------------------------------------------------------------------------- /docs/api/password_policies.models.rst: -------------------------------------------------------------------------------- 1 | .. _api-models: 2 | 3 | Models 4 | ====== 5 | 6 | .. automodule:: password_policies.models 7 | 8 | 9 | .. model:: PasswordChangeRequired 10 | 11 | ``PasswordChangeRequired`` 12 | -------------------------- 13 | 14 | .. autoclass:: password_policies.models.PasswordChangeRequired 15 | :members: 16 | 17 | 18 | .. model:: PasswordHistory 19 | 20 | ``PasswordHistory`` 21 | ------------------- 22 | 23 | .. autoclass:: password_policies.models.PasswordHistory 24 | :members: 25 | -------------------------------------------------------------------------------- /docs/api/password_policies.views.rst: -------------------------------------------------------------------------------- 1 | .. _api-views: 2 | 3 | Views 4 | ====== 5 | 6 | .. automodule:: password_policies.views 7 | 8 | 9 | .. view:: LoggedOutMixin 10 | 11 | ``LoggedOutMixin`` 12 | ------------------ 13 | 14 | .. autoclass:: password_policies.views.LoggedOutMixin 15 | :members: 16 | 17 | 18 | .. view:: PasswordChangeDoneView 19 | 20 | ``PasswordChangeDoneView`` 21 | -------------------------- 22 | 23 | .. autoclass:: password_policies.views.PasswordChangeDoneView 24 | :members: 25 | :member-order: bysource 26 | :show-inheritance: 27 | 28 | 29 | .. view:: PasswordChangeFormView 30 | 31 | ``PasswordChangeFormView`` 32 | -------------------------- 33 | 34 | .. autoclass:: password_policies.views.PasswordChangeFormView 35 | :members: 36 | :member-order: bysource 37 | :show-inheritance: 38 | 39 | 40 | .. view:: PasswordResetCompleteView 41 | 42 | ``PasswordResetCompleteView`` 43 | ----------------------------- 44 | 45 | .. autoclass:: password_policies.views.PasswordResetCompleteView 46 | :members: 47 | :member-order: bysource 48 | :show-inheritance: 49 | 50 | 51 | .. view:: PasswordResetConfirmView 52 | 53 | ``PasswordResetConfirmView`` 54 | ---------------------------- 55 | 56 | .. autoclass:: password_policies.views.PasswordResetConfirmView 57 | :members: 58 | :member-order: bysource 59 | :show-inheritance: 60 | 61 | 62 | .. view:: PasswordResetDoneView 63 | 64 | ``PasswordResetDoneView`` 65 | ------------------------- 66 | 67 | .. autoclass:: password_policies.views.PasswordResetDoneView 68 | :members: 69 | :member-order: bysource 70 | :show-inheritance: 71 | 72 | 73 | .. view:: PasswordResetFormView 74 | 75 | ``PasswordResetFormView`` 76 | ------------------------- 77 | 78 | .. autoclass:: password_policies.views.PasswordResetFormView 79 | :members: 80 | :member-order: bysource 81 | :show-inheritance: 82 | -------------------------------------------------------------------------------- /docs/contents.rst: -------------------------------------------------------------------------------- 1 | .. _contents: 2 | 3 | ================= 4 | Table of contents 5 | ================= 6 | 7 | :Date: |today| 8 | 9 | **Documentation**: 10 | 11 | .. toctree:: 12 | :hidden: 13 | 14 | index 15 | 16 | .. toctree:: 17 | :maxdepth: 3 18 | 19 | topics/overview 20 | topics/install 21 | topics/setup 22 | topics/security 23 | topics/custom.validation 24 | topics/password.history 25 | topics/force.password.change 26 | topics/support 27 | api/index 28 | topics/testing 29 | topics/contributing 30 | topics/internationalization 31 | license 32 | 33 | 34 | Indices and tables 35 | ================== 36 | 37 | * :ref:`genindex` 38 | * :ref:`modindex` 39 | * :ref:`search` 40 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. _index: 2 | 3 | ============================================ 4 | django-password-policies documentation index 5 | ============================================ 6 | 7 | 8 | ``django-password-policies`` is an application for the `Django`_ framework that 9 | provides unicode-aware password policies on password changes and resets and a 10 | mechanism to force password changes. 11 | 12 | A detailled overview of the features and workflow of this application, along 13 | with instructions on how to install and set it up can be found here: 14 | 15 | * **First steps:** 16 | :doc:`Overview ` | 17 | :doc:`Installation ` | 18 | :doc:`Setup ` 19 | 20 | Informations on how to use the application can be found here: 21 | 22 | * **Using the app:** 23 | :doc:`Security ` | 24 | :doc:`Customizing validation ` | 25 | :doc:`Using the password history ` | 26 | :doc:`Forcing password changes ` 27 | 28 | For bugfixing and feature requests please read: 29 | 30 | * **Support:** 31 | :doc:`Getting help ` 32 | 33 | To participate in the development of this application please read: 34 | 35 | * **Development:** 36 | :doc:`API reference ` | 37 | :doc:`Testing ` | 38 | :doc:`Contributing ` | 39 | :doc:`Internationalization ` | 40 | :doc:`License ` 41 | 42 | .. _`Django`: https://www.djangoproject.com/ 43 | -------------------------------------------------------------------------------- /docs/license.rst: -------------------------------------------------------------------------------- 1 | .. _license: 2 | 3 | License 4 | ======= 5 | 6 | .. literalinclude:: ../LICENSE 7 | 8 | -------------------------------------------------------------------------------- /docs/topics/contributing.rst: -------------------------------------------------------------------------------- 1 | .. _contributing: 2 | 3 | ============ 4 | Contributing 5 | ============ 6 | 7 | ``django-password-policies`` is an open source project managed using the Git 8 | version control system. The repository is hosted on `GitHub`_, so contributing 9 | is as easy as forking the project and committing back your enhancements. 10 | 11 | Please note the following guidelines for contributing: 12 | 13 | * Contributed code must be written in the existing style. This is 14 | as simple as following the `Django coding style`_ and (most 15 | importantly) `PEP 8`_. 16 | * Contributions must be available on a separately named branch 17 | based on the latest version of the main branch. 18 | * Run the tests before committing your changes. If your changes 19 | cause the tests to break, they won't be accepted. 20 | * If you are adding new functionality, you must include basic tests 21 | and documentation. 22 | * If you write tests you should use the included BaseTest and use test 23 | fixtures:: 24 | 25 | from password_policies.tests.lib import BaseTest 26 | 27 | class CustomTest(BaseTest): 28 | 29 | fixtures = ['django_password_policies_custom_fixtures.json'] 30 | 31 | def test_something(self): 32 | pass 33 | 34 | * Documentation must be formatted to be used with `Sphinx`_. 35 | 36 | .. _`PEP 8`: http://www.python.org/dev/peps/pep-0008/ 37 | .. _`Django coding style`: http://docs.djangoproject.com/en/dev/internals/contributing/#coding-style 38 | .. _`GitHub`: https://github.com/tarak/django-password-policies/ 39 | .. _`Sphinx`: http://sphinx.pocoo.org/ 40 | -------------------------------------------------------------------------------- /docs/topics/custom.validation.rst: -------------------------------------------------------------------------------- 1 | .. _custom-validation: 2 | 3 | ====================== 4 | Customizing validation 5 | ====================== 6 | 7 | .. _built-in-validators: 8 | 9 | ----------------------------- 10 | Using the built-in validators 11 | ----------------------------- 12 | 13 | The built-in validators can be customized by changing values in a project's 14 | settings file. 15 | 16 | A list of built-in validators is available at: 17 | 18 | * :ref:`api-validators` 19 | 20 | A list of default application settings is available at: 21 | 22 | * :ref:`api-settings` 23 | 24 | .. _custom-use: 25 | 26 | --------------------------------- 27 | Customizing by sub-classing forms 28 | --------------------------------- 29 | 30 | Customizing password validation can be used by simply using a 31 | :formfield:`PasswordPoliciesField` and :form:`PasswordPoliciesForm`:: 32 | 33 | from password_policies.conf import settings 34 | from password_policies.forms import PasswordPoliciesForm 35 | from password_policies.forms.fields import PasswordPoliciesField 36 | 37 | from your_app import your_custom_validators 38 | 39 | 40 | class CustomPasswordPoliciesForm(PasswordPoliciesForm): 41 | """ 42 | A form that lets a user set his/her password without entering the 43 | old password. 44 | """ 45 | new_password1 = PasswordPoliciesField(label=_("New password"), 46 | max_length=settings.PASSWORD_MAX_LENGTH, 47 | min_length=settings.PASSWORD_MIN_LENGTH, 48 | validators=[your_custom_validators.some_validator, 49 | your_custom_validators.another_validator],) 50 | 51 | def clean(self): 52 | cleaned_data = super(CustomPasswordPoliciesForm, self).clean() 53 | new_password1 = cleaned_data.get("new_password1") 54 | new_password2 = cleaned_data.get("new_password2") 55 | 56 | if new_password1 and new_password2: 57 | # Perform additional validation... 58 | pass 59 | 60 | # Always return the full collection of cleaned data. 61 | return cleaned_data 62 | 63 | To use the form with the built-in :view:`PasswordResetConfirmView` an 64 | URL pattern needs to be added to a project's ``URLconf``:: 65 | 66 | 67 | from password_policies.views import PasswordResetConfirmView 68 | 69 | from your_app.forms import CustomPasswordPoliciesForm 70 | 71 | urlpatterns = patterns('', 72 | (r'^password/reset/', PasswordResetConfirmView.as_view(form_class=CustomPasswordPoliciesForm)), 73 | ) 74 | -------------------------------------------------------------------------------- /docs/topics/force.password.change.rst: -------------------------------------------------------------------------------- 1 | .. _forced-password-changes: 2 | 3 | ======================== 4 | Forcing password changes 5 | ======================== 6 | 7 | .. note:: 8 | Forcing password changes only works if 9 | the :doc:`password history ` is activated. 10 | 11 | ``django-password-policies`` provides the possibility to force password resets 12 | when user passwords expire. To activate forced password changes for a project 13 | different settings need to be set: 14 | 15 | .. _password-change-requirements: 16 | 17 | ------------ 18 | Requirements 19 | ------------ 20 | 21 | To use the password change feature Django's authentication and sessions 22 | framework is used. It must be set up correctly for the middleware and the 23 | context processor to work:: 24 | 25 | INSTALLED_APPS = ( 26 | 'django.contrib.auth', 27 | 'django.contrib.contenttypes', 28 | 'django.contrib.sessions', 29 | 'django.contrib.sites', 30 | 'password_policies', 31 | ) 32 | 33 | For more informations on the authentication and sessions framework please 34 | consult the `Django documentation`_. 35 | 36 | .. _password-change-expiry: 37 | 38 | ----------------------- 39 | Setting password expiry 40 | ----------------------- 41 | 42 | To customize the duration of a password the following setting can be added to a 43 | project's settings file:: 44 | 45 | # Defaults to 60 days. 46 | PASSWORD_DURATION_SECONDS = 24 * 60**3 47 | 48 | .. _password-change-middleware: 49 | 50 | -------------------- 51 | Using the middleware 52 | -------------------- 53 | 54 | Forcing password changes is done using the 55 | :middleware:`PasswordChangeMiddleware`. To use it add it to the list of 56 | ``MIDDLEWARE_CLASSES`` in a project's settings file:: 57 | 58 | MIDDLEWARE_CLASSES = ( 59 | 'django.middleware.common.CommonMiddleware', 60 | 'django.contrib.sessions.middleware.SessionMiddleware', 61 | 'django.middleware.csrf.CsrfViewMiddleware', 62 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 63 | 'password_policies.middleware.PasswordChangeMiddleware', 64 | # ... other middlewares ... 65 | ) 66 | 67 | .. note:: 68 | The order of this middleware in the stack is important, 69 | it must be listed after the authentication AND the session 70 | middlewares. 71 | 72 | .. _password-change-context-processor: 73 | 74 | --------------------------- 75 | Using the context processor 76 | --------------------------- 77 | 78 | ``django-password-policies`` provides a context processor that adds a template 79 | variable to the context. To use it add it to the list of 80 | ``TEMPLATE_CONTEXT_PROCESSORS`` in a project's settings file:: 81 | 82 | TEMPLATE_CONTEXT_PROCESSORS = ( 83 | 'django.contrib.auth.context_processors.auth', 84 | 'django.core.context_processors.debug', 85 | 'django.core.context_processors.i18n', 86 | 'django.contrib.messages.context_processors.messages', 87 | 'password_policies.context_processors.password_status', 88 | ) 89 | 90 | Then the template for the password change view can display a message if the user 91 | is required to change his/her password:: 92 | 93 | {% extends 'registration/base.html' %} 94 | {% load i18n %} 95 | {% if password_change_required %} 96 |

{% trans "Your password has expired. Please change it using the form below." %}

97 | {% endif %} 98 |
{% csrf_token %} 99 | {{ form.as_p }}{% if next %} 100 | {% endif %} 101 | 102 |
103 | 104 | .. _`Django documentation`: https://docs.djangoproject.com/en/dev/ 105 | -------------------------------------------------------------------------------- /docs/topics/install.rst: -------------------------------------------------------------------------------- 1 | .. _install: 2 | 3 | ============ 4 | Installation 5 | ============ 6 | 7 | .. _install-requirements: 8 | 9 | Requirements 10 | ============ 11 | 12 | This application requires 13 | 14 | * `Django`_ 1.7 or newer 15 | * `django-easysettings`_ 16 | 17 | .. _install-cracklib: 18 | 19 | Cracklib 20 | ======== 21 | 22 | To use the included :class:`~password_policies.forms.validators.CracklibValidator` 23 | the `Python bindings for cracklib`_ need to be installed. 24 | 25 | .. warning:: 26 | The :class:`~password_policies.forms.validators.CracklibValidator` is not 27 | used if the crack module is not installed. 28 | 29 | On most linux distros it can simply be installed via a package manager. On 30 | Debian based distributions the according package is called: 31 | 32 | * python-cracklib 33 | 34 | .. _install-levenshtein: 35 | 36 | Levenshtein 37 | =========== 38 | 39 | The included :class:`~password_policies.forms.PasswordPoliciesChangeForm` uses 40 | the `Levenshtein Python C extension module`_. 41 | 42 | .. warning:: 43 | The :class:`~password_policies.forms.PasswordPoliciesChangeForm` does not 44 | compare both the old and new password if the module is not installed. 45 | 46 | On most linux distros it can simply be installed via a package manager. On 47 | Debian based distributions the according package is called: 48 | 49 | * python-levenshtein 50 | 51 | .. _install-pypi: 52 | 53 | From Pypi 54 | ========= 55 | 56 | To install from `PyPi`_:: 57 | 58 | [sudo] pip install django-password-policies 59 | 60 | or:: 61 | 62 | [sudo] easy_install django-password-policies 63 | 64 | .. _`PyPi`: https://pypi.python.org/pypi/django-password-policies 65 | 66 | .. _install-source: 67 | 68 | From source 69 | =========== 70 | 71 | The latest release package can be downloaded from `the GitHub download page`_. 72 | 73 | .. _`the GitHub download page`: https://github.com/tarak/django-password-policies/releases 74 | 75 | Once you've downloaded the package, unpack it (on most operating systems, simply 76 | double-click; alternately, at a command line on Linux, Mac OS X or other 77 | Unix-like systems, type):: 78 | 79 | $ tar zxvf django-password-policies-.tar.gz 80 | 81 | This will create the directory:: 82 | 83 | django-password-policies- 84 | 85 | which contains 86 | the ``setup.py`` installation script. From a command line in that directory, 87 | type:: 88 | 89 | python setup.py install 90 | 91 | Note that on some systems you may need to execute this with 92 | administrative privileges (e.g., ``sudo python setup.py install``). 93 | 94 | Another possibility to install the application is to create a link to the app 95 | inside the Python path:: 96 | 97 | $ sudo ln -s django-password-policies/password_policies /path/to/python_site_packages/password_policies 98 | 99 | 100 | .. _`Django`: https://www.djangoproject.com/ 101 | .. _`django-easysettings`: https://github.com/SmileyChris/django-easysettings 102 | .. _`Python bindings for cracklib`: http://www.nongnu.org/python-crack/ 103 | .. _`Levenshtein Python C extension module`: https://github.com/miohtama/python-Levenshtein 104 | -------------------------------------------------------------------------------- /docs/topics/internationalization.rst: -------------------------------------------------------------------------------- 1 | .. _internationalization: 2 | 3 | ==================== 4 | Internationalization 5 | ==================== 6 | 7 | ``django-password-policies`` makes full use of translation strings, which allow 8 | ``django-password-policies`` to be translated into multiple languages using 9 | `Django's internationalization`_ methodology. Translations are managed on and 10 | can also be submitted via `GitHub`_. Consult the documentation for `Django's 11 | internationalization`_ methodology for more information on creating translations 12 | and using them. 13 | 14 | .. _`Django's internationalization`: https://docs.djangoproject.com/en/dev/topics/i18n/translation/ 15 | .. _`GitHub`: https://github.com/tarak/django-password-policies/ 16 | -------------------------------------------------------------------------------- /docs/topics/overview.rst: -------------------------------------------------------------------------------- 1 | .. _overview: 2 | 3 | ======== 4 | Overview 5 | ======== 6 | 7 | .. _features: 8 | 9 | -------- 10 | Features 11 | -------- 12 | 13 | ``django-password-policies`` is an application for the `Django`_ framework that 14 | 15 | * provides a form field and forms that handle the validation of 16 | unicode passwords using different validators, see :ref:`api-validators`. 17 | 18 | * checks that passwords containing unicode characters conform to `RFC 4013`_, 19 | including checks for 20 | 21 | - bidirectional characters and 22 | - invalid unicode characters. 23 | 24 | * verifies if passwords contain 25 | 26 | - consecutive repetitions of the same characters, 27 | - common sequences, 28 | - dictionary words, using 29 | 30 | + `Python bindings for cracklib`_, 31 | + a custom dictionary 32 | + and a list of words specific to each project. 33 | 34 | * verifies that a new password is not too similar to an old one when a user 35 | changes his/her password. 36 | 37 | * verifies that a new password is not equal to an email address. 38 | 39 | * implements a password history for users making it possible to check if users 40 | try to use passwords again. 41 | 42 | * uses `Django`_'s cryptographic signing API to generate one-time secret URLs 43 | for password resets. 44 | 45 | .. _`Django`: https://www.djangoproject.com/ 46 | .. _`RFC 4013`: http://tools.ietf.org/html/rfc4013 47 | .. _`Python bindings for cracklib`: http://www.nongnu.org/python-crack/ 48 | -------------------------------------------------------------------------------- /docs/topics/password.history.rst: -------------------------------------------------------------------------------- 1 | .. _password-history: 2 | 3 | ========================== 4 | Using the password history 5 | ========================== 6 | 7 | ``django-password-policies`` provides a password history to "remember" user 8 | passwords. To deactivate the password history for a project the following needs 9 | to be added to a project's settings file:: 10 | 11 | # Defaults to True 12 | PASSWORD_USE_HISTORY = False 13 | 14 | To customize how many passwords are saved in a user's password history the 15 | following setting can be set:: 16 | 17 | # Defaults to 10 18 | PASSWORD_HISTORY_COUNT = 20 19 | 20 | Each time a user changes his/her password it is counted how many entries in a 21 | user's password history exist. If there a more than 22 | :py:attr:`~password_policies.conf.Settings.PASSWORD_HISTORY_COUNT` older entries 23 | are deleted automatically from the user's password history upon successfull 24 | password change. 25 | -------------------------------------------------------------------------------- /docs/topics/security.rst: -------------------------------------------------------------------------------- 1 | .. _security: 2 | 3 | ======== 4 | Security 5 | ======== 6 | 7 | .. _notes: 8 | 9 | -------------------- 10 | Notes about security 11 | -------------------- 12 | 13 | The use of a security related application like this one implies consequences. 14 | The following notes should be read carefully to understand how this application 15 | works: 16 | 17 | * When a user changes his/her password, and only then, the old password is 18 | compared to the new using the Levenshtein algorithm. This of course doesn't 19 | work doing a password reset, obviously because the user has forgotten the old 20 | password. 21 | 22 | * This application only counts letters, numbers and symbols in passwords. It 23 | does not try to differentiate between upper- or lowercase letter, simply 24 | because there are languages without uppercase letters. Forcing users speaking 25 | only these languages to use characters of "foreign" scripts is not really 26 | user friendly. The usage of unicode characters and especially numbers and 27 | symbols makes it hard enough to crack such a password. 28 | 29 | * The minimum length of a password is the required number of letters, numbers 30 | and symbols. The :class:`~password_policies.forms.fields.PasswordPoliciesField` uses 31 | the :attr:`min_length` attribute, but the usage only makes sense if you want 32 | to, in example, enforce 3 letters, 1 number and 1 symbol in a password with 33 | a minimum length of 8 characters, which is the default, by the way... 34 | 35 | * The maximum length for a password is not limited by default, but can easily 36 | be set using :ref:`api-settings`. 37 | 38 | * Using the dictionary validator is basically opening a text file with a single 39 | word per line, reading ALL lines into memory and perform validation. 40 | 41 | The same applies to the list of words specific to each project. 42 | 43 | This slows down the validator depending of the sizes of lines or list entries. 44 | 45 | Also note that the validator opens the text file each time it is called. 46 | 47 | Therefore, the validator is disabled by default, but can easily be enabled in 48 | each projects :ref:`api-settings`. 49 | 50 | * The validator using the `Python bindings for cracklib`_ does not handle 51 | unicode characters and is disabled by default. Considering the advantage of 52 | such a validator, it was included in this application anyway. Like the 53 | dictionary validator it is disabled by default, but can easily be enabled in 54 | each projects :ref:`api-settings`. 55 | 56 | * The password history, if enabled, stores the user's password by generating a 57 | newly encrypted version of the new password, each time a user changes his/her 58 | password, using the included ``django-password-policies`` forms. Django 59 | includes a mechanism to compare a raw password with different encrypted 60 | passwords. No unencrypted password is saved to the database! 61 | 62 | .. _`Python bindings for cracklib`: http://www.nongnu.org/python-crack/ 63 | -------------------------------------------------------------------------------- /docs/topics/support.rst: -------------------------------------------------------------------------------- 1 | .. _support: 2 | 3 | Getting help 4 | ============ 5 | 6 | At the present time this help is available: 7 | 8 | 9 | * Looking for specific information? Try the :ref:`genindex`, :ref:`modindex` or 10 | the :doc:`detailed table of contents <../contents>`. 11 | 12 | * To report a bug or other type of issue, please use the `GitHub issue tracker`_. 13 | 14 | .. _`GitHub issue tracker`: https://github.com/tarak/django-password-policies/issues 15 | 16 | -------------------------------------------------------------------------------- /docs/topics/testing.rst: -------------------------------------------------------------------------------- 1 | .. _testing: 2 | 3 | ======= 4 | Testing 5 | ======= 6 | 7 | django-password-policies provides unit tests to test the application. These 8 | tests do not require to be run from within a project. They can be executed in 9 | the application's source directory:: 10 | 11 | $ python setup.py test 12 | 13 | -------------------------------------------------------------------------------- /password_policies/__init__.py: -------------------------------------------------------------------------------- 1 | VERSION = (0, 4, 3, 'beta', 0) 2 | 3 | 4 | def get_version(version=None): 5 | """Derives a PEP386-compliant version number from VERSION.""" 6 | if version is None: 7 | version = VERSION 8 | assert len(version) == 5 9 | assert version[3] in ('alpha', 'beta', 'rc', 'final') 10 | 11 | # Now build the two parts of the version number: 12 | # main = X.Y[.Z] 13 | # sub = .devN - for pre-alpha releases 14 | # | {a|b|c}N - for alpha, beta and rc releases 15 | 16 | parts = 2 if version[2] == 0 else 3 17 | main = '.'.join(str(x) for x in version[:parts]) 18 | 19 | sub = '' 20 | if version[3] == 'alpha' and version[4] == 0: 21 | # At the toplevel, this would cause an import loop. 22 | from django.utils.version import get_git_changeset 23 | git_changeset = get_git_changeset() 24 | if git_changeset != 'unknown': 25 | sub = '.dev%s' % git_changeset 26 | 27 | elif version[3] != 'final': 28 | mapping = {'alpha': 'a', 'beta': 'b', 'rc': 'c'} 29 | sub = mapping[version[3]] + str(version[4]) 30 | 31 | return main + sub 32 | 33 | 34 | __version__ = get_version() 35 | -------------------------------------------------------------------------------- /password_policies/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.utils.translation import ugettext_lazy as _ 3 | 4 | from password_policies.conf import settings 5 | from password_policies.models import PasswordHistory 6 | from password_policies.models import PasswordChangeRequired 7 | 8 | 9 | def force_password_change(modeladmin, request, queryset): 10 | for user in queryset.all(): 11 | PasswordChangeRequired.objects.create(user=user) 12 | force_password_change.short_description = _('Force password change for selected' 13 | ' users') 14 | 15 | 16 | class PasswordHistoryAdmin(admin.ModelAdmin): 17 | date_hierarchy = 'created' 18 | exclude = ('password',) 19 | list_display = ('id', 'user', 'created') 20 | list_display_links = ('id', 'user',) 21 | search_fields = settings.PASSWORD_HISTORY_ADMIN_SEARCH_FIELDS 22 | readonly_fields = ('user', 'created') 23 | 24 | def has_add_permission(self, request): 25 | return False 26 | 27 | 28 | class PasswordChangeRequiredAdmin(admin.ModelAdmin): 29 | date_hierarchy = 'created' 30 | list_display = ('id', 'user', 'created') 31 | list_display_links = ('id', 'user',) 32 | search_fields = settings.PASSWORD_CHANGE_REQUIRED_ADMIN_SEARCH_FIELDS 33 | readonly_fields = ('user', 'created') 34 | 35 | def get_readonly_fields(self, request, obj=None): 36 | """ 37 | Sets the ``user`` and the ``created`` field to read only if an instance 38 | already exists. 39 | """ 40 | if obj: 41 | return ['user'] 42 | else: 43 | return [] 44 | 45 | 46 | admin.site.register(PasswordHistory, PasswordHistoryAdmin) 47 | admin.site.register(PasswordChangeRequired, PasswordChangeRequiredAdmin) 48 | -------------------------------------------------------------------------------- /password_policies/context_processors.py: -------------------------------------------------------------------------------- 1 | from password_policies.models import PasswordHistory 2 | 3 | 4 | def password_status(request): 5 | """ 6 | Adds a variable determining the state of a user's password 7 | to the context if the user has authenticated: 8 | 9 | * ``password_change_required`` 10 | Determines if the user needs to change his/her password. 11 | 12 | Set to ``True`` if the user has to change his/her password, 13 | ``False`` otherwise. 14 | 15 | To use it add it to the list of ``TEMPLATE_CONTEXT_PROCESSORS`` 16 | in a project's settings file:: 17 | 18 | TEMPLATE_CONTEXT_PROCESSORS = ( 19 | 'django.contrib.auth.context_processors.auth', 20 | 'django.core.context_processors.debug', 21 | 'django.core.context_processors.i18n', 22 | 'django.contrib.messages.context_processors.messages', 23 | 'password_policies.context_processors.password_status', 24 | ) 25 | """ 26 | d = {} 27 | if request.user.is_authenticated(): 28 | if '_password_policies_change_required' not in request.session: 29 | r = PasswordHistory.objects.change_required(request.user) 30 | else: 31 | r = request.session['_password_policies_change_required'] 32 | d['password_change_required'] = r 33 | return d 34 | -------------------------------------------------------------------------------- /password_policies/forms/admin.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import AdminPasswordChangeForm 3 | from django.utils.translation import ugettext_lazy as _ 4 | 5 | from password_policies.conf import settings 6 | from password_policies.forms.fields import PasswordPoliciesField 7 | from password_policies.models import PasswordHistory 8 | from password_policies.models import PasswordChangeRequired 9 | 10 | 11 | class PasswordPoliciesAdminForm(AdminPasswordChangeForm): 12 | """Enforces password policies in the admin interface. 13 | 14 | Use this form to enforce strong passwords in the admin interface. 15 | """ 16 | error_messages = { 17 | 'password_mismatch': _("The two password fields didn't match."), 18 | 'password_used': _("The new password was used before. Please enter another one.") 19 | } 20 | 21 | password1 = PasswordPoliciesField(label=_("Password new"), 22 | max_length=settings.PASSWORD_MAX_LENGTH, 23 | min_length=settings.PASSWORD_MIN_LENGTH 24 | ) 25 | 26 | def clean_password1(self): 27 | """ 28 | Validates that a given password was not used before. 29 | """ 30 | password1 = self.cleaned_data.get('password1') 31 | if settings.PASSWORD_USE_HISTORY: 32 | if self.user.check_password(password1): 33 | raise forms.ValidationError( 34 | self.error_messages['password_used']) 35 | if not PasswordHistory.objects.check_password(self.user, 36 | password1): 37 | raise forms.ValidationError( 38 | self.error_messages['password_used']) 39 | return password1 40 | 41 | 42 | class ForceChangeAdminForm(PasswordPoliciesAdminForm): 43 | change_required = forms.BooleanField(initial=True, required=False, label=_('Must change?')) 44 | 45 | def save(self, commit=True): 46 | user = super(ForceChangeAdminForm, self).save(commit=commit) 47 | if self.cleaned_data["change_required"] and not PasswordChangeRequired.objects.filter(user=user).count(): 48 | PasswordChangeRequired.objects.create(user=user) 49 | return user 50 | 51 | 52 | class ForceChangeRequiredAdminForm(PasswordPoliciesAdminForm): 53 | 54 | def save(self, commit=True): 55 | user = super(ForceChangeRequiredAdminForm, self).save(commit=commit) 56 | if not PasswordChangeRequired.objects.filter(user=user).count(): 57 | PasswordChangeRequired.objects.create(user=user) 58 | return user 59 | -------------------------------------------------------------------------------- /password_policies/forms/fields.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from password_policies.forms.validators import validate_common_sequences 4 | from password_policies.forms.validators import validate_consecutive_count 5 | from password_policies.forms.validators import validate_cracklib 6 | from password_policies.forms.validators import validate_dictionary_words 7 | from password_policies.forms.validators import validate_entropy 8 | from password_policies.forms.validators import validate_letter_count 9 | from password_policies.forms.validators import validate_number_count 10 | from password_policies.forms.validators import validate_symbol_count 11 | from password_policies.forms.validators import validate_not_email 12 | 13 | 14 | class PasswordPoliciesField(forms.CharField): 15 | """ 16 | A form field that validates a password using :ref:`api-validators`. 17 | """ 18 | default_validators = [validate_common_sequences, 19 | validate_consecutive_count, 20 | validate_cracklib, 21 | validate_dictionary_words, 22 | validate_letter_count, 23 | validate_number_count, 24 | validate_symbol_count, 25 | validate_entropy, 26 | validate_not_email] 27 | 28 | def __init__(self, *args, **kwargs): 29 | if "widget" not in kwargs: 30 | kwargs["widget"] = forms.PasswordInput(render_value=False) 31 | super(PasswordPoliciesField, self).__init__(*args, **kwargs) 32 | -------------------------------------------------------------------------------- /password_policies/locale/ar/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ar/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/az/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/az/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/az/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/bg/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/bg/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/bg/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/bn/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/bn/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/bn/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/bs/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/bs/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ca/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ca/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/cs/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/cs/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/cy/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/cy/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/da/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/da/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/da/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/de/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/de/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/el/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/el/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/el/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/en/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/en/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/en/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: models.py:13 21 | msgid "password" 22 | msgstr "" 23 | 24 | #: models.py:14 25 | msgid "user" 26 | msgstr "" 27 | 28 | #: models.py:15 29 | msgid "created" 30 | msgstr "" 31 | 32 | #: models.py:23 33 | msgid "password history entry" 34 | msgstr "" 35 | 36 | #: models.py:24 37 | msgid "password history entries" 38 | msgstr "" 39 | 40 | #: forms/__init__.py:26 41 | msgid "The two password fields didn't match." 42 | msgstr "" 43 | 44 | #: forms/__init__.py:27 45 | msgid "The new password was used before. Please enter another one." 46 | msgstr "" 47 | 48 | #: forms/__init__.py:30 49 | msgid "New password" 50 | msgstr "" 51 | 52 | #: forms/__init__.py:33 53 | msgid "New password confirmation" 54 | msgstr "" 55 | 56 | #: forms/__init__.py:96 57 | msgid "Your old password was entered incorrectly. Please enter it again." 58 | msgstr "" 59 | 60 | #: forms/__init__.py:98 61 | msgid "The old and the new password are too similar." 62 | msgstr "" 63 | 64 | #: forms/__init__.py:99 65 | msgid "The old and the new password are the same." 66 | msgstr "" 67 | 68 | #: forms/__init__.py:101 69 | msgid "Old password" 70 | msgstr "" 71 | 72 | #: forms/__init__.py:150 73 | msgid "" 74 | "That e-mail address doesn't have an associated user account. Are you sure " 75 | "you've registered?" 76 | msgstr "" 77 | 78 | #: forms/__init__.py:152 79 | msgid "" 80 | "The user account associated with this e-mail address cannot reset the " 81 | "password." 82 | msgstr "" 83 | 84 | #: forms/__init__.py:155 85 | msgid "E-mail" 86 | msgstr "" 87 | 88 | #: forms/validators.py:152 89 | msgid "The new password contains ambiguous bidirectional characters." 90 | msgstr "" 91 | 92 | #: forms/validators.py:171 93 | msgid "The new password is based on a common sequence of characters." 94 | msgstr "" 95 | 96 | #: forms/validators.py:189 97 | #, python-format 98 | msgid "" 99 | "The new password contains consecutive characters. Only %(count)d consecutive " 100 | "character is allowed." 101 | msgid_plural "" 102 | "The new password contains consecutive characters. Only %(count)d consecutive " 103 | "characters are allowed." 104 | msgstr[0] "" 105 | msgstr[1] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | msgstr[1] "" 130 | 131 | #: forms/validators.py:430 132 | msgid "The new password is similar to an email address." 133 | msgstr "" 134 | 135 | #: forms/validators.py:466 136 | #, python-format 137 | msgid "The new password must contain %d or more number." 138 | msgid_plural "The new password must contain %d or more numbers." 139 | msgstr[0] "" 140 | msgstr[1] "" 141 | 142 | #: forms/validators.py:519 143 | #, python-format 144 | msgid "The new password must contain %d or more symbol." 145 | msgid_plural "The new password must contain %d or more symbols." 146 | msgstr[0] "" 147 | msgstr[1] "" 148 | -------------------------------------------------------------------------------- /password_policies/locale/en_GB/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/en_GB/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/es/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/es/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/es_AR/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/es_AR/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/es_MX/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/es_MX/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/es_NI/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/es_NI/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/es_NI/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: models.py:13 21 | msgid "password" 22 | msgstr "" 23 | 24 | #: models.py:14 25 | msgid "user" 26 | msgstr "" 27 | 28 | #: models.py:15 29 | msgid "created" 30 | msgstr "" 31 | 32 | #: models.py:23 33 | msgid "password history entry" 34 | msgstr "" 35 | 36 | #: models.py:24 37 | msgid "password history entries" 38 | msgstr "" 39 | 40 | #: forms/__init__.py:26 41 | msgid "The two password fields didn't match." 42 | msgstr "" 43 | 44 | #: forms/__init__.py:27 45 | msgid "The new password was used before. Please enter another one." 46 | msgstr "" 47 | 48 | #: forms/__init__.py:30 49 | msgid "New password" 50 | msgstr "" 51 | 52 | #: forms/__init__.py:33 53 | msgid "New password confirmation" 54 | msgstr "" 55 | 56 | #: forms/__init__.py:96 57 | msgid "Your old password was entered incorrectly. Please enter it again." 58 | msgstr "" 59 | 60 | #: forms/__init__.py:98 61 | msgid "The old and the new password are too similar." 62 | msgstr "" 63 | 64 | #: forms/__init__.py:99 65 | msgid "The old and the new password are the same." 66 | msgstr "" 67 | 68 | #: forms/__init__.py:101 69 | msgid "Old password" 70 | msgstr "" 71 | 72 | #: forms/__init__.py:150 73 | msgid "" 74 | "That e-mail address doesn't have an associated user account. Are you sure " 75 | "you've registered?" 76 | msgstr "" 77 | 78 | #: forms/__init__.py:152 79 | msgid "" 80 | "The user account associated with this e-mail address cannot reset the " 81 | "password." 82 | msgstr "" 83 | 84 | #: forms/__init__.py:155 85 | msgid "E-mail" 86 | msgstr "" 87 | 88 | #: forms/validators.py:152 89 | msgid "The new password contains ambiguous bidirectional characters." 90 | msgstr "" 91 | 92 | #: forms/validators.py:171 93 | msgid "The new password is based on a common sequence of characters." 94 | msgstr "" 95 | 96 | #: forms/validators.py:189 97 | #, python-format 98 | msgid "" 99 | "The new password contains consecutive characters. Only %(count)d consecutive " 100 | "character is allowed." 101 | msgid_plural "" 102 | "The new password contains consecutive characters. Only %(count)d consecutive " 103 | "characters are allowed." 104 | msgstr[0] "" 105 | msgstr[1] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | msgstr[1] "" 130 | 131 | #: forms/validators.py:430 132 | msgid "The new password is similar to an email address." 133 | msgstr "" 134 | 135 | #: forms/validators.py:466 136 | #, python-format 137 | msgid "The new password must contain %d or more number." 138 | msgid_plural "The new password must contain %d or more numbers." 139 | msgstr[0] "" 140 | msgstr[1] "" 141 | 142 | #: forms/validators.py:519 143 | #, python-format 144 | msgid "The new password must contain %d or more symbol." 145 | msgid_plural "The new password must contain %d or more symbols." 146 | msgstr[0] "" 147 | msgstr[1] "" 148 | -------------------------------------------------------------------------------- /password_policies/locale/et/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/et/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/et/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/eu/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/eu/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/eu/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/fa/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/fa/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/fa/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/fi/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/fi/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/fi/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/fr/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/fr/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/fr/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n > 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/fy_NL/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/fy_NL/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ga/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ga/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/gl/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/gl/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/gl/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/he/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/he/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/he/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/hi/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/hi/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/hi/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/hr/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/hr/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/hu/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/hu/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/hu/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/id/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/id/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/id/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/is/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/is/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/is/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | msgstr[1] "" 107 | 108 | #: forms/validators.py:250 109 | #, python-format 110 | msgid "Please choose a different password, %s." 111 | msgstr "" 112 | 113 | #: forms/validators.py:279 114 | msgid "The new password is not varied enough." 115 | msgstr "" 116 | 117 | #: forms/validators.py:339 118 | msgid "The new password is based on a dictionary word." 119 | msgstr "" 120 | 121 | #: forms/validators.py:374 122 | msgid "The new password contains invalid unicode characters." 123 | msgstr "" 124 | 125 | #: forms/validators.py:411 126 | #, python-format 127 | msgid "The new password must contain %d or more letter." 128 | msgid_plural "The new password must contain %d or more letters." 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: forms/validators.py:430 133 | msgid "The new password is similar to an email address." 134 | msgstr "" 135 | 136 | #: forms/validators.py:466 137 | #, python-format 138 | msgid "The new password must contain %d or more number." 139 | msgid_plural "The new password must contain %d or more numbers." 140 | msgstr[0] "" 141 | msgstr[1] "" 142 | 143 | #: forms/validators.py:519 144 | #, python-format 145 | msgid "The new password must contain %d or more symbol." 146 | msgid_plural "The new password must contain %d or more symbols." 147 | msgstr[0] "" 148 | msgstr[1] "" 149 | -------------------------------------------------------------------------------- /password_policies/locale/it/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/it/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ja/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ja/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ja/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/ka/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ka/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ka/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/km/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/km/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/km/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/kn/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/kn/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/kn/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/ko/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ko/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ko/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/lt/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/lt/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/lv/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/lv/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/mk/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/mk/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ml/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ml/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/mn/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/mn/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/nb/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/nb/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/nl/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/nl/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/nn/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/nn/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/no/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/no/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/no/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: models.py:13 21 | msgid "password" 22 | msgstr "" 23 | 24 | #: models.py:14 25 | msgid "user" 26 | msgstr "" 27 | 28 | #: models.py:15 29 | msgid "created" 30 | msgstr "" 31 | 32 | #: models.py:23 33 | msgid "password history entry" 34 | msgstr "" 35 | 36 | #: models.py:24 37 | msgid "password history entries" 38 | msgstr "" 39 | 40 | #: forms/__init__.py:26 41 | msgid "The two password fields didn't match." 42 | msgstr "" 43 | 44 | #: forms/__init__.py:27 45 | msgid "The new password was used before. Please enter another one." 46 | msgstr "" 47 | 48 | #: forms/__init__.py:30 49 | msgid "New password" 50 | msgstr "" 51 | 52 | #: forms/__init__.py:33 53 | msgid "New password confirmation" 54 | msgstr "" 55 | 56 | #: forms/__init__.py:96 57 | msgid "Your old password was entered incorrectly. Please enter it again." 58 | msgstr "" 59 | 60 | #: forms/__init__.py:98 61 | msgid "The old and the new password are too similar." 62 | msgstr "" 63 | 64 | #: forms/__init__.py:99 65 | msgid "The old and the new password are the same." 66 | msgstr "" 67 | 68 | #: forms/__init__.py:101 69 | msgid "Old password" 70 | msgstr "" 71 | 72 | #: forms/__init__.py:150 73 | msgid "" 74 | "That e-mail address doesn't have an associated user account. Are you sure " 75 | "you've registered?" 76 | msgstr "" 77 | 78 | #: forms/__init__.py:152 79 | msgid "" 80 | "The user account associated with this e-mail address cannot reset the " 81 | "password." 82 | msgstr "" 83 | 84 | #: forms/__init__.py:155 85 | msgid "E-mail" 86 | msgstr "" 87 | 88 | #: forms/validators.py:152 89 | msgid "The new password contains ambiguous bidirectional characters." 90 | msgstr "" 91 | 92 | #: forms/validators.py:171 93 | msgid "The new password is based on a common sequence of characters." 94 | msgstr "" 95 | 96 | #: forms/validators.py:189 97 | #, python-format 98 | msgid "" 99 | "The new password contains consecutive characters. Only %(count)d consecutive " 100 | "character is allowed." 101 | msgid_plural "" 102 | "The new password contains consecutive characters. Only %(count)d consecutive " 103 | "characters are allowed." 104 | msgstr[0] "" 105 | msgstr[1] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | msgstr[1] "" 130 | 131 | #: forms/validators.py:430 132 | msgid "The new password is similar to an email address." 133 | msgstr "" 134 | 135 | #: forms/validators.py:466 136 | #, python-format 137 | msgid "The new password must contain %d or more number." 138 | msgid_plural "The new password must contain %d or more numbers." 139 | msgstr[0] "" 140 | msgstr[1] "" 141 | 142 | #: forms/validators.py:519 143 | #, python-format 144 | msgid "The new password must contain %d or more symbol." 145 | msgid_plural "The new password must contain %d or more symbols." 146 | msgstr[0] "" 147 | msgstr[1] "" 148 | -------------------------------------------------------------------------------- /password_policies/locale/pa/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/pa/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/pl/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/pl/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/pt/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/pt/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/pt_BR/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/pt_BR/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ro/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ro/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ru/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ru/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/sk/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/sk/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/sl/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/sl/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/sq/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/sq/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/sr/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/sr/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/sr_Latn/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/sr_Latn/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/sv/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/sv/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ta/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ta/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/te/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/te/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/th/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/th/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/th/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/tr/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/tr/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/tr/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/uk/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/uk/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/ur/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/ur/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/vi/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/vi/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/vi/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/zh_CN/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/zh_CN/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/zh_CN/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/locale/zh_TW/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/locale/zh_TW/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /password_policies/locale/zh_TW/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2012-09-28 17:45+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0\n" 20 | 21 | #: models.py:13 22 | msgid "password" 23 | msgstr "" 24 | 25 | #: models.py:14 26 | msgid "user" 27 | msgstr "" 28 | 29 | #: models.py:15 30 | msgid "created" 31 | msgstr "" 32 | 33 | #: models.py:23 34 | msgid "password history entry" 35 | msgstr "" 36 | 37 | #: models.py:24 38 | msgid "password history entries" 39 | msgstr "" 40 | 41 | #: forms/__init__.py:26 42 | msgid "The two password fields didn't match." 43 | msgstr "" 44 | 45 | #: forms/__init__.py:27 46 | msgid "The new password was used before. Please enter another one." 47 | msgstr "" 48 | 49 | #: forms/__init__.py:30 50 | msgid "New password" 51 | msgstr "" 52 | 53 | #: forms/__init__.py:33 54 | msgid "New password confirmation" 55 | msgstr "" 56 | 57 | #: forms/__init__.py:96 58 | msgid "Your old password was entered incorrectly. Please enter it again." 59 | msgstr "" 60 | 61 | #: forms/__init__.py:98 62 | msgid "The old and the new password are too similar." 63 | msgstr "" 64 | 65 | #: forms/__init__.py:99 66 | msgid "The old and the new password are the same." 67 | msgstr "" 68 | 69 | #: forms/__init__.py:101 70 | msgid "Old password" 71 | msgstr "" 72 | 73 | #: forms/__init__.py:150 74 | msgid "" 75 | "That e-mail address doesn't have an associated user account. Are you sure " 76 | "you've registered?" 77 | msgstr "" 78 | 79 | #: forms/__init__.py:152 80 | msgid "" 81 | "The user account associated with this e-mail address cannot reset the " 82 | "password." 83 | msgstr "" 84 | 85 | #: forms/__init__.py:155 86 | msgid "E-mail" 87 | msgstr "" 88 | 89 | #: forms/validators.py:152 90 | msgid "The new password contains ambiguous bidirectional characters." 91 | msgstr "" 92 | 93 | #: forms/validators.py:171 94 | msgid "The new password is based on a common sequence of characters." 95 | msgstr "" 96 | 97 | #: forms/validators.py:189 98 | #, python-format 99 | msgid "" 100 | "The new password contains consecutive characters. Only %(count)d consecutive " 101 | "character is allowed." 102 | msgid_plural "" 103 | "The new password contains consecutive characters. Only %(count)d consecutive " 104 | "characters are allowed." 105 | msgstr[0] "" 106 | 107 | #: forms/validators.py:250 108 | #, python-format 109 | msgid "Please choose a different password, %s." 110 | msgstr "" 111 | 112 | #: forms/validators.py:279 113 | msgid "The new password is not varied enough." 114 | msgstr "" 115 | 116 | #: forms/validators.py:339 117 | msgid "The new password is based on a dictionary word." 118 | msgstr "" 119 | 120 | #: forms/validators.py:374 121 | msgid "The new password contains invalid unicode characters." 122 | msgstr "" 123 | 124 | #: forms/validators.py:411 125 | #, python-format 126 | msgid "The new password must contain %d or more letter." 127 | msgid_plural "The new password must contain %d or more letters." 128 | msgstr[0] "" 129 | 130 | #: forms/validators.py:430 131 | msgid "The new password is similar to an email address." 132 | msgstr "" 133 | 134 | #: forms/validators.py:466 135 | #, python-format 136 | msgid "The new password must contain %d or more number." 137 | msgid_plural "The new password must contain %d or more numbers." 138 | msgstr[0] "" 139 | 140 | #: forms/validators.py:519 141 | #, python-format 142 | msgid "The new password must contain %d or more symbol." 143 | msgid_plural "The new password must contain %d or more symbols." 144 | msgstr[0] "" 145 | -------------------------------------------------------------------------------- /password_policies/managers.py: -------------------------------------------------------------------------------- 1 | from datetime import timedelta 2 | 3 | from django.db import models 4 | from django.utils import timezone 5 | from django.contrib.auth.hashers import identify_hasher 6 | from django.core.exceptions import ObjectDoesNotExist 7 | 8 | from password_policies.conf import settings 9 | 10 | 11 | class PasswordHistoryManager(models.Manager): 12 | default_offset = settings.PASSWORD_HISTORY_COUNT 13 | 14 | def delete_expired(self, user, offset=None): 15 | """ 16 | Deletes expired password history entries from the database(s). 17 | 18 | :arg user: A :class:`~django.contrib.auth.models.User` instance. 19 | :arg int offset: A number specifying how much entries are to be kept 20 | in the user's password history. Defaults 21 | to :py:attr:`~password_policies.conf.Settings.PASSWORD_HISTORY_COUNT`. 22 | """ 23 | if not offset: 24 | offset = self.default_offset 25 | qs = self.filter(user=user) 26 | if qs.count() > offset: 27 | entry = qs[offset:offset + 1].get() 28 | qs.filter(created__lte=entry.created).delete() 29 | 30 | def change_required(self, user): 31 | """ 32 | Checks if the user needs to change his/her password. 33 | 34 | :arg object user: A :class:`~django.contrib.auth.models.User` instance. 35 | :returns: ``True`` if the user needs to change his/her password, 36 | ``False`` otherwise. 37 | :rtype: bool 38 | """ 39 | newest = self.get_newest(user) 40 | if newest: 41 | last_change = newest.created 42 | else: 43 | # TODO: Do not rely on this property! 44 | last_change = user.date_joined 45 | d = timedelta(seconds=settings.PASSWORD_DURATION_SECONDS) 46 | expiry = timezone.now() - d 47 | if last_change < expiry: 48 | return True 49 | return False 50 | 51 | def check_password(self, user, raw_password): 52 | """ 53 | Compares a raw (UNENCRYPTED!!!) password to entries in the users's 54 | password history. 55 | 56 | :arg object user: A :class:`~django.contrib.auth.models.User` instance. 57 | :arg str raw_password: A unicode string representing a password. 58 | :returns: ``False`` if a password has been used before, ``True`` if not. 59 | :rtype: bool 60 | """ 61 | result = True 62 | if user.check_password(raw_password): 63 | result = False 64 | else: 65 | entries = self.filter(user=user).all()[:self.default_offset] 66 | for entry in entries: 67 | hasher = identify_hasher(entry.password) 68 | if hasher.verify(raw_password, entry.password): 69 | result = False 70 | break 71 | return result 72 | 73 | def get_newest(self, user): 74 | """ 75 | Gets the newest password history entry. 76 | 77 | :arg object user: A :class:`~django.contrib.auth.models.User` instance. 78 | :returns: A :class:`~password_policies.models.PasswordHistory` instance 79 | if found, ``None`` if not. 80 | """ 81 | try: 82 | entry = self.filter(user=user).latest() 83 | except ObjectDoesNotExist: 84 | return None 85 | return entry 86 | -------------------------------------------------------------------------------- /password_policies/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models, migrations 5 | from django.conf import settings 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='PasswordChangeRequired', 17 | fields=[ 18 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 19 | ('created', models.DateTimeField(auto_now_add=True, help_text='The date the entry was created.', verbose_name='created', db_index=True)), 20 | ('user', models.OneToOneField(related_name='password_change_required', verbose_name='user', to=settings.AUTH_USER_MODEL, help_text='The user who needs to change his/her password.')), 21 | ], 22 | options={ 23 | 'ordering': ['-created'], 24 | 'get_latest_by': 'created', 25 | 'verbose_name': 'enforced password change', 26 | 'verbose_name_plural': 'enforced password changes', 27 | }, 28 | bases=(models.Model,), 29 | ), 30 | migrations.CreateModel( 31 | name='PasswordHistory', 32 | fields=[ 33 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 34 | ('created', models.DateTimeField(auto_now_add=True, help_text='The date the entry was created.', verbose_name='created', db_index=True)), 35 | ('password', models.CharField(help_text='The encrypted password.', max_length=128, verbose_name='password')), 36 | ('user', models.ForeignKey(related_name='password_history_entries', verbose_name='user', to=settings.AUTH_USER_MODEL, help_text='The user this password history entry belongs to.')), 37 | ], 38 | options={ 39 | 'ordering': ['-created'], 40 | 'get_latest_by': 'created', 41 | 'verbose_name': 'password history entry', 42 | 'verbose_name_plural': 'password history entries', 43 | }, 44 | bases=(models.Model,), 45 | ), 46 | ] 47 | -------------------------------------------------------------------------------- /password_policies/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/migrations/__init__.py -------------------------------------------------------------------------------- /password_policies/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.utils.translation import ugettext_lazy as _ 3 | 4 | from password_policies.conf import settings 5 | from password_policies.managers import PasswordHistoryManager 6 | 7 | 8 | class PasswordChangeRequired(models.Model): 9 | """ 10 | Stores an entry to enforce password changes, related to :model:`auth.User`. 11 | 12 | Has the following fields: 13 | """ 14 | created = models.DateTimeField(auto_now_add=True, 15 | verbose_name=_('created'), db_index=True, 16 | help_text=_('The date the entry was ' 17 | 'created.')) 18 | user = models.OneToOneField(settings.AUTH_USER_MODEL, 19 | verbose_name=_('user'), 20 | help_text=_('The user who needs to change ' 21 | 'his/her password.'), 22 | related_name='password_change_required') 23 | 24 | class Meta: 25 | get_latest_by = 'created' 26 | ordering = ['-created'] 27 | verbose_name = _('enforced password change') 28 | verbose_name_plural = _('enforced password changes') 29 | 30 | 31 | class PasswordHistory(models.Model): 32 | """ 33 | Stores a single password history entry, related to :model:`auth.User`. 34 | 35 | Has the following fields: 36 | """ 37 | created = models.DateTimeField(auto_now_add=True, 38 | verbose_name=_('created'), db_index=True, 39 | help_text=_('The date the entry was ' 40 | 'created.')) 41 | password = models.CharField(max_length=128, verbose_name=_('password'), 42 | help_text=_('The encrypted password.')) 43 | user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'), 44 | help_text=_('The user this password history ' 45 | 'entry belongs to.'), 46 | related_name='password_history_entries') 47 | 48 | objects = PasswordHistoryManager() 49 | 50 | class Meta: 51 | get_latest_by = 'created' 52 | ordering = ['-created'] 53 | verbose_name = _('password history entry') 54 | verbose_name_plural = _('password history entries') 55 | -------------------------------------------------------------------------------- /password_policies/south_migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/south_migrations/__init__.py -------------------------------------------------------------------------------- /password_policies/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarak/django-password-policies/4816664e6f2e6bbebd996aee2dc74a73412e0802/password_policies/tests/__init__.py -------------------------------------------------------------------------------- /password_policies/tests/lib.py: -------------------------------------------------------------------------------- 1 | from datetime import timedelta 2 | from random import randint 3 | 4 | from django.contrib.auth import get_user_model 5 | from django.contrib.auth.hashers import make_password 6 | from django.utils import timezone 7 | from django.test import TestCase 8 | 9 | from password_policies.conf import settings 10 | from password_policies.models import PasswordHistory 11 | 12 | 13 | passwords = [ 14 | 'ohl"ahn8aiSu', 15 | 'la]ePhae1Ies', 16 | 'xareW&ang4sh', 17 | 'haea_d7AiWoo', 18 | 'Eim9Co:e0aev', 19 | 'Ve2eereil>ai', 20 | 'Aengae]t:ie4', 21 | 'ao6Lei+Hip=u', 22 | 'zo!i8aigai{L', 23 | 'Ju8AhGhoo(p?', 24 | 'xieY6fohv>ei', 25 | 'Elu1ie*z5aa3', 26 | 'ooDei1Hoo+Ru', 27 | 'Xohth3ohpu$o', 28 | 'ia)D5AP7sie$', 29 | 'heeb8aeCh-ae' 30 | ] 31 | 32 | 33 | class BaseTest(TestCase): 34 | 35 | def setUp(self): 36 | """ 37 | Isolate all application specific settings. 38 | """ 39 | output = super(BaseTest, self).setUp() 40 | settings.isolated = True 41 | return output 42 | 43 | def tearDown(self): 44 | """ 45 | Restore settings to their original state. 46 | """ 47 | settings.isolated = False 48 | settings.revert() 49 | return super(BaseTest, self).tearDown() 50 | 51 | 52 | def create_user(username="alice", email="alice@example.com", raw_password=None, 53 | date_joined=None, last_login=None, commit=True): 54 | """ Creates a non-staff user with dynamically generated properties. 55 | This function dynamically creates an user with following properties: 56 | - The user is neither an admin nor a staff member. 57 | - The user is active. 58 | - The date and his/her last login is generated dynamically. 59 | """ 60 | count = settings.PASSWORD_HISTORY_COUNT 61 | duration = settings.PASSWORD_DURATION_SECONDS 62 | if not raw_password: 63 | raw_password = passwords[-1] 64 | if not date_joined: 65 | rind = randint(0, (duration / count + 1)) 66 | seconds = (count * duration + rind) * 2 67 | date_joined = get_datetime_from_delta(timezone.now(), seconds) 68 | if not last_login: 69 | last_login = date_joined 70 | user = get_user_model()(username=username, email=email, is_active=True, last_login=last_login, date_joined=date_joined) 71 | user.set_password(raw_password) 72 | if commit: 73 | user.save() 74 | return user 75 | 76 | 77 | def create_password_history(user, password_list=[]): 78 | duration = settings.PASSWORD_DURATION_SECONDS 79 | if not password_list: 80 | password_list = passwords 81 | seconds = len(password_list) * duration 82 | created = get_datetime_from_delta(timezone.now(), seconds) 83 | for raw_password in password_list: 84 | password = make_password(raw_password) 85 | entry = PasswordHistory.objects.create(password=password, user=user) 86 | entry.created = created 87 | entry.save() 88 | created = get_datetime_from_delta(created, (duration * -1)) 89 | 90 | 91 | def get_datetime_from_delta(value, seconds): 92 | "Returns a Datetime value after subtracting given seconds." 93 | return value - timedelta(seconds=seconds) 94 | -------------------------------------------------------------------------------- /password_policies/tests/templates/403.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

403 Forbidden

9 | 10 | -------------------------------------------------------------------------------- /password_policies/tests/templates/registration/password_change_done.html: -------------------------------------------------------------------------------- 1 | E-mail sent -------------------------------------------------------------------------------- /password_policies/tests/templates/registration/password_change_form.html: -------------------------------------------------------------------------------- 1 | {{ form.as_ul }} -------------------------------------------------------------------------------- /password_policies/tests/templates/registration/password_reset_complete.html: -------------------------------------------------------------------------------- 1 | Password reset. -------------------------------------------------------------------------------- /password_policies/tests/templates/registration/password_reset_confirm.html: -------------------------------------------------------------------------------- 1 | {% if validlink %}Please enter your new password: {{ form }}{% else %}The password reset link was invalid.{% endif %} -------------------------------------------------------------------------------- /password_policies/tests/templates/registration/password_reset_done.html: -------------------------------------------------------------------------------- 1 | E-mail sent -------------------------------------------------------------------------------- /password_policies/tests/templates/registration/password_reset_email.html: -------------------------------------------------------------------------------- 1 | {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uid timestamp signature %} 2 | -------------------------------------------------------------------------------- /password_policies/tests/templates/registration/password_reset_email.txt: -------------------------------------------------------------------------------- 1 | {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uid timestamp signature %} 2 | -------------------------------------------------------------------------------- /password_policies/tests/templates/registration/password_reset_form.html: -------------------------------------------------------------------------------- 1 | {{ form.as_ul }} -------------------------------------------------------------------------------- /password_policies/tests/templates/registration/password_reset_subject.txt: -------------------------------------------------------------------------------- 1 | {% autoescape off %}Password reset on {{ site_name }}{% endautoescape %} 2 | -------------------------------------------------------------------------------- /password_policies/tests/test_middleware.py: -------------------------------------------------------------------------------- 1 | try: 2 | from urllib.parse import urljoin 3 | except ImportError: 4 | from urlparse import urljoin 5 | 6 | from django.core.urlresolvers import reverse 7 | from django.utils import timezone 8 | 9 | from password_policies.conf import settings 10 | from password_policies.models import PasswordChangeRequired 11 | from password_policies.models import PasswordHistory 12 | from password_policies.tests.lib import BaseTest 13 | from password_policies.tests.lib import create_user 14 | from password_policies.tests.lib import create_password_history 15 | from password_policies.tests.lib import get_datetime_from_delta 16 | from password_policies.tests.lib import passwords 17 | 18 | 19 | def get_response_location(location): 20 | if not location.startswith("http://testserver/"): 21 | location = urljoin("http://testserver/", location) 22 | return location 23 | 24 | 25 | class PasswordPoliciesMiddlewareTest(BaseTest): 26 | 27 | def setUp(self): 28 | self.user = create_user() 29 | self.redirect_url = 'http://testserver/password/change/?next=/' 30 | 31 | def test_password_middleware_without_history(self): 32 | seconds = settings.PASSWORD_DURATION_SECONDS - 60 33 | self.user.date_joined = get_datetime_from_delta(timezone.now(), seconds) 34 | self.user.last_login = get_datetime_from_delta(timezone.now(), seconds) 35 | self.user.save() 36 | self.client.login(username='alice', password=passwords[-1]) 37 | response = self.client.get(reverse('home')) 38 | self.assertEqual(response.status_code, 200) 39 | self.client.logout() 40 | 41 | def test_password_middleware_with_history(self): 42 | create_password_history(self.user) 43 | self.client.login(username='alice', password=passwords[-1]) 44 | response = self.client.get(reverse('home')) 45 | self.assertEqual(response.status_code, 302) 46 | self.assertEqual(get_response_location(response['Location']), self.redirect_url) 47 | self.client.logout() 48 | PasswordHistory.objects.filter(user=self.user).delete() 49 | 50 | def test_password_middleware_enforced_redirect(self): 51 | self.client.login(username='alice', password=passwords[-1]) 52 | response = self.client.get(reverse('home')) 53 | self.assertEqual(response.status_code, 302) 54 | self.assertEqual(get_response_location(response['Location']), self.redirect_url) 55 | self.client.logout() 56 | 57 | def test_password_change_required_enforced_redirect(self): 58 | seconds = settings.PASSWORD_DURATION_SECONDS - 60 59 | self.user.date_joined = get_datetime_from_delta(timezone.now(), seconds) 60 | self.user.last_login = get_datetime_from_delta(timezone.now(), seconds) 61 | self.user.save() 62 | p = PasswordChangeRequired.objects.create(user=self.user) 63 | self.client.login(username='alice', password=passwords[-1]) 64 | response = self.client.get(reverse('home')) 65 | self.assertEqual(response.status_code, 302) 66 | self.assertEqual(get_response_location(response['Location']), self.redirect_url) 67 | self.client.logout() 68 | p.delete() 69 | -------------------------------------------------------------------------------- /password_policies/tests/test_models.py: -------------------------------------------------------------------------------- 1 | from password_policies.conf import settings 2 | from password_policies.models import PasswordHistory 3 | from password_policies.tests.lib import BaseTest 4 | from password_policies.tests.lib import create_user 5 | from password_policies.tests.lib import create_password_history 6 | from password_policies.tests.lib import passwords 7 | 8 | 9 | class PasswordHistoryModelTestCase(BaseTest): 10 | 11 | def setUp(self): 12 | self.user = create_user() 13 | create_password_history(self.user) 14 | return super(PasswordHistoryModelTestCase, self).setUp() 15 | 16 | def test_password_history_expiration_with_offset(self): 17 | offset = settings.PASSWORD_HISTORY_COUNT + 2 18 | PasswordHistory.objects.delete_expired(self.user, offset=offset) 19 | count = PasswordHistory.objects.filter(user=self.user).count() 20 | self.assertEqual(count, offset) 21 | 22 | def test_password_history_expiration(self): 23 | PasswordHistory.objects.delete_expired(self.user) 24 | count = PasswordHistory.objects.filter(user=self.user).count() 25 | self.assertEqual(count, settings.PASSWORD_HISTORY_COUNT) 26 | 27 | def test_password_history_recent_passwords(self): 28 | self.failIf(PasswordHistory.objects.check_password(self.user, 29 | passwords[-1])) 30 | -------------------------------------------------------------------------------- /password_policies/tests/test_settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | DEBUG = False 4 | 5 | LANGUAGES = ( 6 | ('en', 'English'), 7 | ) 8 | 9 | LANGUAGE_CODE = 'en' 10 | 11 | USE_TZ = False 12 | # If you set this to False, Django will make some optimizations so as not 13 | # to load the internationalization machinery. 14 | USE_I18N = True 15 | 16 | SECRET_KEY = 'fake-key' 17 | 18 | INSTALLED_APPS = [ 19 | 'django.contrib.auth', 20 | 'django.contrib.contenttypes', 21 | 'django.contrib.sessions', 22 | 'django.contrib.sites', 23 | 'django.contrib.messages', 24 | "password_policies", 25 | ] 26 | 27 | DATABASES = { 28 | 'default': { 29 | 'ENGINE': 'django.db.backends.sqlite3', 30 | 'NAME': ':memory:', 31 | 'TEST_NAME': ':memory:', 32 | 'USER': '', 33 | 'PASSWORD': '', 34 | 'PORT': '', 35 | }, 36 | } 37 | 38 | ROOT_URLCONF = 'password_policies.tests.urls' 39 | 40 | SITE_ID = 1 41 | 42 | TEMPLATE_DIRS = ( 43 | os.path.join(os.path.dirname(__file__), 'templates'), 44 | ) 45 | 46 | MIDDLEWARE_CLASSES = ( 47 | 'django.middleware.common.CommonMiddleware', 48 | 'django.contrib.sessions.middleware.SessionMiddleware', 49 | 'django.middleware.csrf.CsrfViewMiddleware', 50 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 51 | 'password_policies.middleware.PasswordChangeMiddleware', 52 | 'django.contrib.messages.middleware.MessageMiddleware', 53 | ) 54 | 55 | TEMPLATE_CONTEXT_PROCESSORS = ( 56 | 'django.contrib.auth.context_processors.auth', 57 | 'django.core.context_processors.debug', 58 | 'django.core.context_processors.i18n', 59 | 'django.contrib.messages.context_processors.messages', 60 | 'password_policies.context_processors.password_status', 61 | ) 62 | 63 | SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' 64 | -------------------------------------------------------------------------------- /password_policies/tests/test_utils.py: -------------------------------------------------------------------------------- 1 | from password_policies.models import PasswordChangeRequired, PasswordHistory 2 | from password_policies.utils import PasswordCheck 3 | 4 | from password_policies.tests.lib import BaseTest 5 | from password_policies.tests.lib import create_user 6 | from password_policies.tests.lib import create_password_history 7 | 8 | 9 | class PasswordPoliciesUtilsTest(BaseTest): 10 | 11 | def setUp(self): 12 | self.user = create_user() 13 | self.check = PasswordCheck(self.user) 14 | create_password_history(self.user) 15 | return super(PasswordPoliciesUtilsTest, self).setUp() 16 | 17 | def test_password_check_is_required(self): 18 | # by default no change is required 19 | self.assertFalse(self.check.is_required()) 20 | 21 | # until a change is required (usually by middleware) 22 | PasswordChangeRequired.objects.create(user=self.user) 23 | self.assertTrue(self.check.is_required()) 24 | 25 | def test_password_check_is_expired(self): 26 | # `create_password_history` creates a history starting at 27 | # t - PASSWORD_DURATION_SECONDS, so the password is expired 28 | self.assertTrue(self.check.is_expired()) 29 | 30 | # now we create a password now, so it isn't expired 31 | PasswordHistory.objects.create(user=self.user, password='testpass') 32 | self.assertFalse(self.check.is_expired()) 33 | -------------------------------------------------------------------------------- /password_policies/tests/test_views.py: -------------------------------------------------------------------------------- 1 | from django.core.urlresolvers import reverse 2 | 3 | from password_policies.forms import PasswordPoliciesChangeForm 4 | from password_policies.models import PasswordHistory 5 | from password_policies.tests.lib import BaseTest 6 | from password_policies.tests.lib import create_user 7 | from password_policies.tests.lib import passwords 8 | 9 | 10 | class PasswordChangeViewsTestCase(BaseTest): 11 | 12 | def setUp(self): 13 | self.user = create_user() 14 | return super(PasswordChangeViewsTestCase, self).setUp() 15 | # 16 | 17 | def test_password_change(self): 18 | """ 19 | A ``GET`` to the ``password_change`` view uses the appropriate 20 | template and populates the password change form into the context. 21 | """ 22 | self.client.login(username='alice', password=passwords[-1]) 23 | response = self.client.get(reverse('password_change')) 24 | self.assertEqual(response.status_code, 200) 25 | self.failUnless(isinstance(response.context['form'], 26 | PasswordPoliciesChangeForm)) 27 | self.assertTemplateUsed(response, 28 | 'registration/password_change_form.html') 29 | self.client.logout() 30 | 31 | def test_password_change_failure(self): 32 | """ 33 | A ``POST`` to the ``password_change`` view with invalid data properly 34 | fails and issues the according error. 35 | """ 36 | data = { 37 | 'old_password': 'password', 38 | 'new_password1': 'Chah+pher9k', 39 | 'new_password2': 'Chah+pher9k', 40 | } 41 | msg = "Your old password was entered incorrectly. Please enter it again." 42 | self.client.login(username='alice', password=passwords[-1]) 43 | response = self.client.post(reverse('password_change'), data=data) 44 | self.assertEqual(response.status_code, 200) 45 | self.failIf(response.context['form'].is_valid()) 46 | self.assertFormError(response, 'form', field='old_password', 47 | errors=msg) 48 | self.client.logout() 49 | 50 | def test_password_change_success(self): 51 | """ 52 | A ``POST`` to the ``change_email_create`` view with valid data properly 53 | changes the user's password, creates a new password history entry 54 | for the user and issues a redirect. 55 | """ 56 | data = {'old_password': passwords[-1], 57 | 'new_password1': 'Chah+pher9k', 58 | 'new_password2': 'Chah+pher9k'} 59 | self.client.login(username='alice', password=data['old_password']) 60 | response = self.client.post(reverse('password_change'), data=data) 61 | self.assertEqual(PasswordHistory.objects.count(), 1) 62 | obj = PasswordHistory.objects.get() 63 | self.assertRedirects(response, 64 | 'http://testserver%s' % reverse('password_change_done')) 65 | obj.delete() 66 | self.client.logout() 67 | -------------------------------------------------------------------------------- /password_policies/tests/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import include, patterns, url 2 | 3 | from password_policies.tests.views import TestHomeView 4 | 5 | 6 | urlpatterns = patterns('', 7 | url(r'^password/', include('password_policies.urls')), 8 | url(r'^$', TestHomeView.as_view(), name='home'), 9 | ) 10 | -------------------------------------------------------------------------------- /password_policies/tests/views.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views.generic.base import View 3 | from django.contrib.auth.decorators import login_required 4 | from django.utils.decorators import method_decorator 5 | 6 | 7 | class TestHomeView(View): 8 | def get(self, request): 9 | return HttpResponse('Home

Welcome!

') 10 | 11 | @method_decorator(login_required) 12 | def dispatch(self, *args, **kwargs): 13 | return super(TestHomeView, self).dispatch(*args, **kwargs) 14 | -------------------------------------------------------------------------------- /password_policies/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, url 2 | 3 | from password_policies.views import PasswordChangeFormView 4 | from password_policies.views import PasswordChangeDoneView 5 | from password_policies.views import PasswordResetCompleteView 6 | from password_policies.views import PasswordResetConfirmView 7 | from password_policies.views import PasswordResetFormView 8 | from password_policies.views import PasswordResetDoneView 9 | 10 | 11 | urlpatterns = patterns('', 12 | url(r'^change/done/$', 13 | PasswordChangeDoneView.as_view(), 14 | name="password_change_done"), 15 | url(r'^change/$', 16 | PasswordChangeFormView.as_view(), 17 | name="password_change"), 18 | url(r'^reset/$', 19 | PasswordResetFormView.as_view(), 20 | name="password_reset"), 21 | url(r'^reset/complete/$', 22 | PasswordResetCompleteView.as_view(), 23 | name="password_reset_complete"), 24 | url(r'^reset/confirm/([0-9A-Za-z_\-]+)/([0-9A-Za-z]{1,13})/([0-9A-Za-z-=_]{1,32})/$', 25 | PasswordResetConfirmView.as_view(), 26 | name="password_reset_confirm"), 27 | url(r'^reset/done/$', 28 | PasswordResetDoneView.as_view(), 29 | name="password_reset_done"), 30 | ) 31 | -------------------------------------------------------------------------------- /password_policies/utils.py: -------------------------------------------------------------------------------- 1 | from datetime import timedelta 2 | 3 | from django.utils import timezone 4 | from django.core.exceptions import ObjectDoesNotExist 5 | 6 | from password_policies.conf import settings 7 | from password_policies.models import PasswordHistory 8 | 9 | 10 | class PasswordCheck(object): 11 | "Checks if a given user needs to change his/her password." 12 | 13 | def __init__(self, user): 14 | self.user = user 15 | self.expiry_datetime = self.get_expiry_datetime() 16 | 17 | def is_required(self): 18 | """Checks if a given user is forced to change his/her password. 19 | 20 | If an instance of :class:`~password_policies.models.PasswordChangeRequired` 21 | exists the verification is successful. 22 | 23 | :returns: ``True`` if the user needs to change his/her password, 24 | ``False`` otherwise. 25 | :rtype: bool 26 | """ 27 | try: 28 | if self.user.password_change_required: 29 | return True 30 | except ObjectDoesNotExist: 31 | pass 32 | return False 33 | 34 | def is_expired(self): 35 | """Checks if a given user's password has expired. 36 | 37 | :returns: ``True`` if the user's password has expired, 38 | ``False`` otherwise. 39 | :rtype: bool 40 | """ 41 | if PasswordHistory.objects.change_required(self.user): 42 | return True 43 | return False 44 | 45 | def get_expiry_datetime(self): 46 | "Returns the date and time when the user's password has expired." 47 | seconds = settings.PASSWORD_DURATION_SECONDS 48 | return timezone.now() - timedelta(seconds=seconds) 49 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | django>=1.7,<1.10 2 | django-easysettings>=1.0 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | 4 | install_requires = ['django>=1.7', 'django-easysettings'] 5 | 6 | setup( 7 | name='django-password-policies', 8 | version=__import__('password_policies').__version__, 9 | description='A Django application to implent password policies.', 10 | long_description="""\ 11 | django-password-policies is an application for the Django framework that 12 | provides unicode-aware password policies on password changes and resets 13 | and a mechanism to force password changes. 14 | """, 15 | author='Tarak Blah', 16 | author_email='halbkarat@gmail.com', 17 | url='https://github.com/tarak/django-password-policies', 18 | include_package_data=True, 19 | packages=find_packages(), 20 | zip_safe=False, 21 | classifiers=[ 22 | 'Development Status :: 3 - Alpha', 23 | 'Environment :: Web Environment', 24 | 'Intended Audience :: Developers', 25 | 'Operating System :: OS Independent', 26 | 'Programming Language :: Python', 27 | 'Programming Language :: Python :: 2', 28 | 'Programming Language :: Python :: 2.7', 29 | 'Programming Language :: Python :: 3', 30 | 'Programming Language :: Python :: 3.3', 31 | 'Programming Language :: Python :: 3.4', 32 | 'Framework :: Django', 33 | 'License :: OSI Approved :: BSD License', 34 | 'Topic :: Software Development :: Libraries :: Python Modules', 35 | 'Topic :: Utilities' 36 | ], 37 | install_requires=install_requires, 38 | test_suite='tests.runtests', 39 | ) 40 | -------------------------------------------------------------------------------- /tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | 6 | import django 7 | from django.conf import settings 8 | from django.test.utils import get_runner 9 | 10 | 11 | def runtests(*test_args): 12 | os.environ['DJANGO_SETTINGS_MODULE'] = 'password_policies.tests.test_settings' 13 | django.setup() 14 | TestRunner = get_runner(settings) 15 | test_runner = TestRunner() 16 | failures = test_runner.run_tests(["password_policies.tests"]) 17 | sys.exit(bool(failures)) 18 | 19 | 20 | if __name__ == '__main__': 21 | runtests(*sys.argv[1:]) 22 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = 3 | py27-django17, 4 | py27-django18, 5 | py27-django19, 6 | py33-django17, 7 | py33-django18, 8 | py34-django17, 9 | py34-django18, 10 | py34-django19, 11 | py35-django18, 12 | py35-django19, 13 | [testenv] 14 | deps = 15 | django17: Django >= 1.7, < 1.8 16 | django18: Django >= 1.8, < 1.9 17 | django19: Django >= 1.9, < 1.10 18 | commands = python setup.py test 19 | --------------------------------------------------------------------------------