pax_global_header00006660000000000000000000000064147756766060014542gustar00rootroot0000000000000052 comment=65bc14febdd7c7b4ea3324278a5db0fa932ec15b django-phonenumber-field-8.1.0/000077500000000000000000000000001477567660600164135ustar00rootroot00000000000000django-phonenumber-field-8.1.0/.github/000077500000000000000000000000001477567660600177535ustar00rootroot00000000000000django-phonenumber-field-8.1.0/.github/CONTRIBUTING.md000066400000000000000000000015201477567660600222020ustar00rootroot00000000000000# Contributing 🙌 First off, thanks for taking the time to contribute! 🙌 If you'd like to contribute, the best approach is to send a well-formed pull request: - [ ] tested - [ ] including documentation [Pull requests](https://docs.github.com/en/pull-requests) should be focused: trying to do more than one thing in a single request will make it more difficult to process. If you have a bug or feature request you can try [logging an issue](/issues). There's no harm in creating an issue and then submitting a pull request to resolve it. This can be a good way to start a conversation and can serve as an anchor point. ## Development To run the full test suite in a range of environments, run [tox](https://tox.wiki/) from the root of the project. This includes some static analysis to detect potential runtime errors and style issues. django-phonenumber-field-8.1.0/.github/dependabot.yml000066400000000000000000000001661477567660600226060ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" django-phonenumber-field-8.1.0/.github/workflows/000077500000000000000000000000001477567660600220105ustar00rootroot00000000000000django-phonenumber-field-8.1.0/.github/workflows/check.yml000066400000000000000000000011311477567660600236040ustar00rootroot00000000000000name: Check on: - push - pull_request jobs: build: name: ${{ matrix.tox-environment }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: tox-environment: - doctest - mypy - ruff env: TOXENV: ${{ matrix.tox-environment }} steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.x" cache: pip - name: Install dependencies run: python -m pip install tox - name: Run run: tox django-phonenumber-field-8.1.0/.github/workflows/release.yml000066400000000000000000000025771477567660600241660ustar00rootroot00000000000000name: Upload release to PyPI on: release: types: [published] jobs: build: name: Build distribution files runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.x" cache: pip - name: Install dependencies run: pip install --user build django setuptools twine wheel - name: Install gettext run: sudo apt-get install gettext - name: Compile messages run: django-admin compilemessages working-directory: phonenumber_field - name: Build package run: python -m build - name: Verify package run: twine check --strict dist/* - name: Upload distributions to GitHub uses: actions/upload-artifact@v4 with: name: dist path: dist/ if-no-files-found: error release: name: Send distribution files to PyPI needs: build runs-on: ubuntu-latest environment: name: pypi-release url: https://pypi.org/p/django-phonenumber-field permissions: id-token: write steps: - name: Download distributions uses: actions/download-artifact@v4 with: name: dist path: dist/ - name: Publish distribution to PyPI uses: pypa/gh-action-pypi-publish@release/v1 django-phonenumber-field-8.1.0/.github/workflows/test.yml000066400000000000000000000032151477567660600235130ustar00rootroot00000000000000name: Test on: - push - pull_request jobs: test: name: Python ${{ matrix.python-version }} / ${{ matrix.tox-environment }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: python-version: - '3.9' - '3.10' - '3.11' - '3.12' - '3.13' - '3.14-dev' env: COVERALLS_FLAG_NAME: Python ${{ matrix.python-version }} / ${{ matrix.tox-environment }} COVERALLS_PARALLEL: true COVERALLS_SERVICE_NAME: github GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} TOXENV: ${{ matrix.tox-environment }} steps: - name: Install gettext run: | sudo apt-get update sudo apt-get install -y gettext - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: pip - name: Install dependencies run: python -m pip install coveralls tox-gh - name: Run tests run: tox - name: Upload coverage data to coveralls.io run: coveralls coveralls: name: Indicate completion to coveralls.io runs-on: ubuntu-latest needs: test # Push coverage report even if test cases failed if: ${{ always() }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 - name: Install coveralls run: python -m pip install coveralls - name: Report coverage to coveralls.io run: coveralls --finish django-phonenumber-field-8.1.0/.gitignore000066400000000000000000000012531477567660600204040ustar00rootroot00000000000000*.pyc *.pyo .installed.cfg .tox bin develop-eggs dist downloads eggs parts build *.egg-info *.egg .DS_Store .project .pydevproject .settings .idea *~ docs/_build tests/.installed.cfg tests/.buildoutsig tests/bin tests/develop-eggs tests/downloads tests/eggs tests/parts tests/personal*.cfg tests/project/personal*.py tests/reports/ distribute* lib/ include/ tests/tmp/ *.coverage /coverage-reports htmlcov/ share/ .coverage* # Written by setuptools_scm. phonenumber_field/version.py # Generated automatically during the release process phonenumber_field/locale/*/LC_MESSAGES/django.mo # python virtualenv .venv/ venv/ # python virtualenv or environment file (potential secrets) .env django-phonenumber-field-8.1.0/.readthedocs.yaml000066400000000000000000000004521477567660600216430ustar00rootroot00000000000000# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details version: 2 build: os: ubuntu-24.04 tools: python: "3.13" python: install: - requirements: docs/requirements.txt - method: pip path: . sphinx: configuration: docs/conf.py fail_on_warning: yes django-phonenumber-field-8.1.0/AUTHORS000066400000000000000000000062231477567660600174660ustar00rootroot00000000000000ackepenek Alan Andre Leitao Andrew Pinkham Andrzej Mateja Andy Kish Ari Todtfeld Arnak Melikyan ArsyiAziz Basil Dubyk Ben Konrath Björn Andersson Craig Loftus Cristi Vîjdea cuchac David Cormier Dmitriy Kalinin Elena Rogleva Emin Mastizada Fábio Thomaz Folkert Francesco Facconi François Freitag g89250741413 Giacomo Graziosi Greg Kaleka Gregory Favre grigna Hugo Osvaldo Barrera hwkns Illya ILUXONCHIK Jacob Rief Jeff Bowen jendas1 Joao S. López John Vandenberg Jonas Lidén Jonathan Stoppani Jon Dufresne Jose Flores kedrrr <52245626+kedrrr@users.noreply.github.com> Kevin Brown Kevin Michel Konstantin Pavlovsky Kristian Klette lampslave László Károlyi Logan Gunthorpe Luci Furtun Ludovic Gasc Luis Rodrigues Maik Hoepfel Mariusz Felisiak Matthew Wilkes Meir Misha Kalyna Mitar Murad nferrari Nicolas Appriou Nikita Kolesnikov Omer Katz Paolo Melchiorre Philippe O. Wagner punkyoon Ramiel Rami Jarrar René Tronsgaard Rasmussen Roman Tolkachyov roybi Saugat Pachhai Sergio Garro Skia Stefan Foulis Stéphane Raimbault Steven Mapes Stu Cox tanvir hasan themarcq Thijs Triemstra Tim Schneider Tim Tisdall Tomas Dobrovolny TonyxDz Tyler Redzko Ville Skyttä Vitaly Babiy Wentao Han django-phonenumber-field-8.1.0/CHANGELOG.rst000066400000000000000000000146311477567660600204410ustar00rootroot00000000000000CHANGELOG ========= **Note:** Releases are now tracked using `GitHub releases `__. This document remains for historical purposes. 6.1.0 (2022-01-12) ------------------ * Make ``formfields.PhoneNumberField`` honor ``PHONENUMBER_DEFAULT_REGION`` * Use ``PHONENUMBER_DEFAULT_REGION`` for example phone number in form field errors. * Add support for Django 4.0 * Add Persian (farsi) translations. * Update uk_AR translations **Backwards incompatible changes** * Drop support for Python 3.6 6.0.0 (2021-10-20) ------------------ * Add support for Python 3.10 * Update Czech, Dutch and pt_BR translations **Backwards incompatible changes** * ``formfields.PhoneNumberField`` with a ``region`` now display national phone numbers in the national format instead of ``PHONENUMBER_DEFAULT_FORMAT``. International numbers are displayed in the ``PHONENUMBER_DEFAULT_FORMAT``. 5.2.0 (2021-05-31) ------------------ * Lazy load ``formfields.PhoneNumberField`` translation for ``invalid`` data. * Update Russian translations **Backwards incompatible changes** * Drop support for end-of-life Django 3.0 5.1.0 (2021-04-02) ------------------ * Allow sorting ``PhoneNumber``\ s from Python * Add support for Python 3.9 and Django 3.2 * Add Argentinian, Bulgarian, Indonesian, Ukrainian translations * Update Esperanto and European Spanish translations **Backwards incompatible changes** * Drop support for Python 3.5 5.0.0 (2020-08-17) ------------------ * Add support for Django 3.1. * Fix rendering ``PhonePrefixSelect`` with ``initial`` passed to the constructor. * The Babel dependency is now optional. * Switched to setuptools declarative configuration for packaging and installation. * Add Arabic and Russian translation. * Correct License information in package metadata. **Backwards incompatible changes** * Drop support for end-of-life Django 1.11 and 2.1. * As the Babel dependency is now optional, you must now install it to use ``PhoneNumberPrefixWidget``. If you do not install it, an ``ImproperlyConfigured`` exception will be raised when instantiated. 4.0.0 (2019-12-06) ------------------ The big version bump is due to the change in how invalid phone numbers are handled. Starting with ``2.4.0`` we added very aggressive validation, which raised ``ValueError`` for invalid numbers. This caused problems in unexpected places (like when filtering a queryset). Starting with ``4.0.0`` we acknowledge that we can not completely prevent invalid numbers from entering the system. Changes directly to the database, validation changes in the upstream phonenumbers library, changes in the django settings may all lead to invalid numbers in the database. Now it is possible to save an invalid number to the database and ``__str__`` and ``__repr__`` clearly indicate invalid numbers. * Don’t raise ``ValueError`` on invalid phone numbers - ``__str__`` and ``__repr__`` updated to report invalid phone numbers correctly if detected. * Various translation updates 3.0.1 (2019-05-28) ------------------ * Allow overriding the default invalid phone number message. 3.0.0 (2019-05-28) ------------------ * Update French and Hebrew translations. * Add a valid phone number example to invalid phone number error messages. **Backwards incompatible changes** * Drop support for Django 2.0. * Drop support for Python 2.7 and 3.4. 2.4.0 (2019-05-06) ------------------ * A ``PhoneNumberField`` can now be deferred with ``QuerySet.defer()``. * Saving or filtering by an invalid phone number will now raise a ``ValueError``. * The model field attribute ``PhoneNumberField.region`` now uses ``PHONENUMBER_DEFAULT_REGION`` if not specified. 2.3.1 (2019-03-26) ------------------ * Fixed a regression to re-allow the model field to override the default form field. 2.3.0 (2019-03-26) ------------------ * Added the ``region`` keyword argument to ``PhoneNumberField``. * Fix representation of invalid phone numbers in the database, previously stored as ``+NoneNone``. Now, invalid phone numbers are represented as: 1. the field's `default`_ when it is specified, or 2. empty ``str`` if the field is `blank`_ and not `null`_, or 3. null. Existing database records can be upgraded with a `data migration`_. * Added support for Django 2.2. * Tests are now included in the sdist package. * ``modelfields.PhoneNumberField`` now inherits from ``models.CharField`` instead of ``models.Field``. .. _default: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.Field.default .. _blank: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.Field.blank .. _null: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.Field.null .. _data migration: https://docs.djangoproject.com/en/dev/topics/migrations/#data-migrations 2.2.0 (2019-01-27) ------------------ * Added support for ``null=True`` 2.1.0 (2018-10-28) ------------------ * Removed hardcoded dependency to phonenumbers library. Now developers have to manually install either phonenumbers or phonenumberslite. * Added Romanian locale * Added Bangla locale * Update French locale * Update Italian locale 2.0.1 (2018-08-19) ------------------ * Statically depend on phonenumbers Previously the phonenumberslight dependency was used dynamically in setup.py if it already was installed, causing problems with building wheels and with pipenv. * Added Ukrainian locale * Added Simplified Chinese locale 2.0.0 (2018-01-04) ------------------ * Add Django 2.0 support * Drop Support for Django<1.11 * Translations: Swedish 1.3.0 (2017-04-15) ------------------ * Add rest_framework Serializer * Hashable phonenumber object * Various bugfixes and improvements 1.2.0 (2017-03-17) ------------------ * Django 1.10 support * Bugfixes and cleanup * Translations: Brazilian Portuguese, Spanish, Norwegian, Dutch, Azerbaijani, Turkish and French 1.1.0 (2016-03-30) ------------------ * Django 1.9 support * README updated and links fixed * support for HTML5.0 tel input type added * locale files are now included * new translations: Danish, Esperanto, Polish, all translations reformatted, Russian translation expanded * PhoneNumberField.get_prep_value changed to enable setting ``null=True`` * new widget added: ``PhoneNumberInternationalFallbackWidget`` * new backward compatible requirement phonenumberslite instead of phonenumbers * lots of tests * dropped support for ``PHONENUMER_DEFAULT_REGION`` setting with typo django-phonenumber-field-8.1.0/LICENSE000066400000000000000000000020651477567660600174230ustar00rootroot00000000000000Copyright (c) 2011 Stefan Foulis and contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.django-phonenumber-field-8.1.0/MANIFEST.in000066400000000000000000000001321477567660600201450ustar00rootroot00000000000000exclude .gitignore prune .github include phonenumber_field/locale/*/LC_MESSAGES/django.mo django-phonenumber-field-8.1.0/README.rst000066400000000000000000000022061477567660600201020ustar00rootroot00000000000000======================== django-phonenumber-field ======================== .. image:: https://github.com/stefanfoulis/django-phonenumber-field/workflows/Test/badge.svg :target: https://github.com/stefanfoulis/django-phonenumber-field/workflows/Test/badge.svg .. image:: https://img.shields.io/coveralls/stefanfoulis/django-phonenumber-field/develop.svg :target: https://coveralls.io/github/stefanfoulis/django-phonenumber-field?branch=main A Django library which interfaces with `python-phonenumbers`_ to validate, pretty print and convert phone numbers. ``python-phonenumbers`` is a port of Google's `libphonenumber`_ library, which powers Android's phone number handling. .. _`python-phonenumbers`: https://github.com/daviddrysdale/python-phonenumbers .. _`libphonenumber`: https://github.com/google/libphonenumber Documentation ============= https://django-phonenumber-field.readthedocs.io/ Running tests ============= tox needs to be installed. To run the whole test matrix with the locally available Python interpreters and generate a combined coverage report:: tox run a specific combination:: tox -e py310-djmain,py39-djmain django-phonenumber-field-8.1.0/docs/000077500000000000000000000000001477567660600173435ustar00rootroot00000000000000django-phonenumber-field-8.1.0/docs/Makefile000066400000000000000000000011721477567660600210040ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) django-phonenumber-field-8.1.0/docs/conf.py000066400000000000000000000031521477567660600206430ustar00rootroot00000000000000# Configuration file for the Sphinx documentation builder. # # For the full list of built-in configuration values, see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html import os import pathlib import sys current_dir = pathlib.Path(__file__).parent # Find current settings module for doctests. sys.path.insert(0, str(current_dir)) sys.path.insert(0, str(current_dir / "ext")) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information project = "django-phonenumber-field" copyright = "2022, django-phonenumber-field" author = "Stefan Foulis" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration extensions = [ "sphinx.ext.autodoc", "sphinx.ext.doctest", "sphinx.ext.intersphinx", "phonenumber_field_docs", ] templates_path = ["_templates"] exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_theme = "sphinx_rtd_theme" html_static_path = [] # -- Options for extensions -------------------------------------------------- intersphinx_mapping = { "django": ( "https://docs.djangoproject.com/en/dev/", "https://docs.djangoproject.com/en/dev/_objects/", ), "python": ("https://docs.python.org/3/", None), } django-phonenumber-field-8.1.0/docs/ext/000077500000000000000000000000001477567660600201435ustar00rootroot00000000000000django-phonenumber-field-8.1.0/docs/ext/phonenumber_field_docs.py000066400000000000000000000002101477567660600252030ustar00rootroot00000000000000def setup(app): app.add_crossref_type( directivename="setting", rolename="setting", indextemplate="pair: %s; setting" ) django-phonenumber-field-8.1.0/docs/index.rst000066400000000000000000000024521477567660600212070ustar00rootroot00000000000000🕿 django-phonenumber-field 🕿 ============================= A `Django `_ library which interfaces with `python-phonenumbers `_ to validate, pretty print and convert phone numbers. The python-phonenumbers library is a port of Google’s `libphonenumber `_ library, which powers Android’s phone number handling. Installation ============ Choosing a phonenumbers provider -------------------------------- The `python-phonenumbers `_ library comes in `two flavors `_: .. code-block:: # Installs phonenumbers minimal metadata pip install "django-phonenumber-field[phonenumberslite]" .. code-block:: # Installs phonenumbers extended features (e.g. geocoding) pip install "django-phonenumber-field[phonenumbers]" Setup ----- Add ``phonenumber_field`` to the list of the installed apps in your ``settings.py`` file :external+django:setting:`INSTALLED_APPS`: .. code-block:: python INSTALLED_APPS = [ # Other apps… "phonenumber_field", ] .. toctree:: :maxdepth: 2 :caption: Contents: phonenumbers reference django-phonenumber-field-8.1.0/docs/make.bat000066400000000000000000000014401477567660600207470ustar00rootroot00000000000000@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=. set BUILDDIR=_build %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.https://www.sphinx-doc.org/ exit /b 1 ) if "%1" == "" goto help %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% :end popd django-phonenumber-field-8.1.0/docs/phonenumbers.rst000066400000000000000000000030631477567660600226040ustar00rootroot00000000000000Handling phone numbers ====================== `Google’s libphonenumber “Falsehoods Programmers Believe About Phone Numbers” `_ are worth keeping in mind, especially since this library relies heavily on `libphonenumber `_. About phone numbers extensions ------------------------------ An extension is an additional phone line added to an existing phone system, making it possible to reach a specific employee or department within an organization. An extension is defined in the following manner: .. doctest:: extensions >>> import phonenumbers >>> phonenumbers.parse("+1 604-401-1234 ext. 987") PhoneNumber(country_code=1, national_number=6044011234, extension='987', italian_leading_zero=None, number_of_leading_zeros=None, country_code_source=0, preferred_domestic_carrier_code=None) >>> phonenumbers.parse("+1 604-401-1234,987") PhoneNumber(country_code=1, national_number=6044011234, extension='987', italian_leading_zero=None, number_of_leading_zeros=None, country_code_source=0, preferred_domestic_carrier_code=None) The library primarily focuses on public phone numbers, its default format and database representation are using `E.164 `_, which has no support for extensions. Projects that need to handle phone number extensions must set **both** :setting:`PHONENUMBER_DEFAULT_FORMAT` and :setting:`PHONENUMBER_DB_FORMAT` to an extension-compatible format, as described in :ref:`settings-format-choices`. django-phonenumber-field-8.1.0/docs/reference.rst000066400000000000000000000410741477567660600220410ustar00rootroot00000000000000.. testsetup:: * import django from bs4 import BeautifulSoup django.setup() def print_html(html): print(BeautifulSoup(html).prettify().strip()) def print_html_compact(html): output = BeautifulSoup(html).prettify().strip().splitlines() print("\n".join(output[:15])) print(" ...") print("\n".join(output[-7:])) The PhoneNumber wrapper ======================= .. autoclass:: phonenumber_field.phonenumber.PhoneNumber() .. automethod:: phonenumber_field.phonenumber.PhoneNumber.from_string .. automethod:: phonenumber_field.phonenumber.PhoneNumber.is_valid .. autoproperty:: phonenumber_field.phonenumber.PhoneNumber.as_international .. autoproperty:: phonenumber_field.phonenumber.PhoneNumber.as_national .. autoproperty:: phonenumber_field.phonenumber.PhoneNumber.as_e164 .. autoproperty:: phonenumber_field.phonenumber.PhoneNumber.as_rfc3966 Usage ----- .. doctest:: wrapper >>> from phonenumber_field.phonenumber import PhoneNumber >>> number = PhoneNumber.from_string("+16044011234") >>> print(number.as_national) (604) 401-1234 >>> print(number.as_e164) +16044011234 >>> print(number.as_international) +1 604-401-1234 >>> print(number.as_rfc3966) tel:+1-604-401-1234 # Using national numbers with the region keyword argument. >>> canadian_number = "(604) 401 1234" >>> number = PhoneNumber.from_string(canadian_number, region="CA") >>> print(number.as_e164) +16044011234 Model field =========== The :class:`~phonenumber_field.modelfields.PhoneNumberField` :ref:`model field ` allows storing :class:`~phonenumber_field.phonenumber.PhoneNumber`\ s in the database, based on a :class:`~django.db.models.CharField`. The phone number format used by the database is controlled with :setting:`PHONENUMBER_DB_FORMAT`. When no region is specified, a phone number in the ``"NATIONAL"`` format will be assumed to be from the :setting:`PHONENUMBER_DEFAULT_REGION`. - The default :ref:`form field ` for this field is the :class:`~phonenumber_field.formfields.PhoneNumberField`. - The default :ref:`form widget ` for this field is the :class:`~phonenumber_field.widgets.RegionalPhoneNumberWidget`. .. autoclass:: phonenumber_field.modelfields.PhoneNumberField .. automethod:: __init__ Usage ----- .. code-block:: python from django.db import models from phonenumber_field.modelfields import PhoneNumberField class Customer(models.Model): name = models.TextField() # An optional phone number. phone_number = PhoneNumberField(blank=True) Form fields =========== :class:`~phonenumber_field.formfields.PhoneNumberField` ------------------------------------------------------- The :class:`~phonenumber_field.formfields.PhoneNumberField` :ref:`form field ` to validate :class:`~phonenumber_field.phonenumber.PhoneNumber`, based on a :class:`~django.forms.CharField`. - Default widget: :class:`~phonenumber_field.widgets.RegionalPhoneNumberWidget` - Empty value: ``""`` - Normalizes to: A :class:`~phonenumber_field.phonenumber.PhoneNumber` or an empty :class:`str` (``""``) - Uses :func:`~phonenumber_field.validators.validate_international_phonenumber` .. autoclass:: phonenumber_field.formfields.PhoneNumberField .. automethod:: __init__ Usage ~~~~~ .. doctest:: formfield >>> from phonenumber_field.formfields import PhoneNumberField >>> class PhoneForm(django.forms.Form): ... number = PhoneNumberField(region="CA") ... # Manipulating data >>> form = PhoneForm({"number": "+1 604 401 1234"}) >>> form.is_valid() True >>> form.cleaned_data {'number': PhoneNumber(country_code=1, national_number=6044011234, extension=None, italian_leading_zero=None, number_of_leading_zeros=None, country_code_source=1, preferred_domestic_carrier_code=None)} >>> print_html(form.as_div())
# Handling errors >>> form = PhoneForm({"number": "invalid"}) >>> form.is_valid() False >>> print_html(form.as_div())
  • Enter a valid phone number (e.g. (506) 234-5678) or a number with an international call prefix.
.. note:: Because the PhoneNumberField specifies a region, the example number is a national number from that region. When no region is specified, an international example phone number in the E.164 format is suggested. :class:`~phonenumber_field.formfields.SplitPhoneNumberField` ------------------------------------------------------------ A :class:`~django.forms.MultiValueField` that offers: - a ```` to enter the phone number. To customize each field, subclass :class:`~phonenumber_field.formfields.SplitPhoneNumberField` and override: - :func:`~phonenumber_field.formfields.SplitPhoneNumberField.prefix_field` for the phone number prefix field, - :func:`~phonenumber_field.formfields.SplitPhoneNumberField.number_field` for the phone number field. This widget uses an example phone number from the selected region for the ``invalid`` key in :attr:`~django.forms.Field.error_messages`, when the region choice is valid. To customize the dynamic message, use :func:`phonenumber_field.formfields.SplitPhoneNumberField.invalid_error_message`. .. important:: Requires the `Babel `_ package. .. autoclass:: phonenumber_field.formfields.SplitPhoneNumberField .. automethod:: __init__ .. automethod:: prefix_field .. automethod:: number_field .. automethod:: invalid_error_message Usage ~~~~~ Simple ...... .. doctest:: SplitPhoneNumberField.basic >>> from phonenumber_field.formfields import SplitPhoneNumberField >>> class PhoneForm(django.forms.Form): ... number = SplitPhoneNumberField() ... >>> form = PhoneForm() >>> print_html_compact(form.as_div())
Number:
Limiting country choices ........................ .. doctest:: SplitPhoneNumberField.country_choices >>> from phonenumber_field.formfields import SplitPhoneNumberField >>> class DemoSplitPhoneNumberField(SplitPhoneNumberField): ... def prefix_field(self): ... return django.forms.ChoiceField(choices=[ ... ("", "---------"), ... ("CA", "Canada"), ... ("FR", "France"), ... ]) ... >>> class LimitedCountryPhoneForm(django.forms.Form): ... number = DemoSplitPhoneNumberField() ... >>> form = LimitedCountryPhoneForm() >>> print_html(form.as_div())
Number:
Pre-selecting a country ....................... .. doctest:: SplitPhoneNumberField.preselecting_country >>> from phonenumber_field.formfields import SplitPhoneNumberField >>> class DemoSplitPhoneNumberField(SplitPhoneNumberField): ... def prefix_field(self): ... return django.forms.ChoiceField(choices=[ ... ("", "---------"), ... ("CA", "Canada"), ... ("FR", "France"), ... ]) ... >>> class FrenchPhoneForm(django.forms.Form): ... number = DemoSplitPhoneNumberField(region="FR") ... >>> form = FrenchPhoneForm() >>> print_html(form.as_div())
Number:
Customizing widget attrs ........................ .. doctest:: SplitPhoneNumberField.preselecting_country >>> from phonenumber_field.formfields import SplitPhoneNumberField >>> class DemoSplitPhoneNumberField(SplitPhoneNumberField): ... def prefix_field(self): ... return django.forms.ChoiceField(choices=[ ... ("", "---------"), ... ("CA", "Canada"), ... ("FR", "France"), ... ]) ... ... def number_field(self): ... number_field = super().number_field() ... number_field.widget.attrs["class"] = "form-control" ... return number_field ... >>> class BootstrapPhoneForm(django.forms.Form): ... number = DemoSplitPhoneNumberField() ... >>> form = BootstrapPhoneForm() >>> print_html(form.as_div())
Number:
Widgets ------- RegionalPhoneNumberWidget ~~~~~~~~~~~~~~~~~~~~~~~~~ **Default widget** for :class:`~phonenumber_field.formfields.PhoneNumberField`. - input_type: ``tel`` - Renders as ```` .. important:: The region should be specified (either per field using the ``region`` keyword argument, or with the :setting:`PHONENUMBER_DEFAULT_REGION` setting) in order to know which national number format to recognize. .. autoclass:: phonenumber_field.widgets.RegionalPhoneNumberWidget .. automethod:: __init__ Usage ..... .. doctest:: fallbackwidget >>> from phonenumber_field.formfields import PhoneNumberField >>> class CanadianPhoneForm(django.forms.Form): ... # RegionalPhoneNumberWidget is the default widget. ... number = PhoneNumberField(region="CA") ... # Using the national format for the field’s region. >>> form = CanadianPhoneForm({"number": "+16044011234"}) >>> print_html(form.as_div())
# Using E164 for an international number. >>> french_number = "+33612345678" >>> form = CanadianPhoneForm({"number": french_number}) >>> print_html(form.as_div())
PhoneNumberPrefixWidget ~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: phonenumber_field.widgets.PhoneNumberPrefixWidget Serializer field ================ The :class:`~phonenumber_field.serializersfields.PhoneNumberField` `serializer field `_, based on the `CharField `_. The serialization format is controlled by the :setting:`PHONENUMBER_DEFAULT_FORMAT`. .. autoclass:: phonenumber_field.serializerfields.PhoneNumberField .. automethod:: __init__ Usage ----- .. doctest:: serializerfield >>> from django.conf import settings >>> from rest_framework import renderers, serializers >>> from phonenumber_field.serializerfields import PhoneNumberField >>> class PhoneNumberSerializer(serializers.Serializer): ... number = PhoneNumberField(region="CA") ... >>> serializer = PhoneNumberSerializer(data={"number": "604 401 1234"}) >>> serializer.is_valid() True >>> serializer.validated_data {'number': PhoneNumber(country_code=1, national_number=6044011234, extension=None, italian_leading_zero=None, number_of_leading_zeros=None, country_code_source=20, preferred_domestic_carrier_code=None)} # Using the PHONENUMBER_DEFAULT_FORMAT. >>> renderers.JSONRenderer().render(serializer.data) b'{"number":"+16044011234"}' Validator ========= Validates: - a :class:`~phonenumber_field.phonenumber.PhoneNumber` instance, or - an :class:`str` in an international format (with a prefix), or - an :class:`str` that’s a local phone number according to :setting:`PHONENUMBER_DEFAULT_REGION`. .. note:: Not all well-formed phone numbers are valid. The rules to construct phone numbers vary per region of the world. `Falsehoods Programmers Believe About Phone Numbers `_ is a good read. .. autofunction:: phonenumber_field.validators.validate_international_phonenumber **code**: ``"invalid"`` Settings ======== .. _settings-format-choices: Phone number format choices --------------------------- +------------------------+---------------+------------+-----------------------------------------------------------------+ | Setting value | International | Extensions | Notes | +========================+===============+============+=================================================================+ | ``"E164"`` *(default)* | ✓ | ❌ | https://en.wikipedia.org/wiki/E.164 | +------------------------+---------------+------------+-----------------------------------------------------------------+ | ``"INTERNATIONAL"`` | ✓ | ✓ | https://en.wikipedia.org/wiki/E.123#Telephone_number | +------------------------+---------------+------------+-----------------------------------------------------------------+ | ``"RFC3966"`` | ✓ | ✓ | https://www.rfc-editor.org/rfc/rfc3966.html | +------------------------+---------------+------------+-----------------------------------------------------------------+ | ``"NATIONAL"`` | ❌ | ✓ | **DISCOURAGED**, requires :setting:`PHONENUMBER_DEFAULT_REGION` | +------------------------+---------------+------------+-----------------------------------------------------------------+ .. warning:: By default, the library uses `E.164, the international public telecommunication numbering plan `_, which **does not support phone numbers extensions**. Set **both** :setting:`PHONENUMBER_DB_FORMAT` and :setting:`PHONENUMBER_DEFAULT_FORMAT` to an extension-compatible format to handle phone numbers extensions. .. setting:: PHONENUMBER_DB_FORMAT ``PHONENUMBER_DB_FORMAT`` ------------------------- Store phone numbers strings in the specified format in the database. Default: ``"E164"``. See :ref:`settings-format-choices`. .. warning:: **Data loss may occur when changing the DB format.** Phone numbers stored in the database are parsed every time they are loaded from the database. When switching from a format that can represent extensions to a format that cannot, the **extension information is definitely lost**. When using :setting:`PHONENUMBER_DB_FORMAT`\ ``="NATIONAL"``, changing the :setting:`PHONENUMBER_DEFAULT_REGION` will cause phone numbers stored in the database to be interpreted differently, resulting in data corruption. .. setting:: PHONENUMBER_DEFAULT_FORMAT ``PHONENUMBER_DEFAULT_FORMAT`` ------------------------------ String formatting of phone numbers. Default: ``"E164"``. See :ref:`settings-format-choices`. .. setting:: PHONENUMBER_DEFAULT_REGION ``PHONENUMBER_DEFAULT_REGION`` ------------------------------ `ISO-3166-1 `_ two-letter country code indicating how to interpret regional phone numbers. Default: ``None``. django-phonenumber-field-8.1.0/docs/requirements.txt000066400000000000000000000000751477567660600226310ustar00rootroot00000000000000django djangorestframework phonenumberslite sphinx-rtd-theme django-phonenumber-field-8.1.0/docs/settings.py000066400000000000000000000001171477567660600215540ustar00rootroot00000000000000DATABASES = {} SECRET_KEY = "secretkey" INSTALLED_APPS = ["phonenumber_field"] django-phonenumber-field-8.1.0/phonenumber_field/000077500000000000000000000000001477567660600221005ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/__init__.py000066400000000000000000000002501477567660600242060ustar00rootroot00000000000000try: from .version import version except ImportError: # The version module is written by setuptools_scm. __version__ = None else: __version__ = version django-phonenumber-field-8.1.0/phonenumber_field/formfields.py000066400000000000000000000165121477567660600246110ustar00rootroot00000000000000import phonenumbers from django.conf import settings from django.core import validators from django.core.exceptions import ImproperlyConfigured, ValidationError from django.forms.fields import CharField, ChoiceField, MultiValueField from django.utils import translation from django.utils.text import format_lazy from django.utils.translation import pgettext, pgettext_lazy from phonenumbers import COUNTRY_CODE_TO_REGION_CODE, COUNTRY_CODES_FOR_NON_GEO_REGIONS from phonenumber_field import widgets from phonenumber_field.phonenumber import to_python, validate_region from phonenumber_field.validators import validate_international_phonenumber try: import babel except ModuleNotFoundError: babel = None # type: ignore GEO_COUNTRY_CODE_TO_REGION_CODE = COUNTRY_CODE_TO_REGION_CODE.copy() for country_code in COUNTRY_CODES_FOR_NON_GEO_REGIONS: del GEO_COUNTRY_CODE_TO_REGION_CODE[country_code] # ISO 3166-1 alpha-2 to national prefix REGION_CODE_TO_COUNTRY_CODE = { region_code: country_code for country_code, region_codes in GEO_COUNTRY_CODE_TO_REGION_CODE.items() for region_code in region_codes } class PhoneNumberField(CharField): default_validators = [validate_international_phonenumber] widget = widgets.RegionalPhoneNumberWidget def __init__(self, *args, region=None, widget=None, **kwargs): """ :keyword str region: 2-letter country code as defined in ISO 3166-1. When not supplied, defaults to :setting:`PHONENUMBER_DEFAULT_REGION` :keyword django.forms.Widget widget: defaults to :class:`~phonenumber_field.widgets.RegionalPhoneNumberWidget` """ validate_region(region) self.region = region or getattr(settings, "PHONENUMBER_DEFAULT_REGION", None) if widget is None: try: widget = self.widget(region=self.region) except TypeError: widget = self.widget() super().__init__(*args, widget=widget, **kwargs) self.widget.input_type = "tel" if "invalid" not in self.error_messages: if self.region: number = phonenumbers.example_number(self.region) example_number = to_python(number).as_national error_message = pgettext_lazy( "{example_number} is a national phone number.", "Enter a valid phone number (e.g. {example_number}) " "or a number with an international call prefix.", ) else: example_number = "+12125552368" # Ghostbusters error_message = pgettext_lazy( "{example_number} is an international phone number.", "Enter a valid phone number (e.g. {example_number}).", ) self.error_messages["invalid"] = format_lazy( error_message, example_number=example_number ) def to_python(self, value): if value in validators.EMPTY_VALUES: return self.empty_value return to_python(value, region=self.region) def localized_choices(language): if babel is None: raise ImproperlyConfigured( "The PhonePrefixSelect widget requires the babel package be installed." ) choices = [("", "---------")] locale_name = translation.to_locale(language) locale = babel.Locale(locale_name) for region_code, country_code in REGION_CODE_TO_COUNTRY_CODE.items(): region_name = locale.territories.get(region_code) if region_name: choices.append((region_code, f"{region_name} +{country_code}")) return choices class PrefixChoiceField(ChoiceField): def __init__(self, *, choices=None, **kwargs): if choices is None: language = translation.get_language() or settings.LANGUAGE_CODE choices = localized_choices(language) choices.sort(key=lambda item: item[1]) super().__init__(choices=choices, **kwargs) class SplitPhoneNumberField(MultiValueField): default_validators = [validate_international_phonenumber] widget = widgets.PhoneNumberPrefixWidget def __init__(self, *, initial=None, region=None, widget=None, **kwargs): """ :keyword list initial: A two-elements iterable: #. the region code, an :class:`str`, the 2-letter country code as defined in ISO 3166-1. #. the phone number, an :class:`str` When ``initial`` is not provided, the ``region`` keyword argument is used as the initial for the region field if specified, otherwise :setting:`PHONENUMBER_DEFAULT_REGION` is used. See :attr:`django.forms.Field.initial`. :keyword str region: 2-letter country code as defined in ISO 3166-1. When not supplied, defaults to :setting:`PHONENUMBER_DEFAULT_REGION` :keyword ~django.forms.MultiWidget widget: defaults to :class:`~phonenumber_field.widgets.PhoneNumberPrefixWidget` """ validate_region(region) region = region or getattr(settings, "PHONENUMBER_DEFAULT_REGION", None) if initial is None and region: initial = [region, None] prefix_field = self.prefix_field() number_field = self.number_field() fields = (prefix_field, number_field) if widget is None: widget = self.widget((prefix_field.widget, number_field.widget)) super().__init__(fields, initial=initial, widget=widget, **kwargs) def prefix_field(self): """ Returns the default :class:`~django.forms.Field` for the phone number prefix field. Use this hook to set widget attributes or update the field definition. """ return PrefixChoiceField() def number_field(self): """ Returns the default :class:`~django.forms.Field` for the phone number field. Use this hook to set widget attributes or update the field definition. """ number_field = CharField() number_field.widget.input_type = "tel" return number_field def invalid_error_message(self): """ Hook to customize ``error_messages["invalid"]`` for a given region. Include the example number in the message with the ``{example_number}`` placeholder. """ return pgettext( "{example_number} is a national phone number.", "Enter a valid phone number (e.g. {example_number}).", ) def compress(self, data_list): if not data_list: return data_list region, national_number = data_list return to_python(national_number, region=region) def clean(self, value): if not self.disabled: prefix_field = self.fields[0] try: region = prefix_field.clean(value[0]) except ValidationError: pass # The parent class handles validation. else: if region: number = phonenumbers.example_number(region) example_number = to_python(number).as_national error_message = self.invalid_error_message() self.error_messages["invalid"] = format_lazy( error_message, example_number=example_number, ) return super().clean(value) django-phonenumber-field-8.1.0/phonenumber_field/locale/000077500000000000000000000000001477567660600233375ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/ar/000077500000000000000000000000001477567660600237415ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/ar/LC_MESSAGES/000077500000000000000000000000001477567660600255265ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/ar/LC_MESSAGES/django.po000066400000000000000000000041751477567660600273370ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # FULL NAME , 2020. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2020-03-23 15:41+0100\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" "X-Generator: Gtranslator 2.91.7\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "أدخل رقم هاتف صالح (مثال {example_number} ) أو رقم له بادئة دولية " #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "أدخل رقم هاتف صالح (مثال {example_number} )." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "أدخل رقم هاتف صالح (مثال {example_number} )." #: modelfields.py:53 msgid "Phone number" msgstr "رقم الهاتف" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "أدخل رقم هاتف صالح" #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "رقم الهاتف الذي تم إدخاله غير صالح." django-phonenumber-field-8.1.0/phonenumber_field/locale/az/000077500000000000000000000000001477567660600237515ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/az/LC_MESSAGES/000077500000000000000000000000001477567660600255365ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/az/LC_MESSAGES/django.po000066400000000000000000000033551477567660600273460ustar00rootroot00000000000000# Azerbaijani Locale. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Emin Mastizada , 2016. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Emin Mastizada \n" "Language-Team: Azerbaijani \n" "Language: az\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "Düzgün telefon nömrəsi daxil edin." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Düzgün telefon nömrəsi daxil edin." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Düzgün telefon nömrəsi daxil edin." #: modelfields.py:53 msgid "Phone number" msgstr "Telefon nömrəsi" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Düzgün telefon nömrəsi daxil edin." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Daxil etdiyiniz telefon nömrəsi səhvdir." django-phonenumber-field-8.1.0/phonenumber_field/locale/bg/000077500000000000000000000000001477567660600237275ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/bg/LC_MESSAGES/000077500000000000000000000000001477567660600255145ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/bg/LC_MESSAGES/django.po000066400000000000000000000043001477567660600273130ustar00rootroot00000000000000# Bulgarian translations # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Elena Rogleva , 2020. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2020-11-12 13:04+0200\n" "Last-Translator: ELENA ROGLEVA \n" "Language-Team: \n" "Language: bg\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Моля, въведете валиден телефонен номер (например {example_number}) или номер " "с международен телефонен код." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Моля, въведете валиден телефонен номер (например {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Моля, въведете валиден телефонен номер (например {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Телефонен номер" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Моля, въведете валиден телефонен номер." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Въведеният телефонен номер е невалиден." django-phonenumber-field-8.1.0/phonenumber_field/locale/bn/000077500000000000000000000000001477567660600237365ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/bn/LC_MESSAGES/000077500000000000000000000000001477567660600255235ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/bn/LC_MESSAGES/django.po000066400000000000000000000035741477567660600273360ustar00rootroot00000000000000# Bangali Locale. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Tanvir Hasan , 2016. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Tanvir Hasan \n" "Language-Team: \n" "Language: bn\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "একটি বৈধ ফোন নম্বর লিখুন।" #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "একটি বৈধ ফোন নম্বর লিখুন।" #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "একটি বৈধ ফোন নম্বর লিখুন।" #: modelfields.py:53 msgid "Phone number" msgstr "ফোন নাম্বার" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "একটি বৈধ ফোন নম্বর লিখুন।" #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "প্রদত্ত ফোন নাম্বারটি বৈধ নয়।" django-phonenumber-field-8.1.0/phonenumber_field/locale/cs/000077500000000000000000000000001477567660600237445ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/cs/LC_MESSAGES/000077500000000000000000000000001477567660600255315ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/cs/LC_MESSAGES/django.po000066400000000000000000000034371477567660600273420ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: django-phonenumber-field 5.2.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2021-07-28 21:06+0200\n" "Last-Translator: melanger\n" "Language-Team: Melanger.cz\n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Vložte platné telefonní číslo (např. {example_number}) nebo číslo s " "mezinárodní předvolbou." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Vložte platné telefonní číslo (např. {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Vložte platné telefonní číslo (např. {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Telefonní číslo" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Vložte platné telefonní číslo." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Zadané telefonní číslo není platné." django-phonenumber-field-8.1.0/phonenumber_field/locale/da/000077500000000000000000000000001477567660600237235ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/da/LC_MESSAGES/000077500000000000000000000000001477567660600255105ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/da/LC_MESSAGES/django.po000066400000000000000000000032501477567660600273120ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # René Tronsgaard , 2016. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2016-03-14 12:50+0100\n" "Last-Translator: René Tronsgaard \n" "Language-Team: \n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.5.4\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "Indtast et gyldigt telefonnummer." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Indtast et gyldigt telefonnummer." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Indtast et gyldigt telefonnummer." #: modelfields.py:53 msgid "Phone number" msgstr "Telefonnummer" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Indtast et gyldigt telefonnummer." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Det indtastede telefonnummer er ugyldigt." django-phonenumber-field-8.1.0/phonenumber_field/locale/de/000077500000000000000000000000001477567660600237275ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/de/LC_MESSAGES/000077500000000000000000000000001477567660600255145ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/de/LC_MESSAGES/django.po000066400000000000000000000037651477567660600273310ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Bitte eine gültige Telefonnummer (z. B. {example_number}) oder eine gültige " "Nummer mit internationaler Vorwahl eingeben." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Bitte eine gültige Telefonnummer (z. B. {example_number}) eingeben." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Bitte eine gültige Telefonnummer (z. B. {example_number}) eingeben." #: modelfields.py:53 msgid "Phone number" msgstr "Telefonnummer" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Bitte eine gültige Telefonnummer eingeben." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Die eingegebene Telefonnummer ist ungültig." django-phonenumber-field-8.1.0/phonenumber_field/locale/eo/000077500000000000000000000000001477567660600237425ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/eo/LC_MESSAGES/000077500000000000000000000000001477567660600255275ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/eo/LC_MESSAGES/django.po000066400000000000000000000034121477567660600273310ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2021-03-11 16:09+0000\n" "Last-Translator: Meiyer \n" "Language-Team: Esperanto\n" "Language: eo\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Bv. enigu ĝustan lokan telefon-numeron (ekz. {example_number}) aŭ numeron " "kun internacia voko-prefikso." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Bv. enigu ĝustan telefon-numeron (ekz. {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Bv. enigu ĝustan telefon-numeron (ekz. {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Telefona numero" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Bv. enigu ĝustan telefon-numeron." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "La provizita numero ne estas en akceptebla formato." django-phonenumber-field-8.1.0/phonenumber_field/locale/es/000077500000000000000000000000001477567660600237465ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/es/LC_MESSAGES/000077500000000000000000000000001477567660600255335ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/es/LC_MESSAGES/django.po000066400000000000000000000037371477567660600273470ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2020-09-30 18:32+0200\n" "Last-Translator: Joao Lopez \n" "Language-Team: \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Ingrese un número de teléfono válido (ej.: {example_number}) o un número " "con un prefijo de llamado internacional." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Ingrese un número de teléfono válido (ej.: {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Ingrese un número de teléfono válido (ej.: {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Número de teléfono" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Ingrese un número de teléfono válido." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "El número de teléfono ingresado no es válido." django-phonenumber-field-8.1.0/phonenumber_field/locale/es_AR/000077500000000000000000000000001477567660600243305ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/es_AR/LC_MESSAGES/000077500000000000000000000000001477567660600261155ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/es_AR/LC_MESSAGES/django.po000066400000000000000000000037351477567660600277270ustar00rootroot00000000000000# Argentinian Spanish translations for django-phonenumber-field # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the django-phonenumber-field package. # Hugo Osvaldo Barrera , 2020. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" "Language: es_AR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Ingresá un número de teléfono válido (ej.: {example_number}) o un número con " "un prefijo internacional." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Ingresá un número de teléfono válido (ej.: {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Ingresá un número de teléfono válido (ej.: {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Número de teléfono" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Ingresá un número de teléfono válido." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "El número de teléfono ingresado es inválido." django-phonenumber-field-8.1.0/phonenumber_field/locale/fa/000077500000000000000000000000001477567660600237255ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/fa/LC_MESSAGES/000077500000000000000000000000001477567660600255125ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/fa/LC_MESSAGES/django.po000066400000000000000000000040401477567660600273120ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR mahmoodh1378@gmail.com, 2021. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2021-12-10 14:27+0330\n" "Last-Translator: Mahmood Heidari mahmoodh1378@gmail.com\n" "Language-Team: \n" "Language: fa\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "یک شماره تماس معتبر (مانند {example_number}) یا یک شماره با پیشوند کشور مورد " "نظر وارد نمایید." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "یک شماره تماس معتبر وارد نمایید (مانند {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "یک شماره تماس معتبر وارد نمایید (مانند {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "شماره تماس" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "یک شماره تماس معتبر وارد نمایید." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "شماره تماس وارد شده معتبر نیست." django-phonenumber-field-8.1.0/phonenumber_field/locale/fi/000077500000000000000000000000001477567660600237355ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/fi/LC_MESSAGES/000077500000000000000000000000001477567660600255225ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/fi/LC_MESSAGES/django.po000066400000000000000000000032131477567660600273230ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Ville Skyttä , 2015. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2015-10-26 10:25+0200\n" "Last-Translator: Ville Skyttä \n" "Language-Team: \n" "Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.8.5\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "Syötä oikea puhelinnumero." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Syötä oikea puhelinnumero." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Syötä oikea puhelinnumero." #: modelfields.py:53 msgid "Phone number" msgstr "Puhelinnumero" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Syötä oikea puhelinnumero." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Syötetty puhelinnumero on virheellinen." django-phonenumber-field-8.1.0/phonenumber_field/locale/fr/000077500000000000000000000000001477567660600237465ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/fr/LC_MESSAGES/000077500000000000000000000000001477567660600255335ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/fr/LC_MESSAGES/django.po000066400000000000000000000034651477567660600273450ustar00rootroot00000000000000# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Ludovic Gasc , 2011. # Stéphane Raimbault , 2018 msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2024-07-16 11:23+0200\n" "Last-Translator: François Freitag \n" "Language-Team: French \n" "Language: fr_FR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Poedit 3.4.2\n" #: formfields.py:57 #, python-brace-format msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Saisissez un numéro de téléphone valide, par exemple {example_number}, ou un " "numéro avec un indicatif international." #: formfields.py:64 #, python-brace-format msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Saisissez un numéro de téléphone valide, par exemple {example_number}." #: formfields.py:157 #, python-brace-format msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Saisissez un numéro de téléphone valide, par exemple {example_number}." #: modelfields.py:53 msgid "Phone number" msgstr "Numéro de téléphone" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Saisissez un numéro de téléphone valide." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Le numéro saisi n'est pas valide." django-phonenumber-field-8.1.0/phonenumber_field/locale/he/000077500000000000000000000000001477567660600237335ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/he/LC_MESSAGES/000077500000000000000000000000001477567660600255205ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/he/LC_MESSAGES/django.po000066400000000000000000000037741477567660600273350ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "הזן מספר טלפון חוקי (לדוגמה {example_number}) או מספר עם קידומת בינלאומית." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "הזן מספר טלפון חוקי (לדוגמה {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "הזן מספר טלפון חוקי (לדוגמה {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "מספר טלפון" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "הזן מספר טלפון חוקי" #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "מספר הטלפון שהוזן אינו חוקי" django-phonenumber-field-8.1.0/phonenumber_field/locale/hy/000077500000000000000000000000001477567660600237575ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/hy/LC_MESSAGES/000077500000000000000000000000001477567660600255445ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/hy/LC_MESSAGES/django.po000066400000000000000000000042001477567660600273420ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Arnak Melikyan \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Մուտքագրեք վավեր հեռախոսահամար (օրինակ, {example_number}) կամ միջազգային " "ձեւաչափով։" #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Մուտքագրեք վավեր հեռախոսահամար (օրինակ, {example_number})։" #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Մուտքագրեք վավեր հեռախոսահամար (օրինակ, {example_number})։" #: modelfields.py:53 msgid "Phone number" msgstr "Հեռախոսահամար" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Մուտքագրեք վավեր հեռախոսահամար" #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Մուտքագրված հեռախոսահամարը վավեր չէ։" django-phonenumber-field-8.1.0/phonenumber_field/locale/id/000077500000000000000000000000001477567660600237335ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/id/LC_MESSAGES/000077500000000000000000000000001477567660600255205ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/id/LC_MESSAGES/django.po000066400000000000000000000037271477567660600273330ustar00rootroot00000000000000# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , 2021. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2021-02-05 21:42+0700\n" "Last-Translator: Arsyi Syarief Aziz \n" "Language-Team: Indonesian \n" "Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Masukkan nomor telepon yang benar (misalkan {example_number}) atau nomor " "yang dilengkapi dengan prefiks kode panggilan internasional." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Masukkan nomor telepon yang benar (misalkan {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Masukkan nomor telepon yang benar (misalkan {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Nomor telepon" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Masukkan nomor telepon yang benar." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Nomor telepon yang dimasukkan tidak benar." django-phonenumber-field-8.1.0/phonenumber_field/locale/it/000077500000000000000000000000001477567660600237535ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/it/LC_MESSAGES/000077500000000000000000000000001477567660600255405ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/it/LC_MESSAGES/django.po000066400000000000000000000041341477567660600273440ustar00rootroot00000000000000# Copyright (C) 2013-2018 # This file is distributed under the same license as the PACKAGE package. # # Francesco Facconi , 2013-2017. # Paolo Melchiorre , 2018. # Ruggero Fabbiano , 2023. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2018-02-28 20:23+0100\n" "Last-Translator: Paolo Melchiorre \n" "Language-Team: Italian \n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Poedit 2.0.4\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Inserisci un numero di telefono valido (esempio: {example_number}) o un " "numero con un prefisso internazionale." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Inserisci un numero di telefono valido (esempio: {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Inserisci un numero di telefono valido (esempio: {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Numero di telefono" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Inserisci un numero di telefono valido." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Il numero di telefono inserito non è valido." django-phonenumber-field-8.1.0/phonenumber_field/locale/ko/000077500000000000000000000000001477567660600237505ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/ko/LC_MESSAGES/000077500000000000000000000000001477567660600255355ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/ko/LC_MESSAGES/django.po000066400000000000000000000033121477567660600273360ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Jiyoon Ha , 2017. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2017-04-15 16:56+0100\n" "Last-Translator: Jiyoon Ha \n" "Language-Team: \n" "Language: ko\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "올바른 전화번호를 입력해주세요." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "올바른 전화번호를 입력해주세요." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "올바른 전화번호를 입력해주세요." #: modelfields.py:53 msgid "Phone number" msgstr "전화번호" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "올바른 전화번호를 입력해주세요." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "입력하신 전화번호가 올바른 형식이 아닙니다." django-phonenumber-field-8.1.0/phonenumber_field/locale/lt/000077500000000000000000000000001477567660600237565ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/lt/LC_MESSAGES/000077500000000000000000000000001477567660600255435ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/lt/LC_MESSAGES/django.po000066400000000000000000000041061477567660600273460ustar00rootroot00000000000000# Lithuanian translations # Copyright (C) 2020 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2020-10-15 21:22+0300\n" "Last-Translator: KiraLT \n" "Language-Team: Lithuanian (http://www.transifex.com/django/django)\n" "Language: lt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " "11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " "1 : n % 1 != 0 ? 2: 3);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Įveskite teisingą telefono numerį (pvz. {example_number}) arba numerį su " "tarptautinio skambučio kodu." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Įveskite teisingą telefono numerį (pvz. {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Įveskite teisingą telefono numerį (pvz. {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Telefono numeris" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Įveskite teisingą telefono numerį." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Įvestas telefono numeris nėra teisingas." django-phonenumber-field-8.1.0/phonenumber_field/locale/nb/000077500000000000000000000000001477567660600237365ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/nb/LC_MESSAGES/000077500000000000000000000000001477567660600255235ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/nb/LC_MESSAGES/django.po000066400000000000000000000037241477567660600273330ustar00rootroot00000000000000# Norwegian Bokmål Translation for django-phonenumber-field. # Copyright (C) 2016 # This file is distributed under the same license as the django-phonenumber-field package. # FIRST AUTHOR , 2016. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2016-10-21 15:04+0200\n" "Last-Translator: Kristian Klette \n" "Language-Team: \n" "Language: nb\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.8.9\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Tast inn et gyldig telefonnummer (f.eks. {example_number}) eller et nummer " "med internasjonal landskode." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Tast inn et gyldig telefonnummer (f.eks. {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Tast inn et gyldig telefonnummer (f.eks. {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Telefonnummer" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Tast inn et gyldig telefonnummer." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Telefonnummeret er ugyldig." django-phonenumber-field-8.1.0/phonenumber_field/locale/nl/000077500000000000000000000000001477567660600237505ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/nl/LC_MESSAGES/000077500000000000000000000000001477567660600255355ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/nl/LC_MESSAGES/django.po000066400000000000000000000037271477567660600273500ustar00rootroot00000000000000# Dutch Translation. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Folkert de Vries , 2016. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Folkert de Vries \n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Vul een geldig telefoonnummer in (bijvoorbeeld: {example_number}) of een " "telefoonnummer voorafgegaan door een landcode (bijvoorbeeld: +31)." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Vul een geldig telefoonnummer in (bijvoorbeeld: {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Vul een geldig telefoonnummer in (bijvoorbeeld: {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Telefoonnummer" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Vul een geldig telefoonnummer in." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Het ingevulde telefoonnummer is niet geldig." django-phonenumber-field-8.1.0/phonenumber_field/locale/pl/000077500000000000000000000000001477567660600237525ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/pl/LC_MESSAGES/000077500000000000000000000000001477567660600255375ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/pl/LC_MESSAGES/django.po000066400000000000000000000040351477567660600273430ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2022-03-22 08:45+0100\n" "Last-Translator: Andrzej Mateja \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Wprowadź poprawny numer telefonu (np. {example_number}) lub numer " "poprzedzony międzynarodowym numerem kierunkowym." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Wprowadź poprawny numer telefonu (np. {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Wprowadź poprawny numer telefonu (np. {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Numer telefonu" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Wprowadź poprawny numer telefonu." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Wprowadzony numer telefonu jest nieprawidłowy." django-phonenumber-field-8.1.0/phonenumber_field/locale/pt/000077500000000000000000000000001477567660600237625ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/pt/LC_MESSAGES/000077500000000000000000000000001477567660600255475ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/pt/LC_MESSAGES/django.po000066400000000000000000000037631477567660600273620ustar00rootroot00000000000000# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Luis Rodrigues , 2013. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2013-02-26 14:10+0200\n" "Last-Translator: Luis Rodrigues \n" "Language-Team: Portuguese \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" "X-Generator: Lokalize 1.2\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Introduza um número de telefone válido (ex. {example_number}) ou um número " "com prefixo internacional" #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Introduza um número de telefone válido (ex. {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Introduza um número de telefone válido (ex. {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Número de telefone" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Introduza um número de telefone válido." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Este número de telefone não é válido." django-phonenumber-field-8.1.0/phonenumber_field/locale/pt_BR/000077500000000000000000000000001477567660600243455ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/pt_BR/LC_MESSAGES/000077500000000000000000000000001477567660600261325ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/pt_BR/LC_MESSAGES/django.po000066400000000000000000000036521477567660600277420ustar00rootroot00000000000000# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Fábio Thomaz , 2017. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2013-02-26 14:10-0300\n" "Last-Translator: Fábio Thomaz \n" "Language-Team: Portuguese - Brazil \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" "X-Generator: Lokalize 1.2\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Forneça um número de telefone válido, por exemplo {example_number}, ou um " "número que tenha um prefixo internacional." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Informe um número de telefone válido." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Informe um número de telefone válido." #: modelfields.py:53 msgid "Phone number" msgstr "Número de telefone" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Informe um número de telefone válido." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Este número de telefone não é válido." django-phonenumber-field-8.1.0/phonenumber_field/locale/ro/000077500000000000000000000000001477567660600237575ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/ro/LC_MESSAGES/000077500000000000000000000000001477567660600255445ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/ro/LC_MESSAGES/django.po000066400000000000000000000033271477567660600273530ustar00rootroot00000000000000# django-phonenumber-field # This file is distributed under the same license as the django-phonenumber-field package. # Cristian Vîjdea , 2018. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2018-10-19 14:07+0300\n" "Last-Translator: Cristi Vîjdea \n" "Language-Team: \n" "Language: ro\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" "2:1));\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "Introduceți un număr de telefon valid." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Introduceți un număr de telefon valid." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Introduceți un număr de telefon valid." #: modelfields.py:53 msgid "Phone number" msgstr "Număr de telefon" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Introduceți un număr de telefon valid." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Numărul de telefon introdus nu este valid." django-phonenumber-field-8.1.0/phonenumber_field/locale/ru/000077500000000000000000000000001477567660600237655ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/ru/LC_MESSAGES/000077500000000000000000000000001477567660600255525ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/ru/LC_MESSAGES/django.po000066400000000000000000000044011477567660600273530ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Nikita Kolesnikov , 2013. msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2021-05-15 19:57+0700\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Введите корректный номер телефона (например, {example_number}) или номер с " "префиксом международной связи." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Введите корректный номер телефона (например, {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Введите корректный номер телефона (например, {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Номер телефона" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Введите корректный номер телефона." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Введен некорректный номер телефона." django-phonenumber-field-8.1.0/phonenumber_field/locale/sk/000077500000000000000000000000001477567660600237545ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/sk/LC_MESSAGES/000077500000000000000000000000001477567660600255415ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/sk/LC_MESSAGES/django.po000066400000000000000000000033501477567660600273440ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "Vložte platné telefónne číslo." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Vložte platné telefónne číslo." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Vložte platné telefónne číslo." #: modelfields.py:53 msgid "Phone number" msgstr "Telefónne číslo" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Vložte platné telefónne číslo." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Zadané telefónne číslo je neplatné." django-phonenumber-field-8.1.0/phonenumber_field/locale/sv/000077500000000000000000000000001477567660600237675ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/sv/LC_MESSAGES/000077500000000000000000000000001477567660600255545ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/sv/LC_MESSAGES/django.po000066400000000000000000000036551477567660600273670ustar00rootroot00000000000000# Swedish Locale # Copyright (C) 2017 # This file is distributed under the same license as the django-phonenumber-field package. # Jonas Lidén , 2017. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2017-12-05 22:18+0100\n" "Last-Translator: Jonas Lidén \n" "Language-Team: Swedish\n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.8.7.1\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Ange ett giltigt telefonnummer (t ex {example_number}) eller ett nummer med " "internationellt format." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Ange ett giltigt telefonnummer (t ex {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Ange ett giltigt telefonnummer (t ex {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Telefonnummer" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Ange ett giltigt telefonnummer." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Det angivna telefonnumret är inte giltigt." django-phonenumber-field-8.1.0/phonenumber_field/locale/tr/000077500000000000000000000000001477567660600237645ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/tr/LC_MESSAGES/000077500000000000000000000000001477567660600255515ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/tr/LC_MESSAGES/django.po000066400000000000000000000037631477567660600273640ustar00rootroot00000000000000# Turkish Locale. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Emin Mastizada , 2016. # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2022-01-15 14:51+0300\n" "Last-Translator: Şuayip Üzülmez \n" "Language-Team: LANGUAGE \n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Geçerli bir telefon numarası girin (ör. {example_number}) ya da uluslararası " "arama öneki olan bir numara girin." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Geçerli bir telefon numarası giriniz (ör. {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Geçerli bir telefon numarası giriniz (ör. {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Telefon numarası" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Geçerli bir telefon numarası giriniz." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Girmiş olduğunuz telefon numarası geçersiz." django-phonenumber-field-8.1.0/phonenumber_field/locale/uk/000077500000000000000000000000001477567660600237565ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/uk/LC_MESSAGES/000077500000000000000000000000001477567660600255435ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/uk/LC_MESSAGES/django.po000066400000000000000000000043441477567660600273520ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Nikita Kolesnikov , 2013. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2018-06-06 00:07+0300\n" "Last-Translator: \n" "Language-Team: \n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Poedit 2.0.8\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Введіть коректний номер телефону (наприклад, {example_number}) або номер з " "префіксом міжнародного зв'язку." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Введіть коректний номер телефону (наприклад, {example_number})." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number (e.g. {example_number})." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Введіть коректний номер телефону (наприклад, {example_number})." #: modelfields.py:53 msgid "Phone number" msgstr "Номер телефону" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Введіть коректний номер телефону." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Введено некоректний номер телефону." django-phonenumber-field-8.1.0/phonenumber_field/locale/uk_UA/000077500000000000000000000000001477567660600243435ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/uk_UA/LC_MESSAGES/000077500000000000000000000000001477567660600261305ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/uk_UA/LC_MESSAGES/django.po000066400000000000000000000041071477567660600277340ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Nikita Kolesnikov , 2013. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: 2018-06-06 00:07+0300\n" "Last-Translator: \n" "Language-Team: \n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Poedit 2.0.8\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "" "Введіть коректний номер телефону (e.g. {example_number}) або номер " "зміжнародним префіксом." #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Введіть коректний номер телефону." #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "Введіть коректний номер телефону." #: modelfields.py:53 msgid "Phone number" msgstr "Номер телефону" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "Введіть коректний номер телефону." #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "Введено некоректний номер телефону." django-phonenumber-field-8.1.0/phonenumber_field/locale/zh_Hans/000077500000000000000000000000001477567660600247315ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/zh_Hans/LC_MESSAGES/000077500000000000000000000000001477567660600265165ustar00rootroot00000000000000django-phonenumber-field-8.1.0/phonenumber_field/locale/zh_Hans/LC_MESSAGES/django.po000066400000000000000000000036131477567660600303230ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-07-16 11:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Wentao Han \n" "Language-Team: \n" "Language: zh-Hans\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #: formfields.py:57 #, fuzzy, python-brace-format #| msgid "" #| "Enter a valid phone number (e.g. {example_number}) or a number with an " #| "international call prefix." msgctxt "{example_number} is a national phone number." msgid "" "Enter a valid phone number (e.g. {example_number}) or a number with an " "international call prefix." msgstr "输入一个合法的电话号码(例如,{example_number})或带国际冠码的号码。" #: formfields.py:64 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is an international phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "输入一个合法的电话号码(例如,{example_number})。" #: formfields.py:157 #, fuzzy, python-brace-format #| msgid "Enter a valid phone number." msgctxt "{example_number} is a national phone number." msgid "Enter a valid phone number (e.g. {example_number})." msgstr "输入一个合法的电话号码(例如,{example_number})。" #: modelfields.py:53 msgid "Phone number" msgstr "电话号码" #: serializerfields.py:10 msgid "Enter a valid phone number." msgstr "输入一个合法的电话号码。" #: validators.py:12 validators.py:23 msgid "The phone number entered is not valid." msgstr "输入的电话号码不合法。" django-phonenumber-field-8.1.0/phonenumber_field/modelfields.py000066400000000000000000000104721477567660600247450ustar00rootroot00000000000000from typing import Optional from django.conf import settings from django.core import checks from django.db import models from django.forms import Field from django.utils.encoding import force_str from django.utils.translation import gettext_lazy as _ from phonenumber_field import formfields from phonenumber_field.phonenumber import PhoneNumber, to_python, validate_region from phonenumber_field.validators import validate_international_phonenumber class PhoneNumberDescriptor: """ The descriptor for the phone number attribute on the model instance. Returns a PhoneNumber when accessed so you can do stuff like:: >>> instance.phone_number.as_international Assigns a phone number object on assignment so you can do:: >>> instance.phone_number = PhoneNumber(...) or, >>> instance.phone_number = '+414204242' """ def __init__(self, field): self.field = field def __get__(self, instance, owner): if instance is None: return self # The instance dict contains whatever was originally assigned in # __set__. if self.field.name in instance.__dict__: value = instance.__dict__[self.field.name] else: instance.refresh_from_db(fields=[self.field.name]) value = getattr(instance, self.field.name) return value def __set__(self, instance, value): instance.__dict__[self.field.name] = to_python(value, region=self.field.region) class PhoneNumberField(models.CharField): attr_class = PhoneNumber descriptor_class = PhoneNumberDescriptor default_validators = [validate_international_phonenumber] description = _("Phone number") def __init__(self, *args, region=None, **kwargs): """ :keyword str region: 2-letter country code as defined in ISO 3166-1. When not supplied, defaults to :setting:`PHONENUMBER_DEFAULT_REGION` :keyword int max_length: The maximum length of the underlying char field. """ kwargs.setdefault("max_length", 128) super().__init__(*args, **kwargs) self._region = region @property def region(self): return self._region or getattr(settings, "PHONENUMBER_DEFAULT_REGION", None) def check(self, **kwargs): errors = super().check(**kwargs) errors.extend(self._check_region()) return errors def _check_region(self): try: validate_region(self.region) except ValueError as e: return [checks.Error(force_str(e), obj=self)] return [] def get_prep_value(self, value): """ Perform preliminary non-db specific value checks and conversions. """ if not value: return super().get_prep_value(value) if isinstance(value, PhoneNumber): parsed_value = value else: # Convert the string to a PhoneNumber object. parsed_value = to_python(value) if parsed_value.is_valid(): # A valid phone number. Normalize it for storage. format_string = getattr(settings, "PHONENUMBER_DB_FORMAT", "E164") fmt = PhoneNumber.format_map[format_string] value = parsed_value.format_as(fmt) else: # Not a valid phone number. Store the raw string. value = parsed_value.raw_input return super().get_prep_value(value) def from_db_value(self, value, expression, connection): return to_python(value) def contribute_to_class(self, cls, name, *args, **kwargs): super().contribute_to_class(cls, name, *args, **kwargs) setattr(cls, self.name, self.descriptor_class(self)) def deconstruct(self): name, path, args, kwargs = super().deconstruct() kwargs["region"] = self._region return name, path, args, kwargs def formfield( self, form_class=None, choices_form_class=None, **kwargs, ) -> Optional[Field]: defaults = { "form_class": ( formfields.PhoneNumberField if form_class is None else form_class ), "region": self.region, "error_messages": self.error_messages, "choices_form_class": choices_form_class, } defaults.update(kwargs) return super().formfield(**defaults) django-phonenumber-field-8.1.0/phonenumber_field/phonenumber.py000066400000000000000000000134311477567660600247760ustar00rootroot00000000000000from __future__ import annotations from functools import total_ordering from typing import TYPE_CHECKING import phonenumbers from django.conf import settings from django.core import validators if TYPE_CHECKING: # Use ‘from typing import Self’ from Python 3.11 onwards. from typing_extensions import Self @total_ordering class PhoneNumber(phonenumbers.PhoneNumber): """ A extended version of phonenumbers.PhoneNumber that provides some neat and more pythonic, easy to access methods. This makes using a PhoneNumber instance much easier, especially in templates and such. """ format_map = { "E164": phonenumbers.PhoneNumberFormat.E164, "INTERNATIONAL": phonenumbers.PhoneNumberFormat.INTERNATIONAL, "NATIONAL": phonenumbers.PhoneNumberFormat.NATIONAL, "RFC3966": phonenumbers.PhoneNumberFormat.RFC3966, } @classmethod def from_string(cls, phone_number, region=None) -> Self: """ :arg str phone_number: parse this :class:`str` as a phone number. :keyword str region: 2-letter country code as defined in ISO 3166-1. When not supplied, defaults to :setting:`PHONENUMBER_DEFAULT_REGION` """ phone_number_obj = cls() if region is None: region = getattr(settings, "PHONENUMBER_DEFAULT_REGION", None) phonenumbers.parse( number=phone_number, region=region, keep_raw_input=True, numobj=phone_number_obj, ) return phone_number_obj def __str__(self): if self.is_valid(): format_string = getattr(settings, "PHONENUMBER_DEFAULT_FORMAT", "E164") fmt = self.format_map[format_string] return self.format_as(fmt) else: return self.raw_input def __repr__(self): if not self.is_valid(): return f"Invalid{type(self).__name__}(raw_input={self.raw_input})" return super().__repr__() def is_valid(self): """ Whether the number supplied is actually valid. :return: ``True`` when the phone number is valid. :rtype: bool """ return phonenumbers.is_valid_number(self) def format_as(self, format): return phonenumbers.format_number(self, format) @property def as_international(self): return self.format_as(phonenumbers.PhoneNumberFormat.INTERNATIONAL) @property def as_e164(self): return self.format_as(phonenumbers.PhoneNumberFormat.E164) @property def as_national(self): return self.format_as(phonenumbers.PhoneNumberFormat.NATIONAL) @property def as_rfc3966(self): return self.format_as(phonenumbers.PhoneNumberFormat.RFC3966) def __len__(self): return len(str(self)) def __eq__(self, other): """ Override parent equality because we store only string representation of phone number, so we must compare only this string representation """ if other in validators.EMPTY_VALUES: return False elif isinstance(other, str): default_region = getattr(settings, "PHONENUMBER_DEFAULT_REGION", None) other = to_python(other, region=default_region) elif isinstance(other, type(self)): # Nothing to do. Good to compare. pass elif isinstance(other, phonenumbers.PhoneNumber): # The parent class of PhoneNumber does not have .is_valid(). # We need to make it match ours. old_other = other other = type(self)() other.merge_from(old_other) else: return False format_string = getattr(settings, "PHONENUMBER_DB_FORMAT", "E164") fmt = self.format_map[format_string] self_str = self.format_as(fmt) if self.is_valid() else self.raw_input other_str = other.format_as(fmt) if other.is_valid() else other.raw_input return self_str == other_str def __lt__(self, other): if isinstance(other, phonenumbers.PhoneNumber): old_other = other other = type(self)() other.merge_from(old_other) elif not isinstance(other, type(self)): raise TypeError( "'<' not supported between instances of " f"'{type(self).__name__}' and '{type(other).__name__}'" ) invalid = None if not self.is_valid(): invalid = self elif not other.is_valid(): invalid = other if invalid is not None: raise ValueError(f"Invalid phone number: {invalid!r}") format_string = getattr(settings, "PHONENUMBER_DB_FORMAT", "E164") fmt = self.format_map[format_string] return self.format_as(fmt) < other.format_as(fmt) def __hash__(self): return hash(str(self)) def to_python(value, region=None): if value in validators.EMPTY_VALUES: # None or '' phone_number = value elif isinstance(value, str): try: phone_number = PhoneNumber.from_string(phone_number=value, region=region) except phonenumbers.NumberParseException: # the string provided is not a valid PhoneNumber. phone_number = PhoneNumber(raw_input=value) elif isinstance(value, PhoneNumber): phone_number = value elif isinstance(value, phonenumbers.PhoneNumber): phone_number = PhoneNumber() phone_number.merge_from(value) else: raise TypeError(f"Can't convert {type(value).__name__} to PhoneNumber.") return phone_number def validate_region(region): if region is not None and region not in phonenumbers.SUPPORTED_REGIONS: raise ValueError( f"“{region}” is not a valid region code. " f"Choices are {phonenumbers.SUPPORTED_REGIONS!r}" ) django-phonenumber-field-8.1.0/phonenumber_field/serializerfields.py000066400000000000000000000022451477567660600260150ustar00rootroot00000000000000from django.conf import settings from django.utils.translation import gettext_lazy as _ from rest_framework import serializers from rest_framework.exceptions import ValidationError from phonenumber_field.phonenumber import PhoneNumber, to_python, validate_region class PhoneNumberField(serializers.CharField): default_error_messages = {"invalid": _("Enter a valid phone number.")} def __init__(self, *args, region=None, **kwargs): """ :keyword str region: 2-letter country code as defined in ISO 3166-1. When not supplied, defaults to :setting:`PHONENUMBER_DEFAULT_REGION` """ super().__init__(*args, **kwargs) validate_region(region) self.region = region or getattr(settings, "PHONENUMBER_DEFAULT_REGION", None) def to_internal_value(self, data): if isinstance(data, PhoneNumber): phone_number = data else: str_value = super().to_internal_value(data) phone_number = to_python(str_value, region=self.region) if phone_number and not phone_number.is_valid(): raise ValidationError(self.error_messages["invalid"]) return phone_number django-phonenumber-field-8.1.0/phonenumber_field/validators.py000066400000000000000000000014711477567660600246250ustar00rootroot00000000000000import phonenumbers from django.core.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ from phonenumber_field.phonenumber import PhoneNumber, to_python def validate_international_phonenumber(value): phone_number = to_python(value) if isinstance(phone_number, PhoneNumber) and not phone_number.is_valid(): raise ValidationError( _("The phone number entered is not valid."), code="invalid" ) def validate_phonenumber(value): phone_number = to_python(value) if isinstance(phone_number, PhoneNumber) and not ( phonenumbers.is_valid_number(phone_number) or phonenumbers.is_valid_short_number(phone_number) ): raise ValidationError( _("The phone number entered is not valid."), code="invalid" ) django-phonenumber-field-8.1.0/phonenumber_field/widgets.py000066400000000000000000000036331477567660600241250ustar00rootroot00000000000000from django.conf import settings from django.forms.widgets import MultiWidget, TextInput from phonenumbers import ( national_significant_number, region_code_for_number, region_codes_for_country_code, ) from phonenumber_field.phonenumber import PhoneNumber, to_python class PhoneNumberPrefixWidget(MultiWidget): """ Companion widget of :class:`~phonenumber_field.formfields.SplitPhoneNumberField`. """ def decompress(self, value): if isinstance(value, PhoneNumber): region_code = region_code_for_number(value) national_number = national_significant_number(value) return [region_code, national_number] return [None, None] class RegionalPhoneNumberWidget(TextInput): """ A :class:`~django.forms.Widget` that prefers displaying numbers in the national format, and falls back to :setting:`PHONENUMBER_DEFAULT_FORMAT` for international numbers. """ input_type = "tel" def __init__(self, region=None, attrs=None): """ :keyword str region: 2-letter country code as defined in ISO 3166-1. When not supplied, defaults to :setting:`PHONENUMBER_DEFAULT_REGION` :keyword dict attrs: See :attr:`django.forms.Widget.attrs` """ if region is None: region = getattr(settings, "PHONENUMBER_DEFAULT_REGION", None) self.region = region super().__init__(attrs) def format_value(self, value): number = value if not isinstance(number, PhoneNumber): try: number = to_python(value, region=self.region) except TypeError: pass if isinstance(number, PhoneNumber) and number.country_code: region_codes = region_codes_for_country_code(number.country_code) if self.region in region_codes: return number.as_national return super().format_value(value) django-phonenumber-field-8.1.0/pyproject.toml000066400000000000000000000051571477567660600213370ustar00rootroot00000000000000[project] name = "django-phonenumber-field" requires-python = ">=3.9" description = "An international phone number field for django models." readme = "README.rst" authors = [ { name="Stefan Foulis", email="stefan@foulis.ch" }, { name="François Freitag", email="mail@franek.fr" }, ] maintainers = [ { name="François Freitag", email="mail@franek.fr" }, { name="Stefan Foulis", email="stefan@foulis.ch" }, ] license = { text="MIT" } classifiers = [ "Development Status :: 5 - Production/Stable", "Framework :: Django", "Framework :: Django :: 4.2", "Framework :: Django :: 5.0", "Framework :: Django :: 5.1", "Framework :: Django :: 5.2", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Internet :: WWW/HTTP", ] dynamic = ["version"] dependencies = ["Django>=4.2"] [project.optional-dependencies] phonenumbers = ["phonenumbers >= 7.0.2"] phonenumberslite = ["phonenumberslite >= 7.0.2"] [project.urls] Homepage = "https://github.com/stefanfoulis/django-phonenumber-field" Documentation = "https://django-phonenumber-field.readthedocs.io/" Source = "https://github.com/stefanfoulis/django-phonenumber-field" Tracker = "https://github.com/stefanfoulis/django-phonenumber-field/issues/" Changelog = "https://github.com/stefanfoulis/django-phonenumber-field/releases/" [tool.ruff.lint] # see prefixes in https://beta.ruff.rs/docs/rules/ select = [ "F", # pyflakes "E", # pycodestyle errors "W", # pycodestyle warnings "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehension "U", # pyupgrade ] [build-system] requires = [ "setuptools>=42", "setuptools_scm[toml]>=3.4", ] build-backend = "setuptools.build_meta" [tool.mypy] python_version = "3.9" check_untyped_defs = true show_error_context = true pretty = true plugins = ["mypy_django_plugin.main", "mypy_drf_plugin.main"] warn_no_return = true warn_redundant_casts = true warn_return_any = true warn_unreachable = true warn_unused_configs = true warn_unused_ignores = true [tool.django-stubs] django_settings_module = "tests.settings" [tool.setuptools_scm] write_to = "phonenumber_field/version.py" django-phonenumber-field-8.1.0/tests/000077500000000000000000000000001477567660600175555ustar00rootroot00000000000000django-phonenumber-field-8.1.0/tests/__init__.py000066400000000000000000000000001477567660600216540ustar00rootroot00000000000000django-phonenumber-field-8.1.0/tests/forms.py000066400000000000000000000007101477567660600212530ustar00rootroot00000000000000from django import forms from phonenumber_field.formfields import PhoneNumberField from .models import NullablePhoneNumber, TestModelRegionAR class PhoneNumberForm(forms.ModelForm): class Meta: model = NullablePhoneNumber fields = ["phone_number"] class CustomPhoneNumberFormField(PhoneNumberField): pass class ARPhoneNumberForm(forms.ModelForm): class Meta: model = TestModelRegionAR fields = ["phone"] django-phonenumber-field-8.1.0/tests/models.py000066400000000000000000000057441477567660600214240ustar00rootroot00000000000000from django.db import models from phonenumber_field.modelfields import PhoneNumberField class MandatoryPhoneNumber(models.Model): phone_number = PhoneNumberField() class OptionalPhoneNumber(models.Model): phone_number = PhoneNumberField(blank=True) class NullablePhoneNumber(models.Model): phone_number = PhoneNumberField(blank=True, null=True) class CustomPhoneNumberModelField(PhoneNumberField): def formfield(self, **kwargs): from .forms import CustomPhoneNumberFormField return super().formfield(form_class=CustomPhoneNumberFormField) class CustomPhoneNumber(models.Model): phone_number = CustomPhoneNumberModelField() class TestModel(models.Model): """Basic Field Test""" name = models.CharField(max_length=255, blank=True) phone = PhoneNumberField() class TestModelPhoneB(models.Model): """Field Test for when Blank""" name = models.CharField(max_length=255, blank=True) phone = PhoneNumberField(blank=True) class TestModelPhoneNU(models.Model): """Field Test for when Null & Unique""" name = models.CharField(max_length=255, blank=True) phone = PhoneNumberField(null=True, unique=True) class TestModelPhoneBNU(models.Model): """Field Test for when Blank, Null & Unique""" name = models.CharField(max_length=255, blank=True) phone = PhoneNumberField(blank=True, null=True, unique=True) class TestModelPhoneNDNU(models.Model): """Field Test for when No Default, Null & Unique""" name = models.CharField(max_length=255, blank=True) phone = PhoneNumberField(default=models.NOT_PROVIDED, null=True, unique=True) class TestModelPhoneBNDNU(models.Model): """Field Test for when Blank, No Default, Null & Unique""" name = models.CharField(max_length=255, blank=True) phone = PhoneNumberField( blank=True, default=models.NOT_PROVIDED, null=True, unique=True ) class TestModelPhoneDNU(models.Model): """Field Test for when Default, Null & Unique""" name = models.CharField(max_length=255, blank=True) phone = PhoneNumberField(default="+41524242424", null=True, unique=True) class TestModelPhoneBDNU(models.Model): """Field Test for when Blank, Default, Null & Unique""" name = models.CharField(max_length=255, blank=True) phone = PhoneNumberField(blank=True, default="+41524242424", null=True, unique=True) class TestModelPhoneEDNU(models.Model): """Field Test for when Empty Default, Null & Unique""" name = models.CharField(max_length=255, blank=True) phone = PhoneNumberField(default="", null=True, unique=True) class TestModelPhoneBEDNU(models.Model): """Field Test for when Blank, Empty Default, Null & Unique""" name = models.CharField(max_length=255, blank=True) phone = PhoneNumberField(blank=True, default="", null=True, unique=True) class FrenchPhoneOwner(models.Model): cell_number = PhoneNumberField(region="FR") class TestModelRegionAR(models.Model): phone = PhoneNumberField(region="AR", blank=True, null=True) django-phonenumber-field-8.1.0/tests/settings.py000066400000000000000000000003011477567660600217610ustar00rootroot00000000000000DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3"}} DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" SECRET_KEY = "secrekey" INSTALLED_APPS = ["phonenumber_field", "tests"] django-phonenumber-field-8.1.0/tests/test_formfields.py000066400000000000000000000575471477567660600233420ustar00rootroot00000000000000from unittest import mock import django import phonenumbers from django import forms from django.core.exceptions import ImproperlyConfigured from django.test import SimpleTestCase, override_settings from django.utils import translation from django.utils.functional import lazy from phonenumbers import COUNTRY_CODES_FOR_NON_GEO_REGIONS from phonenumber_field.formfields import PhoneNumberField, SplitPhoneNumberField from phonenumber_field.phonenumber import PhoneNumber from phonenumber_field.validators import validate_phonenumber ALGERIAN_PHONE_NUMBER = "+213799136332" class PhoneNumberFormFieldTest(SimpleTestCase): def test_error_message(self): class PhoneNumberForm(forms.Form): number = PhoneNumberField() form = PhoneNumberForm({"number": "invalid"}) self.assertIs(form.is_valid(), False) self.assertEqual( form.errors, {"number": ["Enter a valid phone number (e.g. +12125552368)."]} ) @override_settings(PHONENUMBER_DEFAULT_REGION="FR") def test_error_message_uses_default_region(self): class PhoneNumberForm(forms.Form): number = PhoneNumberField() form = PhoneNumberForm({"number": "invalid"}) self.assertIs(form.is_valid(), False) self.assertEqual( form.errors, { "number": [ "Enter a valid phone number (e.g. 01 23 45 67 89) " "or a number with an international call prefix." ] }, ) def test_override_error_message(self): class MyPhoneNumberField(PhoneNumberField): default_error_messages = {"invalid": "MY INVALID MESSAGE!"} class PhoneNumberForm(forms.Form): number = MyPhoneNumberField() form = PhoneNumberForm({"number": "invalid"}) self.assertIs(form.is_valid(), False) self.assertEqual(form.errors, {"number": ["MY INVALID MESSAGE!"]}) def test_override_error_message_inline(self): class PhoneNumberForm(forms.Form): number = PhoneNumberField( error_messages={"invalid": "MY INLINE INVALID MESSAGE!"} ) form = PhoneNumberForm({"number": "invalid"}) self.assertIs(form.is_valid(), False) self.assertEqual(form.errors, {"number": ["MY INLINE INVALID MESSAGE!"]}) def test_algerian_phone_number_in_form(self): class PhoneNumberForm(forms.Form): number = PhoneNumberField() form = PhoneNumberForm({"number": ALGERIAN_PHONE_NUMBER}) self.assertTrue(form.is_valid()) self.assertEqual(ALGERIAN_PHONE_NUMBER, form.cleaned_data["number"]) def test_error_message_lazy(self): def fail_gettext(msgid): raise Exception("gettext was called unexpectedly.") with mock.patch( "phonenumber_field.formfields.pgettext_lazy", side_effect=lazy(fail_gettext, str), ): PhoneNumberField() def test_override_widget(self): class MyPhoneNumberField(PhoneNumberField): widget = forms.TextInput class TestForm(forms.Form): phone = MyPhoneNumberField(region="FR") form = TestForm({"phone": "+33612345678"}) self.assertIs(form.is_valid(), True) self.assertHTMLEqual( form.as_p(), """

""", ) @override_settings(PHONENUMBER_DEFAULT_REGION="FR") def test_widget_uses_default_region(self): class TestForm(forms.Form): phone = PhoneNumberField() form = TestForm({"phone": "+33612345678"}) self.assertIs(form.is_valid(), True) self.assertHTMLEqual( form.as_p(), """

""", ) def test_invalid_phone_number(self): class PhoneNumberForm(forms.Form): number = PhoneNumberField() form = PhoneNumberForm({"number": "+11234567890"}) self.assertIs(form.is_valid(), False) self.assertEqual( form.errors, {"number": ["Enter a valid phone number (e.g. +12125552368)."]} ) def test_validate_shortcode(self): class ShortCodePhoneNumberField(PhoneNumberField): default_validators = [validate_phonenumber] class TestForm(forms.Form): phone = ShortCodePhoneNumberField(region="FR") form = TestForm({"phone": "1010"}) self.assertIs(form.is_valid(), True) class SplitPhoneNumberFormFieldTest(SimpleTestCase): def example_number(self, region_code: str) -> PhoneNumber: number = phonenumbers.example_number(region_code) assert number is not None e164 = phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164) return PhoneNumber.from_string(e164, region=region_code) def test_initial_empty(self): class TestForm(forms.Form): phone = SplitPhoneNumberField(region="CN") rendered = str(TestForm()) self.assertIn('', rendered) self.assertIn('', rendered) @override_settings(PHONENUMBER_DEFAULT_REGION="CN") def test_uses_default_region_as_initial(self): class TestForm(forms.Form): phone = SplitPhoneNumberField() rendered = str(TestForm()) self.assertIn('', rendered) self.assertIn('', rendered) def test_no_initial(self): class TestForm(forms.Form): phone = SplitPhoneNumberField() rendered = str(TestForm()) self.assertIn('', rendered) self.assertIn('', rendered) for prefix in COUNTRY_CODES_FOR_NON_GEO_REGIONS: self.assertNotIn(f"+{prefix}", rendered) def test_initial(self): class TestForm(forms.Form): phone = SplitPhoneNumberField() rendered = str( TestForm(initial={"phone": PhoneNumber.from_string("+33612345678")}) ) self.assertIn('', rendered) self.assertIn('', rendered) self.assertIn( '', rendered, ) def test_invalid_phone_number(self): class TestForm(forms.Form): phone = SplitPhoneNumberField() form = TestForm({"phone_0": "US", "phone_1": "1234567890"}) self.assertIs(form.is_valid(), False) self.assertEqual( form.errors, {"phone": ["Enter a valid phone number (e.g. (201) 555-0123)."]}, ) @override_settings(USE_I18N=True) def test_after_translation_deactivate_all(self): class TestForm(forms.Form): phone = SplitPhoneNumberField() translation.deactivate_all() rendered = str(TestForm()) self.assertIn( '', rendered_form, count=1, ) self.assertInHTML( '', rendered_form, count=1, ) def test_empty_national_number(self): class TestForm(forms.Form): phone = SplitPhoneNumberField() form = TestForm(data={"phone_0": "CA", "phone_1": ""}) self.assertFalse(form.is_valid()) rendered_form = form.as_ul() if django.VERSION >= (5, 2): self.assertInHTML( """
  • This field is required.
""", rendered_form, ) else: self.assertInHTML( '
  • This field is required.
', rendered_form, ) aria_invalid = "" if django.VERSION[0] < 5 else 'aria-invalid="true" ' self.assertInHTML( f'', rendered_form, count=1, ) def test_not_required_empty_data(self): class TestForm(forms.Form): phone = SplitPhoneNumberField(required=False) form = TestForm(data={"phone_0": "", "phone_1": ""}) self.assertIs(form.is_valid(), True) def test_no_region(self): class TestForm(forms.Form): phone = SplitPhoneNumberField() form = TestForm(data={"phone_1": "654321"}) self.assertFalse(form.is_valid()) rendered_form = form.as_ul() if django.VERSION >= (5, 2): self.assertInHTML( """
  • This field is required.
""", rendered_form, ) else: self.assertInHTML( '
  • This field is required.
', rendered_form, ) aria_invalid = "" if django.VERSION[0] < 5 else 'aria-invalid="true" ' self.assertInHTML( f'', rendered_form, count=1, ) self.assertInHTML( '', rendered_form, count=1, ) def test_no_national_number(self): class TestForm(forms.Form): phone = SplitPhoneNumberField() form = TestForm(data={"phone_0": "CA"}) self.assertFalse(form.is_valid()) rendered_form = form.as_ul() if django.VERSION >= (5, 2): self.assertInHTML( """
  • This field is required.
""", rendered_form, count=1, ) else: self.assertInHTML( '
  • This field is required.
', rendered_form, count=1, ) aria_invalid = "" if django.VERSION[0] < 5 else 'aria-invalid="true" ' self.assertInHTML( f'', rendered_form, count=1, ) def test_not_required_no_data(self): class TestForm(forms.Form): phone = SplitPhoneNumberField(required=False) form = TestForm(data={}) self.assertIs(form.is_valid(), True) def test_keeps_region_with_invalid_national_number(self): class TestForm(forms.Form): phone = SplitPhoneNumberField() form = TestForm(data={"phone_0": "CA", "phone_1": "0000"}) self.assertFalse(form.is_valid()) rendered_form = str(form) if django.VERSION >= (5, 2): self.assertInHTML( """
  • Enter a valid phone number (e.g. (506) 234-5678).
""", rendered_form, count=1, ) else: self.assertInHTML( '
    ' "
  • Enter a valid phone number (e.g. (506) 234-5678).
", rendered_form, ) aria_invalid = "" if django.VERSION[0] < 5 else 'aria-invalid="true" ' self.assertInHTML( f'', rendered_form, count=1, ) self.assertInHTML( '', rendered_form, count=1, ) def test_maxlength_not_in_select(self): # Regression test for #490 class TestForm(forms.Form): phone = SplitPhoneNumberField() rendered = str(TestForm()) self.assertIn('', rendered, ) self.assertInHTML( '', rendered, count=1, ) def test_custom_choices(self): class SplitPhoneNumberFieldWithCountries(SplitPhoneNumberField): def prefix_field(self): return forms.ChoiceField(choices=[("FR", "France"), ("BE", "Belgium")]) class TestForm(forms.Form): phone = SplitPhoneNumberFieldWithCountries() form = TestForm() if django.VERSION[0] < 4: self.assertHTMLEqual( str(form.as_p()), """

""", ) else: self.assertHTMLEqual( form.as_div(), """
Phone:
""", ) def test_invalid_region(self): class PhoneNumberForm(forms.Form): number = SplitPhoneNumberField() form = PhoneNumberForm({"number_0": "NONEXISTENT", "number_1": "+33612345678"}) self.assertIs(form.is_valid(), False) self.assertEqual( form.errors, { "number": [ "Select a valid choice. " "NONEXISTENT is not one of the available choices." ] }, ) @override_settings(PHONENUMBER_DEFAULT_REGION="FR") def test_input_not_cleared_on_other_field_error(self): class PhoneNumberForm(forms.Form): name = forms.CharField(min_length=4, max_length=100) number = SplitPhoneNumberField(required=False) form = PhoneNumberForm({"name": "a", "number_0": "FR", "number_1": "612345678"}) self.assertIs(form.is_valid(), False) self.assertEqual( form.errors, {"name": ["Ensure this value has at least 4 characters (it has 1)."]}, ) form_html = form.as_p() if django.VERSION >= (5, 2): self.assertInHTML( """
  • Ensure this value has at least 4 characters (it has 1).

""", form_html, count=1, ) else: aria_invalid = "" if django.VERSION[0] < 5 else 'aria-invalid="true" ' self.assertInHTML( f"""
  • Ensure this value has at least 4 characters (it has 1).

""", form_html, count=1, ) self.assertInHTML( '', form_html, count=1, ) self.assertInHTML( '', form_html, count=1, ) def test_without_babel(self): import phonenumber_field.formfields babel = phonenumber_field.formfields.babel def restore_babel(): phonenumber_field.formfields.babel = babel self.addCleanup(restore_babel) phonenumber_field.formfields.babel = None with self.assertRaises(ImproperlyConfigured): SplitPhoneNumberField() def test_error_message_is_localized(self): class PhoneNumberForm(forms.Form): number = SplitPhoneNumberField() form = PhoneNumberForm({"number_0": "FR", "number_1": "1"}) if django.VERSION >= (5, 2): self.assertIn( '
  • ' "Enter a valid phone number (e.g. 01 23 45 67 89)." "
", str(form), ) else: self.assertIn( '
  • ' "Enter a valid phone number (e.g. 01 23 45 67 89)." "
", str(form), ) def test_customize_invalid_error_message(self): class CustomSplitPhoneNumberField(SplitPhoneNumberField): def invalid_error_message(self): return "My message using {example_number}." class TestForm(forms.Form): phone = CustomSplitPhoneNumberField() form = TestForm({"phone_0": "FR", "phone_1": "1"}) if django.VERSION >= (5, 2): self.assertInHTML( """
  • My message using 01 23 45 67 89.
""", str(form), count=1, ) else: self.assertIn( '
  • My message using 01 23 45 67 89.
', str(form), ) def test_clean_handles_invalid_input(self): data = [ # require_all_fields, phone_data, error_message (True, {"phone_0": "", "phone_1": "1234"}, "This field is required."), (True, {}, "This field is required."), (True, {"phone_1": "1234"}, "This field is required."), ( True, {"phone_0": "invalid", "phone_1": "1234"}, "Select a valid choice. invalid is not one of the available choices.", ), (False, {"phone_0": "", "phone_1": "1234"}, "Enter a complete value."), (False, {}, "This field is required."), (False, {"phone_1": "1234"}, "Enter a complete value."), ( False, {"phone_0": "invalid", "phone_1": "1234"}, "Select a valid choice. invalid is not one of the available choices.", ), ] for all_fields_required, phone_data, error_message in data: with self.subTest( f"require_all_fields={all_fields_required}," f"{phone_data=}," f"{error_message=}" ): class TestForm(forms.Form): phone = SplitPhoneNumberField( require_all_fields=all_fields_required ) form = TestForm(phone_data) self.assertIs(form.is_valid(), False) self.assertEqual(form.errors["phone"], [error_message]) def test_validate_shortcode(self): class ShortCodeSplitPhoneNumberField(SplitPhoneNumberField): default_validators = [validate_phonenumber] class TestForm(forms.Form): phone = ShortCodeSplitPhoneNumberField() form = TestForm({"phone_0": "FR", "phone_1": "1010"}) self.assertIs(form.is_valid(), True) django-phonenumber-field-8.1.0/tests/test_phonenumber.py000066400000000000000000000067421477567660600235210ustar00rootroot00000000000000import phonenumbers from django.test import SimpleTestCase, override_settings from phonenumber_field.phonenumber import PhoneNumber class PhoneNumberTest(SimpleTestCase): def test_phonenumber_default_format(self): phone = PhoneNumber.from_string("+33612345678") # E164 by default. self.assertEqual(str(phone), "+33612345678") with override_settings(PHONENUMBER_DEFAULT_FORMAT="E164"): self.assertEqual(str(phone), "+33612345678") with override_settings(PHONENUMBER_DEFAULT_FORMAT="INTERNATIONAL"): self.assertEqual(str(phone), "+33 6 12 34 56 78") with override_settings(PHONENUMBER_DEFAULT_FORMAT="NATIONAL"): self.assertEqual(str(phone), "06 12 34 56 78") with override_settings(PHONENUMBER_DEFAULT_FORMAT="RFC3966"): self.assertEqual(str(phone), "tel:+33-6-12-34-56-78") def test_phonenumber_extensions(self): for data in [ "+33612345678 extension 456", "+33612345678 ext. 456", "+33612345678,456", ]: with self.subTest(data): phone = PhoneNumber.from_string(data) self.assertEqual(phone.as_international, "+33 6 12 34 56 78 ext. 456") self.assertEqual(phone.as_rfc3966, "tel:+33-6-12-34-56-78;ext=456") self.assertEqual(phone.as_national, "06 12 34 56 78 ext. 456") def test_phonenumber_formatting_properties(self): phone = PhoneNumber.from_string("+33612345678") self.assertEqual(phone.as_e164, "+33612345678") self.assertEqual(phone.as_international, "+33 6 12 34 56 78") self.assertEqual(phone.as_national, "06 12 34 56 78") self.assertEqual(phone.as_rfc3966, "tel:+33-6-12-34-56-78") class PhoneNumberOrdering(SimpleTestCase): def test_ordering(self): phone1 = PhoneNumber.from_string("+33600000000") phone2 = PhoneNumber.from_string("+33600000001") self.assertLess(phone1, phone2) # Ordering is total. self.assertGreater(phone2, phone1) self.assertLessEqual(phone1, phone1) self.assertGreaterEqual(phone1, phone1) self.assertEqual(phone1, phone1) def test_ordering_with_phonenumbers(self): phone1 = PhoneNumber.from_string("+33600000000") phone2 = phonenumbers.parse("+33600000001") self.assertLess(phone1, phone2) def test_ordering_contains_None(self): phone1 = PhoneNumber.from_string("+33600000000") msg = "'<' not supported between instances of 'PhoneNumber' and 'NoneType'" for assertion in [ self.assertLess, self.assertLessEqual, self.assertGreater, self.assertGreaterEqual, ]: with self.subTest(assertion): with self.assertRaisesMessage(TypeError, msg): assertion(phone1, None) def test_ordering_with_invalid_value(self): phone1 = PhoneNumber.from_string("+33600000000") invalid = PhoneNumber.from_string("+1000000000") invalid_phonenumbers = phonenumbers.parse("+1000000000") for number in [invalid, invalid_phonenumbers]: with self.subTest(number): for p1, p2 in [[phone1, number], [number, phone1]]: with self.subTest([p1, p2]): with self.assertRaisesRegex( ValueError, r"^Invalid phone number: " ): self.assertLess(p1, p2) django-phonenumber-field-8.1.0/tests/test_serializers.py000066400000000000000000000121021477567660600235160ustar00rootroot00000000000000from django.test import SimpleTestCase, override_settings from rest_framework import renderers, serializers from phonenumber_field.phonenumber import PhoneNumber from phonenumber_field.serializerfields import PhoneNumberField from .models import OptionalPhoneNumber class PhoneNumberSerializerTest(SimpleTestCase): def test_blank_field(self): class PhoneNumberSerializer(serializers.ModelSerializer): class Meta: model = OptionalPhoneNumber fields = ["phone_number"] for data in [{}, {"phone": ""}]: with self.subTest(data): s = PhoneNumberSerializer(data=data) self.assertIs(s.is_valid(), True) self.assertEqual(s.data, {}) def test_int(self): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField() s = PhoneNumberSerializer(data={"phone": 1}) self.assertIs(s.is_valid(), False) def test_empty_required(self): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField() serializer = PhoneNumberSerializer(data={"phone": ""}) self.assertIs(serializer.is_valid(), False) self.assertEqual(serializer.validated_data, {}) def test_empty_optional(self): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField(allow_blank=True) serializer = PhoneNumberSerializer(data={"phone": ""}) self.assertIs(serializer.is_valid(), True) self.assertEqual(serializer.validated_data, {"phone": ""}) def test_e164_phone_number(self): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField() serializer = PhoneNumberSerializer(data={"phone": "+33612345678"}) self.assertIs(serializer.is_valid(), True) self.assertEqual(serializer.validated_data, {"phone": "+33612345678"}) self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber) def test_region(self): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField(region="FR") serializer = PhoneNumberSerializer(data={"phone": "0612345678"}) self.assertIs(serializer.is_valid(), True) self.assertEqual(serializer.validated_data, {"phone": "+33612345678"}) self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber) def test_region_invalid(self): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField(region="GB") serializer = PhoneNumberSerializer(data={"phone": "0612345678"}) self.assertIs(serializer.is_valid(), False) self.assertEqual(serializer.validated_data, {}) self.assertEqual(serializer.errors, {"phone": ["Enter a valid phone number."]}) @override_settings(PHONENUMBER_DEFAULT_REGION="FR") def test_region_from_settings(self): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField() serializer = PhoneNumberSerializer(data={"phone": "0612345678"}) self.assertIs(serializer.is_valid(), True) self.assertEqual(serializer.validated_data, {"phone": "+33612345678"}) self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber) @override_settings(PHONENUMBER_DEFAULT_REGION="GB") def test_region_kwarg_precedes_setting(self): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField(region="FR") serializer = PhoneNumberSerializer(data={"phone": "0612345678"}) self.assertIs(serializer.is_valid(), True) self.assertEqual(serializer.validated_data, {"phone": "+33612345678"}) self.assertIsInstance(serializer.validated_data["phone"], PhoneNumber) def test_invalid_region(self): with self.assertRaisesMessage( ValueError, "“INVALID” is not a valid region code. Choices are" ): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField(region="INVALID") def test_multiple_isvalid_calls(self): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField() serializer = PhoneNumberSerializer(data={"phone": "+33612345678"}) self.assertIs(serializer.is_valid(), True) self.assertIs(serializer.is_valid(), True) def test_serialization(self): class PhoneNumberSerializer(serializers.Serializer): phone = PhoneNumberField(region="FR") for fmt, expected in [ ("E164", b"+33612345678"), ("INTERNATIONAL", b"+33 6 12 34 56 78"), ("RFC3966", b"tel:+33-6-12-34-56-78"), ]: with override_settings(PHONENUMBER_DEFAULT_FORMAT=fmt), self.subTest(fmt): serializer = PhoneNumberSerializer(data={"phone": "0612345678"}) serializer.is_valid() self.assertEqual( b'{"phone":"%b"}' % expected, renderers.JSONRenderer().render(serializer.data), ) django-phonenumber-field-8.1.0/tests/test_widgets.py000066400000000000000000000051141477567660600226350ustar00rootroot00000000000000from django.test import SimpleTestCase, override_settings from phonenumber_field.phonenumber import PhoneNumber from phonenumber_field.widgets import RegionalPhoneNumberWidget class RegionalPhoneNumberWidgetTest(SimpleTestCase): @override_settings(PHONENUMBER_DEFAULT_FORMAT="INTERNATIONAL") def test_fallback_widget_switches_between_national_and_international(self): region = "GB" number_string = "01606 751 78" number = PhoneNumber.from_string(number_string, region=region) gb_widget = RegionalPhoneNumberWidget() gb_widget.region = "GB" de_widget = RegionalPhoneNumberWidget() de_widget.region = "DE" self.assertHTMLEqual( gb_widget.render("number", number), '', ) self.assertHTMLEqual( de_widget.render("number", number), '', ) # If there's been a validation error, the value should be included verbatim self.assertHTMLEqual( gb_widget.render("number", "error"), '', ) def test_fallback_defaults_to_phonenumber_default_format(self): region = "GB" number_string = "01606 751 78" number = PhoneNumber.from_string(number_string, region=region) widget = RegionalPhoneNumberWidget(region="FR") for fmt, expected in [ ("INTERNATIONAL", "+44 1606 75178"), ("E164", "+44160675178"), ("RFC3966", "tel:+44-1606-75178"), ]: with self.subTest(fmt): with override_settings(PHONENUMBER_DEFAULT_FORMAT=fmt): self.assertHTMLEqual( widget.render("number", number), f'', ) def test_no_region(self): number_string = "+33612345678" number = PhoneNumber.from_string(number_string) widget = RegionalPhoneNumberWidget() for fmt, expected in [ ("INTERNATIONAL", "+33 6 12 34 56 78"), ("E164", "+33612345678"), ("RFC3966", "tel:+33-6-12-34-56-78"), ]: with self.subTest(fmt): with override_settings(PHONENUMBER_DEFAULT_FORMAT=fmt): self.assertHTMLEqual( widget.render("number", number), f'', ) django-phonenumber-field-8.1.0/tests/tests.py000066400000000000000000000642631477567660600213040ustar00rootroot00000000000000import django import phonenumbers from django import forms from django.core import checks from django.db.models import Model from django.test import SimpleTestCase, TestCase, override_settings from django.utils.encoding import force_str from phonenumber_field import formfields, modelfields from phonenumber_field.phonenumber import PhoneNumber, to_python from . import models from .forms import ARPhoneNumberForm, CustomPhoneNumberFormField, PhoneNumberForm ALGERIAN_PHONE_NUMBER = "+213799136332" def phone_transform(obj): return (obj.pk, obj.name, obj.phone) class PhoneNumberFieldTestCase(TestCase): test_number_1 = "+4930123456" equal_number_strings = ["+44 113 8921113", "+441138921113", "tel:+44-113-892-1113"] local_numbers = [("GB", "01606 751 78"), ("DE", "0176/96842671")] storage_numbers = { "E164": ["+44 113 8921113", "+441138921113"], "RFC3966": ["+44 113 8921113", "tel:+44-113-892-1113"], "INTERNATIONAL": ["+44 113 8921113", "+44 113 892 1113"], } invalid_numbers = ["+44 113 892111"] def test_str_for_valid_number(self): self.assertEqual( str(PhoneNumber.from_string(self.test_number_1)), self.test_number_1, ) def test_str_for_invalid_number(self): self.assertEqual( str(to_python("invalid")), "invalid", ) def test_repr_for_invalid_number(self): self.assertEqual( repr(to_python("invalid")), "InvalidPhoneNumber(raw_input=invalid)", ) def test_repr_for_valid_number(self): self.assertTrue( repr(PhoneNumber.from_string(self.test_number_1)).startswith( "PhoneNumber(" ), ) def test_valid_numbers_are_valid(self): numbers = [ PhoneNumber.from_string(number_string) for number_string in self.equal_number_strings ] self.assertTrue(all(number.is_valid() for number in numbers)) numbers = [ PhoneNumber.from_string(number_string, region=region) for region, number_string in self.local_numbers ] self.assertTrue(all(number.is_valid() for number in numbers)) def test_invalid_numbers_are_invalid(self): numbers = [ PhoneNumber.from_string(number_string) for number_string in self.invalid_numbers ] self.assertTrue(all(not number.is_valid() for number in numbers)) def test_same_invalid_numbers_are_equal(self): self.assertEqual(PhoneNumber(raw_input="invalid"), "invalid") def test_objects_with_same_number_are_equal(self): numbers = [ models.MandatoryPhoneNumber.objects.create( phone_number=number_string ).phone_number for number_string in self.equal_number_strings ] self.assertTrue( all( phonenumbers.is_number_match(n, numbers[0]) == phonenumbers.MatchType.EXACT_MATCH for n in numbers ) ) for number in numbers: self.assertEqual(number, numbers[0]) for number_string in self.equal_number_strings: self.assertEqual(number, number_string) def test_same_number_has_same_hash(self): numbers = [ PhoneNumber.from_string(number_string) for number_string in self.equal_number_strings ] numbers_set = set(numbers) self.assertEqual(len(numbers_set), 1) for number in numbers: self.assertIn(number, numbers_set) self.assertNotIn(self.test_number_1, numbers_set) def test_eq_and_ne(self): number_1 = "+411111111" number_2 = "+412222222" one = PhoneNumber.from_string("+411111111") two = PhoneNumber.from_string("+412222222") self.assertNotEqual(one, two) self.assertNotEqual(one, number_2) self.assertNotEqual(number_2, one) self.assertEqual(one, number_1) self.assertEqual(number_1, one) def test_blank_field_returns_empty_string(self): model = models.OptionalPhoneNumber() self.assertEqual(model.phone_number, "") model.phone_number = "+49 176 96842671" self.assertIsInstance(model.phone_number, PhoneNumber) def test_null_field_returns_none(self): model = models.NullablePhoneNumber() self.assertIsNone(model.phone_number) model.phone_number = self.test_number_1 self.assertIsInstance(model.phone_number, PhoneNumber) model.phone_number = phonenumbers.parse(self.test_number_1, keep_raw_input=True) self.assertIsInstance(model.phone_number, PhoneNumber) def test_can_assign_string_phone_number(self): opt_phone = models.OptionalPhoneNumber() opt_phone.phone_number = self.test_number_1 self.assertIsInstance(opt_phone.phone_number, PhoneNumber) self.assertEqual(opt_phone.phone_number.as_e164, self.test_number_1) opt_phone.full_clean() opt_phone.save() self.assertIsInstance(opt_phone.phone_number, PhoneNumber) self.assertEqual(opt_phone.phone_number.as_e164, self.test_number_1) opt_phone_db = models.OptionalPhoneNumber.objects.get(id=opt_phone.id) self.assertIsInstance(opt_phone_db.phone_number, PhoneNumber) self.assertEqual(opt_phone_db.phone_number.as_e164, self.test_number_1) def test_can_assign_phonenumber(self): """ Tests assignment phonenumbers.PhoneNumber to field """ opt_phone = models.OptionalPhoneNumber() opt_phone.phone_number = phonenumbers.parse( self.test_number_1, keep_raw_input=True ) self.assertIsInstance(opt_phone.phone_number, PhoneNumber) self.assertEqual(opt_phone.phone_number.as_e164, self.test_number_1) opt_phone.full_clean() opt_phone.save() self.assertIsInstance(opt_phone.phone_number, PhoneNumber) self.assertEqual(opt_phone.phone_number.as_e164, self.test_number_1) opt_phone_db = models.OptionalPhoneNumber.objects.get(id=opt_phone.id) self.assertIsInstance(opt_phone_db.phone_number, PhoneNumber) self.assertEqual(opt_phone_db.phone_number.as_e164, self.test_number_1) def test_raise_on_invalid_values(self): msg = "Can't convert int to PhoneNumber." with self.assertRaisesMessage(TypeError, msg): to_python(42) def test_create_with_int(self): msg = "Can't convert int to PhoneNumber." with self.assertRaisesMessage(TypeError, msg): models.MandatoryPhoneNumber.objects.create( phone_number=int(self.test_number_1) ) def _test_storage_formats(self): """ Aggregate of tests to perform for db storage formats """ self.test_objects_with_same_number_are_equal() self.test_blank_field_returns_empty_string() self.test_null_field_returns_none() self.test_can_assign_string_phone_number() @override_settings(PHONENUMBER_DEFAULT_REGION="DE") def test_storage_formats(self): """ Perform aggregate tests for all db storage formats """ for frmt in PhoneNumber.format_map: with override_settings(PHONENUMBER_DB_FORMAT=frmt): self._test_storage_formats() def test_prep_value(self): """ Tests correct db storage value against different setting of PHONENUMBER_DB_FORMAT Required output format is set as string constant to guarantee consistent database storage values """ number = modelfields.PhoneNumberField() for frmt in ["E164", "RFC3966", "INTERNATIONAL"]: with override_settings(PHONENUMBER_DB_FORMAT=frmt): self.assertEqual( number.get_prep_value(to_python(self.storage_numbers[frmt][0])), self.storage_numbers[frmt][1], ) def test_phone_number_form_empty_value(self): form = PhoneNumberForm({"phone_number": ""}) self.assertTrue(form.is_valid()) self.assertDictEqual({"phone_number": None}, form.cleaned_data) def test_defer_phone_number_field(self): m = models.MandatoryPhoneNumber.objects.create(phone_number=self.test_number_1) m = models.MandatoryPhoneNumber.objects.defer("phone_number").get(pk=m.pk) self.assertEqual(m.phone_number, self.test_number_1) def test_filtering_by_invalid_number_does_not_raise_value_error(self): models.NullablePhoneNumber.objects.filter(phone_number="123") def test_filter_by_invalid_type_int_raises_value_error(self): msg = "Can't convert int to PhoneNumber" with self.assertRaisesMessage(TypeError, msg): models.NullablePhoneNumber.objects.filter(phone_number=123).exists() def test_filter_by_invalid_number_does_not_match_empty_or_none(self): models.NullablePhoneNumber.objects.create(phone_number="") models.NullablePhoneNumber.objects.create(phone_number=None) self.assertFalse( models.NullablePhoneNumber.objects.filter(phone_number="123").exists() ) def test_filter_by_invalid_number_does_not_match_partial(self): models.NullablePhoneNumber.objects.create(phone_number="+4930123456") self.assertFalse( models.NullablePhoneNumber.objects.filter(phone_number="123").exists() ) def test_filter_by_partial_number_of_valid_number_works(self): models.NullablePhoneNumber.objects.create(phone_number="+4923399999") models.NullablePhoneNumber.objects.create(phone_number="+4930123456") self.assertEqual( models.NullablePhoneNumber.objects.filter( phone_number__contains="9999" ).count(), 1, ) self.assertEqual( models.NullablePhoneNumber.objects.filter( phone_number__contains="123" ).count(), 1, ) def test_values_list(self): num0 = "+33600000000" num1 = "+33611111111" models.MandatoryPhoneNumber.objects.bulk_create( [ models.MandatoryPhoneNumber(phone_number=num0), models.MandatoryPhoneNumber(phone_number=num1), ] ) number0, number1 = models.MandatoryPhoneNumber.objects.order_by( "phone_number" ).values_list("phone_number", flat=True) self.assertIsInstance(number0, PhoneNumber) self.assertEqual(to_python(num0), number0) self.assertIsInstance(number1, PhoneNumber) self.assertEqual(to_python(num1), number1) def test_values_with_null(self): num0 = "+33600000000" models.NullablePhoneNumber.objects.bulk_create( [ models.NullablePhoneNumber(phone_number=num0), models.NullablePhoneNumber(phone_number=""), models.NullablePhoneNumber(phone_number=None), ] ) number0, number1, number2 = models.NullablePhoneNumber.objects.order_by( "pk" ).values_list("phone_number", flat=True) self.assertIsInstance(number0, PhoneNumber) self.assertEqual(to_python(num0), number0) self.assertIsInstance(number1, str) self.assertEqual(number1, "") self.assertIsNone(number2) class PhoneNumberFieldAppTest(TestCase): def test_save_field_to_database(self): """Basic Field Test""" tm = models.TestModel() tm.phone = "+41 52 424 2424" tm.full_clean() tm.save() pk = tm.id tm = models.TestModel.objects.get(pk=pk) self.assertIsInstance(tm.phone, PhoneNumber) self.assertQuerySetEqual( models.TestModel.objects.all(), [(tm.pk, "", "+41524242424")], transform=phone_transform, ) def test_create_with_invalid_number_works(self): obj = models.TestModel.objects.create(phone="invalid") self.assertEqual(obj.phone.raw_input, "invalid") obj = models.TestModel.objects.get(id=obj.id) self.assertEqual(obj.phone.raw_input, "invalid") def test_save_invalid_number_works(self): tm = models.TestModel.objects.create(phone="+1 604-333-4444") tm.phone = "invalid" tm.save() tm.refresh_from_db() self.assertEqual(tm.phone.raw_input, "invalid") def test_save_change_to_invalid_number_works(self): tm = models.TestModel.objects.create(phone="+1 604-333-4444") tm.phone = "invalid" tm.save(update_fields=["phone"]) self.assertEqual(tm.phone.raw_input, "invalid") tm.refresh_from_db() self.assertEqual(tm.phone.raw_input, "invalid") def test_queryset_update_to_invalid_number_works(self): tm = models.TestModel.objects.create(phone="+1 604-333-4444") models.TestModel.objects.filter(id=tm.id).update(phone="invalid") tm.refresh_from_db() self.assertEqual(tm.phone.raw_input, "invalid") def test_save_blank_phone_to_database(self): """Field Test for when Blank""" tm = models.TestModelPhoneB() tm.save() pk = tm.id tm = models.TestModelPhoneB.objects.get(pk=pk) self.assertQuerySetEqual( models.TestModelPhoneB.objects.all(), [(tm.pk, "", "")], transform=phone_transform, ) def __test_nullable_field_helper(self, TestModel): """Helper method for the next four tests.""" tm = TestModel() tm.save() pk = tm.id tm = TestModel.objects.get(pk=pk) self.assertIsNone(tm.phone) self.assertQuerySetEqual( TestModel.objects.all(), [(tm.pk, "", None)], transform=phone_transform ) # ensure that null values do not cause uniqueness conflicts TestModel.objects.create() self.assertEqual(TestModel.objects.count(), 2) def test_save_unique_null_phone_to_database(self): """Field Test for when Null & Unique""" self.__test_nullable_field_helper(models.TestModelPhoneNU) def test_save_unique_null_blank_phone_to_database(self): """Field Test for when Blank, Null & Unique""" self.__test_nullable_field_helper(models.TestModelPhoneBNU) def test_save_unique_null_none_phone_to_database(self): """Field Test for when No Default, Null & Unique""" self.__test_nullable_field_helper(models.TestModelPhoneNDNU) def test_save_unique_null_blank_none_phone_to_database(self): """Field Test for when Blank, No Default, Null & Unique""" self.__test_nullable_field_helper(models.TestModelPhoneBNDNU) def __test_nullable_default_field_helper(self, TestModel): """Helper method for the next two tests.""" tm = TestModel() tm.save() pk = tm.id tm = TestModel.objects.get(pk=pk) self.assertQuerySetEqual( TestModel.objects.all(), [(tm.pk, "", "+41524242424")], transform=phone_transform, ) def test_save_unique_null_default_phone_to_database(self): """Field Test for when Default, Null & Unique""" self.__test_nullable_default_field_helper(models.TestModelPhoneDNU) def test_save_unique_null_blank_default_phone_to_database(self): """Field Test for when Blank, Default, Null & Unique""" self.__test_nullable_default_field_helper(models.TestModelPhoneBDNU) def __test_nullable_empty_default_field_helper(self, TestModel): """Helper method for the next two tests.""" tm = TestModel() tm.save() pk = tm.id tm = TestModel.objects.get(pk=pk) self.assertQuerySetEqual( TestModel.objects.all(), [(tm.pk, "", "")], transform=phone_transform ) def test_save_unique_null_default_empty_phone_to_database(self): """Field Test for when Empty Default, Null & Unique""" self.__test_nullable_empty_default_field_helper(models.TestModelPhoneEDNU) def test_save_unique_null_blank_default_empty_phone_to_database(self): """Field Test for when Blank, Empty Default, Null & Unique""" self.__test_nullable_empty_default_field_helper(models.TestModelPhoneBEDNU) def test_model_attribute_can_be_accessed_on_class(self): self.assertIsInstance(models.TestModel.phone, modelfields.PhoneNumberDescriptor) class RegionPhoneNumberFormFieldTest(SimpleTestCase): def test_regional_phone(self): class PhoneNumberForm(forms.Form): canadian_number = formfields.PhoneNumberField(region="CA") french_number = formfields.PhoneNumberField(region="FR") form = PhoneNumberForm( {"canadian_number": "604-686-2877", "french_number": "06 12 34 56 78"} ) self.assertIs(form.is_valid(), True) self.assertEqual("+16046862877", form.cleaned_data["canadian_number"]) self.assertEqual("+33612345678", form.cleaned_data["french_number"]) def test_invalid_region(self): with self.assertRaises(ValueError) as cm: formfields.PhoneNumberField(region="invalid") self.assertTrue( force_str(cm.exception).startswith("“invalid” is not a valid region code.") ) def test_error_message_nationalize_example(self): class PhoneNumberForm(forms.Form): number = formfields.PhoneNumberField(region="CA") form = PhoneNumberForm({"number": "invalid"}) self.assertIs(form.is_valid(), False) self.assertEqual( form.errors, { "number": [ "Enter a valid phone number (e.g. (506) 234-5678) " "or a number with an international call prefix." ] }, ) @override_settings(PHONENUMBER_DEFAULT_REGION="FR") def test_formfield_uses_default_region(self): class PhoneForm(forms.Form): phone_number = formfields.PhoneNumberField() form = PhoneForm() self.assertEqual("FR", form.fields["phone_number"].region) class RegionPhoneNumberModelFieldTest(TestCase): def test_uses_region(self): m = models.FrenchPhoneOwner(cell_number="06 12 34 56 78") self.assertEqual(phonenumbers.parse("+33612345678"), m.cell_number) def test_accepts_international_numbers(self): num = "+16042234567" m = models.FrenchPhoneOwner(cell_number=num) self.assertEqual(phonenumbers.parse(num), m.cell_number) def test_formfield_uses_region(self): class FrenchPhoneForm(forms.ModelForm): class Meta: model = models.FrenchPhoneOwner fields = ["cell_number"] form = FrenchPhoneForm() self.assertEqual("FR", form.fields["cell_number"].region) def test_deconstruct_region(self): phone_field = modelfields.PhoneNumberField(region="CH") _name, path, args, kwargs = phone_field.deconstruct() self.assertEqual("phonenumber_field.modelfields.PhoneNumberField", path) self.assertEqual([], args) self.assertEqual({"max_length": 128, "region": "CH"}, kwargs) def test_deconstruct_no_region(self): phone_field = modelfields.PhoneNumberField() _name, path, args, kwargs = phone_field.deconstruct() self.assertEqual("phonenumber_field.modelfields.PhoneNumberField", path) self.assertEqual([], args) self.assertEqual({"max_length": 128, "region": None}, kwargs) def test_check_region(self): class InvalidRegionModel(Model): phone_field = modelfields.PhoneNumberField(region="invalid") errors = InvalidRegionModel.check() self.assertEqual(1, len(errors)) error = errors[0] self.assertIsInstance(error, checks.Error) self.assertTrue(error.msg.startswith("“invalid” is not a valid region code.")) self.assertEqual(error.obj, InvalidRegionModel._meta.get_field("phone_field")) def test_override_form_field(self): phone_number = models.CustomPhoneNumber() model_field = phone_number._meta.get_field("phone_number") self.assertIsInstance(model_field.formfield(), CustomPhoneNumberFormField) @override_settings(PHONENUMBER_DEFAULT_REGION="FR") def test_uses_default_region(self): m = models.MandatoryPhoneNumber.objects.create(phone_number="06 12 34 56 78") self.assertEqual(phonenumbers.parse("+33612345678"), m.phone_number) @override_settings(PHONENUMBER_DEFAULT_REGION="FR") def test_formfield_uses_default_region(self): class PhoneForm(forms.ModelForm): class Meta: model = models.MandatoryPhoneNumber fields = ["phone_number"] form = PhoneForm() self.assertEqual("FR", form.fields["phone_number"].region) @override_settings(PHONENUMBER_DEFAULT_REGION="FR") def test_desconstruct_does_not_use_default_region(self): field = modelfields.PhoneNumberField() _name, path, args, kwargs = field.deconstruct() self.assertEqual("phonenumber_field.modelfields.PhoneNumberField", path) self.assertEqual([], args) self.assertEqual({"max_length": 128, "region": None}, kwargs) @override_settings(PHONENUMBER_DEFAULT_REGION="FR") def test_region_uses_default_region(self): field = modelfields.PhoneNumberField() self.assertEqual("FR", field.region) def test_region_none(self): field = modelfields.PhoneNumberField() self.assertIsNone(field.region) def test_algerian_phone_number_in_model(self): m = models.MandatoryPhoneNumber.objects.create( phone_number=ALGERIAN_PHONE_NUMBER ) self.assertEqual(phonenumbers.parse(ALGERIAN_PHONE_NUMBER), m.phone_number) self.assertEqual(ALGERIAN_PHONE_NUMBER, m.phone_number) def test_region_field_empty(self): obj = models.TestModelRegionAR.objects.create() form = ARPhoneNumberForm(instance=obj) self.assertHTMLEqual( form.as_p(), "

" '' "' "

", ) def test_region_field_renders_international_as_E164(self): form = ARPhoneNumberForm({"phone": "+32468547825"}) self.assertTrue(form.is_valid()) self.assertHTMLEqual( form.as_p(), "

" '' "' "

", ) def test_region_field_renders_international_as_E164_from_instance(self): obj = models.TestModelRegionAR.objects.create(phone="+32468547825") form = ARPhoneNumberForm(instance=obj) self.assertHTMLEqual( form.as_p(), "

" ' ' "' "

", ) def test_region_field_renders_national_numbers_as_national(self): form = ARPhoneNumberForm({"phone": "01145482368"}) self.assertTrue(form.is_valid()) self.assertHTMLEqual( form.as_p(), "

" '' "' "

", ) def test_region_field_renders_national_numbers_as_national_from_instance(self): obj = models.TestModelRegionAR.objects.create(phone="01145482368") form = ARPhoneNumberForm(instance=obj) self.assertHTMLEqual( form.as_p(), "

" ' ' "' "

", ) def test_region_field_renders_national_numbers_from_instance_and_form_data(self): obj = models.TestModelRegionAR.objects.create(phone="01145482368") form = ARPhoneNumberForm({"phone": "011 4548-2368"}, instance=obj) self.assertTrue(form.is_valid()) self.assertHTMLEqual( form.as_p(), "

" ' ' "' "

", ) def test_region_field_renders_invalid_numbers(self): form = ARPhoneNumberForm({"phone": "abcdef"}) self.assertFalse(form.is_valid()) if django.VERSION >= (5, 2): self.assertHTMLEqual( form.as_p(), '
    ' "
  • Enter a valid phone number (e.g. 011 2345-6789) " "or a number with an international call prefix.
  • " "
" "

" '' "' "

", ) else: aria_invalid = "" if django.VERSION[0] < 5 else 'aria-invalid="true" ' self.assertHTMLEqual( form.as_p(), '
    ' "
  • Enter a valid phone number (e.g. 011 2345-6789) " "or a number with an international call prefix.
  • " "
" "

" '' "' "

", ) django-phonenumber-field-8.1.0/tox.ini000066400000000000000000000024121477567660600177250ustar00rootroot00000000000000[tox] envlist = ruff dj42 dj50 dj51 dj52 djmain mypy isolated_build = true minversion = 1.9 [gh] python = 3.9 = dj42 3.10 = dj{42,50,51,52} 3.11 = dj{42,50,51,52} 3.12 = dj{42,50,51,52,main} 3.13 = dj{42,50,51,52,main} 3.14 = djmain [testenv] deps = babel coverage dj42: Django>=4.2,<4.3 dj50: Django>=5.0b1,<5.1 dj51: Django>=5.1b1,<5.2 dj52: Django>=5.2a1,<5.3 djmain: https://github.com/django/django/archive/main.tar.gz djangorestframework extras = phonenumberslite commands = coverage run --source phonenumber_field -m django test --settings=tests.settings {posargs} coverage xml -o coverage-reports/coverage.xml coverage html -d coverage-reports/html coverage report [testenv:ruff] commands = ruff check deps = ruff skip_install = true [testenv:doctest] deps = beautifulsoup4 django djangorestframework Sphinx sphinx-rtd-theme changedir = docs/ allowlist_externals=make commands = make doctest [testenv:mypy] commands = mypy phonenumber_field mypy tests --no-check-untyped-defs deps = typing_extensions Django phonenumbers djangorestframework django-stubs[compatible-mypy] djangorestframework-stubs types-babel