diff --git a/.github/ISSUE_TEMPLATE/01-feature_request.yaml b/.github/ISSUE_TEMPLATE/01-feature_request.yaml index f0138a22a..cb39ae9be 100644 --- a/.github/ISSUE_TEMPLATE/01-feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/01-feature_request.yaml @@ -14,7 +14,7 @@ body: attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v4.1.4 + placeholder: v4.1.11 validations: required: true - type: dropdown @@ -36,9 +36,8 @@ body: options: - I volunteer to perform this work (if approved) - I'm a NetBox Labs customer - - This is a very minor change - N/A - default: 3 + default: 2 validations: required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/02-bug_report.yaml b/.github/ISSUE_TEMPLATE/02-bug_report.yaml index a8a2cc45b..e42ff3045 100644 --- a/.github/ISSUE_TEMPLATE/02-bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/02-bug_report.yaml @@ -31,16 +31,15 @@ body: options: - I volunteer to perform this work (if approved) - I'm a NetBox Labs customer - - This is preventing me from using NetBox - N/A - default: 3 + default: 2 validations: required: true - type: input attributes: label: NetBox Version description: What version of NetBox are you currently running? - placeholder: v4.1.4 + placeholder: v4.1.11 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 2ad52023e..efbf38932 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -7,6 +7,9 @@ contact_links: - name: ❓ Discussion url: https://github.com/netbox-community/netbox/discussions about: "If you're just looking for help, try starting a discussion instead." + - name: 👔 Professional Support + url: https://netboxlabs.com/netbox-enterprise/ + about: "Professional support is available for NetBox Enterprise or Cloud." - name: 🌎 Correct a Translation url: https://explore.transifex.com/netbox-community/netbox/ about: "Spot an incorrect translation? You can propose a fix on Transifex." diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d77da90e3..aab8bc34f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,11 @@ on: permissions: contents: read +# Add concurrency group to control job running +concurrency: + group: ${{ github.event_name }}-${{ github.ref }}-${{ github.actor }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/update-translation-strings.yml b/.github/workflows/update-translation-strings.yml index bcd68c887..e78cd4296 100644 --- a/.github/workflows/update-translation-strings.yml +++ b/.github/workflows/update-translation-strings.yml @@ -18,8 +18,17 @@ jobs: NETBOX_CONFIGURATION: netbox.configuration_testing steps: + - name: Create app token + uses: actions/create-github-app-token@v1 + id: app-token + with: + app-id: 1076524 + private-key: ${{ secrets.HOUSEKEEPING_SECRET_KEY }} + - name: Check out repo uses: actions/checkout@v4 + with: + token: ${{ steps.app-token.outputs.token }} - name: Set up Python uses: actions/setup-python@v5 diff --git a/.tx/config b/.tx/config new file mode 100755 index 000000000..342331d4e --- /dev/null +++ b/.tx/config @@ -0,0 +1,12 @@ +[main] +host = https://app.transifex.com + +[o:netbox-community:p:netbox:r:9cbf4fcf95b3d92e4ebbf1a5e5d1caee] +file_filter = netbox/translations//LC_MESSAGES/django.po +source_file = netbox/translations/en/LC_MESSAGES/django.po +type = PO +minimum_perc = 0 +resource_name = django.po +replace_edited_strings = false +keep_translations = false + diff --git a/README.md b/README.md index 0c793b8a4..e3829c2cc 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@
- NetBox logo + NetBox logo

The cornerstone of every automated network

Latest release License diff --git a/base_requirements.txt b/base_requirements.txt index 76955a6e1..169f4196d 100644 --- a/base_requirements.txt +++ b/base_requirements.txt @@ -1,6 +1,6 @@ # The Python web framework on which NetBox is built # https://docs.djangoproject.com/en/stable/releases/ -Django<5.1 +Django<5.2 # Django middleware which permits cross-domain API requests # https://github.com/adamchainz/django-cors-headers/blob/main/CHANGELOG.rst @@ -101,7 +101,7 @@ netaddr nh3 # Fork of PIL (Python Imaging Library) for image processing -# https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst +# https://github.com/python-pillow/Pillow/releases Pillow # PostgreSQL database adapter for Python @@ -116,6 +116,10 @@ PyYAML # https://github.com/psf/requests/blob/main/HISTORY.md requests +# rq +# https://github.com/rq/rq/blob/master/CHANGES.md +rq + # Social authentication framework # https://github.com/python-social-auth/social-core/blob/master/CHANGELOG.md social-auth-core diff --git a/contrib/generated_schema.json b/contrib/generated_schema.json index 56ddee50e..639f0df8d 100644 --- a/contrib/generated_schema.json +++ b/contrib/generated_schema.json @@ -329,6 +329,7 @@ "100base-tx", "100base-t1", "1000base-t", + "1000base-lx", "1000base-tx", "2.5gbase-t", "5gbase-t", diff --git a/docs/administration/authentication/google.md b/docs/administration/authentication/google.md new file mode 100644 index 000000000..456f3a457 --- /dev/null +++ b/docs/administration/authentication/google.md @@ -0,0 +1,52 @@ +# Google + +This guide explains how to configure single sign-on (SSO) support for NetBox using [Google OAuth2](https://developers.google.com/identity/protocols/oauth2/web-server) as an authentication backend. + +## Google OAuth2 Configuration + +1. Log into [console.cloud.google.com](https://console.cloud.google.com/). +2. Create new project for NetBox. +3. Under "APIs and Services" click "OAuth consent screen" and enter the required information. +4. Under "Credentials," click "Create Credentials" and select "OAuth 2.0 Client ID." Select type "Web application." + - "Authorized JavaScript origins" should follow the format `http[s]://[:]` + - "Authorized redirect URIs" should follow the format `http[s]://[:]/oauth/complete/google-oauth2/` +5. Copy the "Client ID" and "Client Secret" values somewhere convenient. + +!!! note + Google requires the NetBox hostname to use a public top-level-domain (e.g. `.com`, `.net`). The use of IP addresses is not permitted (except `127.0.0.1`). + +For more information, consult [Google's documentation](https://developers.google.com/identity/protocols/oauth2/web-server#prerequisites). + +## NetBox Configuration + +### 1. Enter configuration parameters + +Enter the following configuration parameters in `configuration.py`, substituting your own values: + +```python +REMOTE_AUTH_BACKEND = 'social_core.backends.google.GoogleOAuth2' +SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '{CLIENT_ID}' +SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '{CLIENT_SECRET}' +``` + +### 2. Restart NetBox + +Restart the NetBox services so that the new configuration takes effect. This is typically done with the command below: + +```no-highlight +sudo systemctl restart netbox +``` + +## Testing + +Log out of NetBox if already authenticated, and click the "Log In" button at top right. You should see the normal login form as well as an option to authenticate using Google. Click that link. + +![NetBox Google login form](../../media/authentication/netbox_google_login.png) + +You should be redirected to Google's authentication portal. Enter the username/email and password of your test account to continue. You may also be prompted to grant this application access to your account. + +![NetBox Google login form](../../media/authentication/google_login_portal.png) + +If successful, you will be redirected back to the NetBox UI, and will be logged in as the Google user. You can verify this by navigating to your profile (using the button at top right). + +This user account has been replicated locally to NetBox, and can now be assigned groups and permissions. diff --git a/docs/administration/authentication/microsoft-entra-id.md b/docs/administration/authentication/microsoft-entra-id.md index 3451c656f..b44499fbe 100644 --- a/docs/administration/authentication/microsoft-entra-id.md +++ b/docs/administration/authentication/microsoft-entra-id.md @@ -16,7 +16,7 @@ Under the Azure Active Directory dashboard, navigate to **Add > App registration Enter a name for the registration (e.g. "NetBox") and ensure that the "single tenant" option is selected. -Under "Redirect URI", select "Web" for the platform and enter the path to your NetBox installation, ending with `/oauth/complete/entraid-oauth2/`. Note that this URI **must** begin with `https://` unless you are referencing localhost (for development purposes). +Under "Redirect URI", select "Web" for the platform and enter the path to your NetBox installation, ending with `/oauth/complete/azuread-oauth2/`. Note that this URI **must** begin with `https://` unless you are referencing localhost (for development purposes). ![App registration parameters](../../media/authentication/azure_ad_app_registration.png) diff --git a/docs/configuration/miscellaneous.md b/docs/configuration/miscellaneous.md index 576eb8739..c14c0ac77 100644 --- a/docs/configuration/miscellaneous.md +++ b/docs/configuration/miscellaneous.md @@ -106,6 +106,16 @@ By default, NetBox will prevent the creation of duplicate prefixes and IP addres --- +## EVENTS_PIPELINE + +!!! info "This parameter was introduced in NetBox v4.2." + +Default: `['extras.events.process_event_queue',]` + +NetBox will call dotted paths to the functions listed here for events (create, update, delete) on models as well as when custom EventRules are fired. + +--- + ## FILE_UPLOAD_MAX_MEMORY_SIZE Default: `2621440` (2.5 MB) diff --git a/docs/configuration/system.md b/docs/configuration/system.md index 25c724bc9..af3a6f5e6 100644 --- a/docs/configuration/system.md +++ b/docs/configuration/system.md @@ -89,8 +89,6 @@ addresses (and [`DEBUG`](./development.md#debug) is true). ## ISOLATED_DEPLOYMENT -!!! info "This feature was introduced in NetBox v4.1." - Default: False Set this configuration parameter to True for NetBox deployments which do not have Internet access. This will disable miscellaneous functionality which depends on access to the Internet. diff --git a/docs/customization/custom-scripts.md b/docs/customization/custom-scripts.md index 3fa6491d2..1051b31f6 100644 --- a/docs/customization/custom-scripts.md +++ b/docs/customization/custom-scripts.md @@ -72,6 +72,9 @@ script_order = (MyCustomScript, AnotherCustomScript) Script attributes are defined under a class named `Meta` within the script. These are optional, but encouraged. +!!! warning + These are also defined and used as properties on the base custom script class, so don't use the same names as variables or override them in your custom script. + ### `name` This is the human-friendly names of your script. If omitted, the class name will be used. diff --git a/docs/development/adding-models.md b/docs/development/adding-models.md index f3aa9cfcc..0bf020662 100644 --- a/docs/development/adding-models.md +++ b/docs/development/adding-models.md @@ -8,7 +8,7 @@ Each model should define, at a minimum: * A `Meta` class specifying a deterministic ordering (if ordered by fields other than the primary ID) * A `__str__()` method returning a user-friendly string representation of the instance -* A `get_absolute_url()` method returning an instance's direct URL (using `reverse()`) +* A `get_absolute_url()` method if necessary; a standard version of the method is defined in the `NetBoxFeatureSet` base class, but you will need to provide your own (returning an instance's direct URL using `reverse()`) if not subclassing that base class ## 2. Define field choices @@ -78,6 +78,8 @@ Create the following for each model: Create a GraphQL object type for the model in `graphql/types.py` by subclassing the appropriate class from `netbox.graphql.types`. +**Note:** GraphQL unit tests may fail citing null values on a non-nullable field if related objects are prefetched. You may need to fix this by setting the type annotation to be `= strawberry_django.field(select_related=["policy"])` or similar. + Also extend the schema class defined in `graphql/schema.py` with the individual object and object list fields per the established convention. ## 14. Add tests diff --git a/docs/development/application-registry.md b/docs/development/application-registry.md index 570563431..fc96bfd76 100644 --- a/docs/development/application-registry.md +++ b/docs/development/application-registry.md @@ -49,6 +49,10 @@ This key lists all models which have been registered in NetBox which are not des This store maintains all registered items for plugins, such as navigation menus, template extensions, etc. +### `request_processors` + +A list of context managers to invoke when processing a request e.g. in middleware or when executing a background job. Request processors can be registered with the `@register_request_processor` decorator. + ### `search` A dictionary mapping each model (identified by its app and label) to its search index class, if one has been registered for it. diff --git a/docs/development/release-checklist.md b/docs/development/release-checklist.md index 7c8c96f39..4e5fdeca8 100644 --- a/docs/development/release-checklist.md +++ b/docs/development/release-checklist.md @@ -90,7 +90,20 @@ This will automatically update the schema file at `contrib/generated_schema.json ### Update & Compile Translations -Updated language translations should be pulled from [Transifex](https://app.transifex.com/netbox-community/netbox/dashboard/) and re-compiled for each new release. Follow the documented process for [updating translated strings](./translations.md#updating-translated-strings) to do this. +Updated language translations should be pulled from [Transifex](https://app.transifex.com/netbox-community/netbox/dashboard/) and re-compiled for each new release. First, retrieve any updated translation files using the Transifex CLI client: + +```no-highlight +tx pull +``` + +Then, compile these portable (`.po`) files for use in the application: + +```no-highlight +./manage.py compilemessages +``` + +!!! tip + Consult the translation documentation for more detail on [updating translated strings](./translations.md#updating-translated-strings) if you've not set up the Transifex client already. ### Update Version and Changelog diff --git a/docs/development/style-guide.md b/docs/development/style-guide.md index 0d4caf395..9d6630de0 100644 --- a/docs/development/style-guide.md +++ b/docs/development/style-guide.md @@ -76,4 +76,4 @@ When adding a new dependency, a short description of the package and the URL of * When referring to NetBox in writing, use the proper form "NetBox," with the letters N and B capitalized. The lowercase form "netbox" should be used in code, filenames, etc. but never "Netbox" or any other deviation. -* There is an SVG form of the NetBox logo at [docs/netbox_logo.svg](../netbox_logo.svg). It is preferred to use this logo for all purposes as it scales to arbitrary sizes without loss of resolution. If a raster image is required, the SVG logo should be converted to a PNG image of the prescribed size. +* There are SVG forms of the NetBox logo for both [light mode](../netbox_logo_light.svg) and [dark mode](../netbox_logo_dark.svg) available. It is preferred to use the SVG logo for all purposes as it scales to arbitrary sizes without loss of resolution. If a raster image is required, the SVG logo should be converted to a PNG image of the desired size. diff --git a/docs/development/translations.md b/docs/development/translations.md index eca9ce71f..43733c6d1 100644 --- a/docs/development/translations.md +++ b/docs/development/translations.md @@ -16,26 +16,31 @@ To update the English `.po` file from which all translations are derived, use th Then, commit the change and push to the `develop` branch on GitHub. Any new strings will appear for translation on Transifex automatically. +!!! note + It is typically not necessary to update source strings manually, as this is done nightly by a [GitHub action](https://github.com/netbox-community/netbox/blob/develop/.github/workflows/update-translation-strings.yml). + ## Updating Translated Strings Typically, translated strings need to be updated only as part of the NetBox [release process](./release-checklist.md). Check the Transifex dashboard for languages that are not marked _ready for use_, being sure to click _Show all languages_ if it appears at the bottom of the list. Use machine translation to round out any not-ready languages. It's not necessary to review the machine translation immediately as the translation teams will handle that aspect; the goal at this stage is to get translations included in the Transifex pull request. -To update translated strings, start by initiating a sync from Transifex. From the Transifex dashboard, navigate to Settings > Integrations > GitHub > Manage, and click the **Manual Sync** button at top right. +To download translated strings automatically, you'll need to: -![Transifex manual sync](../media/development/transifex_sync.png) +1. Install the [Transifex CLI client](https://github.com/transifex/cli) +2. Generate a [Transifex API token](https://app.transifex.com/user/settings/api/) -Enter a threshold percentage of 1 (to ensure all translations are captured) and select the `develop` branch, then click **Sync**. This will initiate a pull request to GitHub to update any newly modified translation (`.po`) files. +Once you have the client set up, run the following command: -!!! tip - The new PR should appear within a few minutes. If it does not, check that there are in fact new translations to be added. +```no-highlight +TX_TOKEN=$TOKEN tx pull +``` -![Transifex pull request](../media/development/transifex_pull_request.png) +This will download all portable (`.po`) translation files from Transifex, updating them locally as needed. -Once the PR has been merged, the updated strings need to be compiled into new `.mo` files so they can be used by the application. Update the `develop` branch locally to pull in the changes from the Transifex PR, then run Django's [`compilemessages`](https://docs.djangoproject.com/en/stable/ref/django-admin/#django-admin-compilemessages) management command: +Once retrieved, the updated strings need to be compiled into new `.mo` files so they can be used by the application. Run Django's [`compilemessages`](https://docs.djangoproject.com/en/stable/ref/django-admin/#django-admin-compilemessages) management command to compile them: -```nohighlight +```no-highlight ./manage.py compilemessages ``` diff --git a/docs/extra.css b/docs/extra.css index e953fa14c..4b8cd87fe 100644 --- a/docs/extra.css +++ b/docs/extra.css @@ -5,6 +5,10 @@ img { margin-right: auto; } +.md-content img { + background-color: rgba(255, 255, 255, 0.64); +} + /* Tables */ table { margin-bottom: 24px; diff --git a/docs/features/notifications.md b/docs/features/notifications.md index a28a17947..0567a6db6 100644 --- a/docs/features/notifications.md +++ b/docs/features/notifications.md @@ -1,7 +1,5 @@ # Notifications -!!! info "This feature was introduced in NetBox v4.1." - NetBox includes a system for generating user notifications, which can be marked as read or deleted by individual users. There are two built-in mechanisms for generating a notification: * A user can subscribe to an object. When that object is modified, a notification is created to inform the user of the change. diff --git a/docs/index.md b/docs/index.md index 5ef650ca6..a79ab03b4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,5 @@ -![NetBox](netbox_logo.svg "NetBox logo"){style="height: 100px; margin-bottom: 3em"} +![NetBox](netbox_logo_light.svg#only-light "NetBox logo"){style="height: 100px; margin-bottom: 3em; background: none;"} +![NetBox](netbox_logo_dark.svg#only-dark "NetBox logo"){style="height: 100px; margin-bottom: 3em; background: none;"} # The Premier Network Source of Truth diff --git a/docs/media/authentication/google_login_portal.png b/docs/media/authentication/google_login_portal.png new file mode 100644 index 000000000..55eefd872 Binary files /dev/null and b/docs/media/authentication/google_login_portal.png differ diff --git a/docs/media/authentication/netbox_google_login.png b/docs/media/authentication/netbox_google_login.png new file mode 100644 index 000000000..730173b5d Binary files /dev/null and b/docs/media/authentication/netbox_google_login.png differ diff --git a/docs/media/development/transifex_pull_request.png b/docs/media/development/transifex_pull_request.png deleted file mode 100644 index e3ae76991..000000000 Binary files a/docs/media/development/transifex_pull_request.png and /dev/null differ diff --git a/docs/media/development/transifex_sync.png b/docs/media/development/transifex_sync.png deleted file mode 100644 index 44022cc4d..000000000 Binary files a/docs/media/development/transifex_sync.png and /dev/null differ diff --git a/docs/models/circuits/circuitgroup.md b/docs/models/circuits/circuitgroup.md index faa9dbc14..6d1503509 100644 --- a/docs/models/circuits/circuitgroup.md +++ b/docs/models/circuits/circuitgroup.md @@ -1,7 +1,5 @@ # Circuit Groups -!!! info "This feature was introduced in NetBox v4.1." - [Circuits](./circuit.md) can be arranged into administrative groups for organization. The assignment of a circuit to a group is optional. ## Fields diff --git a/docs/models/circuits/circuitgroupassignment.md b/docs/models/circuits/circuitgroupassignment.md index 2aaa375af..c73ba09be 100644 --- a/docs/models/circuits/circuitgroupassignment.md +++ b/docs/models/circuits/circuitgroupassignment.md @@ -8,9 +8,9 @@ Circuits can be assigned to [circuit groups](./circuitgroup.md) for correlation The [circuit group](./circuitgroup.md) being assigned. -### Circuit +### Member -The [circuit](./circuit.md) that is being assigned to the group. +The [circuit](./circuit.md) or [virtual circuit](./virtualcircuit.md) assigned to the group. ### Priority diff --git a/docs/models/circuits/circuittermination.md b/docs/models/circuits/circuittermination.md index c6aa966d0..4b1a16ded 100644 --- a/docs/models/circuits/circuittermination.md +++ b/docs/models/circuits/circuittermination.md @@ -21,13 +21,11 @@ Designates the termination as forming either the A or Z end of the circuit. If selected, the circuit termination will be considered "connected" even if no cable has been connected to it in NetBox. -### Site +### Termination -The [site](../dcim/site.md) with which this circuit termination is associated. Once created, a cable can be connected between the circuit termination and a device interface (or similar component). +!!! info "This field replaced the `site` and `provider_network` fields in NetBox v4.2." -### Provider Network - -Circuits which do not connect to a site modeled by NetBox can instead be terminated to a [provider network](./providernetwork.md) representing an unknown network operated by a [provider](./provider.md). +The [region](../dcim/region.md), [site group](../dcim/sitegroup.md), [site](../dcim/site.md), [location](../dcim/location.md) or [provider network](./providernetwork.md) with which this circuit termination is associated. Once created, a cable can be connected between the circuit termination and a device interface (or similar component). ### Port Speed diff --git a/docs/models/circuits/virtualcircuit.md b/docs/models/circuits/virtualcircuit.md new file mode 100644 index 000000000..17328b87a --- /dev/null +++ b/docs/models/circuits/virtualcircuit.md @@ -0,0 +1,39 @@ +# Virtual Circuits + +!!! info "This feature was introduced in NetBox v4.2." + +A virtual circuit can connect two or more interfaces atop a set of decoupled physical connections. For example, it's very common to form a virtual connection between two virtual interfaces, each of which is bound to a physical interface on its respective device and physically connected to a [provider network](./providernetwork.md) via an independent [physical circuit](./circuit.md). + +## Fields + +### Provider Network + +The [provider network](./providernetwork.md) across which the virtual circuit is formed. + +### Provider Account + +The [provider account](./provideraccount.md) with which the virtual circuit is associated (if any). + +### Circuit ID + +The unique identifier assigned to the virtual circuit by its [provider](./provider.md). + +### Type + +The assigned [virtual circuit type](./virtualcircuittype.md). + +### Status + +The operational status of the virtual circuit. By default, the following statuses are available: + +| Name | +|----------------| +| Planned | +| Provisioning | +| Active | +| Offline | +| Deprovisioning | +| Decommissioned | + +!!! tip "Custom circuit statuses" + Additional circuit statuses may be defined by setting `Circuit.status` under the [`FIELD_CHOICES`](../../configuration/data-validation.md#field_choices) configuration parameter. diff --git a/docs/models/circuits/virtualcircuittermination.md b/docs/models/circuits/virtualcircuittermination.md new file mode 100644 index 000000000..a7833e13c --- /dev/null +++ b/docs/models/circuits/virtualcircuittermination.md @@ -0,0 +1,23 @@ +# Virtual Circuit Terminations + +!!! info "This feature was introduced in NetBox v4.2." + +This model represents the connection of a virtual [interface](../dcim/interface.md) to a [virtual circuit](./virtualcircuit.md). + +## Fields + +### Virtual Circuit + +The [virtual circuit](./virtualcircuit.md) to which the interface is connected. + +### Interface + +The [interface](../dcim/interface.md) connected to the virtual circuit. + +### Role + +The functional role of the termination. This depends on the virtual circuit's topology, which is typically either peer-to-peer or hub-and-spoke (multipoint). Valid choices include: + +* Peer +* Hub +* Spoke diff --git a/docs/models/circuits/virtualcircuittype.md b/docs/models/circuits/virtualcircuittype.md new file mode 100644 index 000000000..69cb0c027 --- /dev/null +++ b/docs/models/circuits/virtualcircuittype.md @@ -0,0 +1,13 @@ +# Virtual Circuit Types + +Like physical [circuits](./circuit.md), [virtual circuits](./virtualcircuit.md) are classified by functional type. These types are completely customizable, and can help categorize circuits by function or technology. + +## Fields + +### Name + +A unique human-friendly name. + +### Slug + +A unique URL-friendly identifier. (This value can be used for filtering.) diff --git a/docs/models/dcim/interface.md b/docs/models/dcim/interface.md index 3667dabd5..b7115050f 100644 --- a/docs/models/dcim/interface.md +++ b/docs/models/dcim/interface.md @@ -45,9 +45,12 @@ The operation duplex (full, half, or auto). The [virtual routing and forwarding](../ipam/vrf.md) instance to which this interface is assigned. -### MAC Address +### Primary MAC Address -The 48-bit MAC address (for Ethernet interfaces). +The [MAC address](./macaddress.md) assigned to this interface which is designated as its primary. + +!!! note "Changed in NetBox v4.2" + The MAC address of an interface (formerly a concrete database field) is available as a property, `mac_address`, which reflects the value of the primary linked [MAC address](./macaddress.md) object. ### WWN @@ -109,6 +112,7 @@ For switched Ethernet interfaces, this identifies the 802.1Q encapsulation strat * **Access:** All traffic is assigned to a single VLAN, with no tagging. * **Tagged:** One untagged "native" VLAN is allowed, as well as any number of tagged VLANs. * **Tagged (all):** Implies that all VLANs are carried by the interface. One untagged VLAN may be designated. +* **Q-in-Q:** Q-in-Q (IEEE 802.1ad) encapsulation is performed using the assigned SVLAN. This field must be left blank for routed interfaces which do employ 802.1Q encapsulation. @@ -120,6 +124,12 @@ The "native" (untagged) VLAN for the interface. Valid only when one of the above The tagged VLANs which are configured to be carried by this interface. Valid only for the "tagged" 802.1Q mode above. +### Q-in-Q SVLAN + +!!! info "This field was introduced in NetBox v4.2." + +The assigned service VLAN (for Q-in-Q/802.1ad interfaces). + ### Wireless Role Indicates the configured role for wireless interfaces (access point or station). @@ -142,3 +152,9 @@ The configured channel width of a wireless interface, in MHz. This is typically ### Wireless LANs The [wireless LANs](../wireless/wirelesslan.md) for which this interface carries traffic. (Valid for wireless interfaces only.) + +### VLAN Translation Policy + +!!! info "This field was introduced in NetBox v4.2." + +The [VLAN translation policy](../ipam/vlantranslationpolicy.md) that applies to this interface (optional). diff --git a/docs/models/dcim/inventoryitem.md b/docs/models/dcim/inventoryitem.md index a6dfa32db..2d648341b 100644 --- a/docs/models/dcim/inventoryitem.md +++ b/docs/models/dcim/inventoryitem.md @@ -25,6 +25,12 @@ The inventory item's name. If the inventory item is assigned to a parent item, i An alternative physical label identifying the inventory item. +### Status + +!!! info "This field was introduced in NetBox v4.2." + +The inventory item's operational status. + ### Role The functional [role](./inventoryitemrole.md) assigned to this inventory item. @@ -44,7 +50,3 @@ The serial number assigned by the manufacturer. ### Asset Tag A unique, locally-administered label used to identify hardware resources. - -### Status - -The inventory item's operational status. diff --git a/docs/models/dcim/macaddress.md b/docs/models/dcim/macaddress.md new file mode 100644 index 000000000..5b1dd93be --- /dev/null +++ b/docs/models/dcim/macaddress.md @@ -0,0 +1,13 @@ +# MAC Addresses + +!!! info "This feature was introduced in NetBox v4.2." + +A MAC address object in NetBox comprises a single Ethernet link layer address, and represents a MAC address as reported by or assigned to a network interface. MAC addresses can be assigned to [device](../dcim/device.md) and [virtual machine](../virtualization/virtualmachine.md) interfaces. A MAC address can be specified as the primary MAC address for a given device or VM interface. + +Most interfaces have only a single MAC address, hard-coded at the factory. However, on some devices (particularly virtual interfaces) it is possible to assign additional MAC addresses or change existing ones. For this reason NetBox allows multiple MACAddress objects to be assigned to a single interface. + +## Fields + +### MAC Address + +The 48-bit MAC address, in colon-hexadecimal notation (e.g. `aa:bb:cc:11:22:33`). diff --git a/docs/models/dcim/modulebay.md b/docs/models/dcim/modulebay.md index 1bff799c2..494012a7b 100644 --- a/docs/models/dcim/modulebay.md +++ b/docs/models/dcim/modulebay.md @@ -16,8 +16,6 @@ The device to which this module bay belongs. ### Module -!!! info "This feature was introduced in NetBox v4.1." - The module to which this bay belongs (optional). ### Name diff --git a/docs/models/dcim/moduletype.md b/docs/models/dcim/moduletype.md index 225873d61..7077e16c2 100644 --- a/docs/models/dcim/moduletype.md +++ b/docs/models/dcim/moduletype.md @@ -42,6 +42,4 @@ The numeric weight of the module, including a unit designation (e.g. 3 kilograms ### Airflow -!!! info "The `airflow` field was introduced in NetBox v4.1." - The direction in which air circulates through the device chassis for cooling. diff --git a/docs/models/dcim/poweroutlet.md b/docs/models/dcim/poweroutlet.md index fe9390056..a99f60b23 100644 --- a/docs/models/dcim/poweroutlet.md +++ b/docs/models/dcim/poweroutlet.md @@ -31,6 +31,8 @@ The type of power outlet. ### Color +!!! info "This field was introduced in NetBox v4.2." + The power outlet's color (optional). ### Power Port diff --git a/docs/models/dcim/racktype.md b/docs/models/dcim/racktype.md index eeb90bd29..b5f2d99e7 100644 --- a/docs/models/dcim/racktype.md +++ b/docs/models/dcim/racktype.md @@ -1,7 +1,5 @@ # Rack Types -!!! info "This feature was introduced in NetBox v4.1." - A rack type defines the physical characteristics of a particular model of [rack](./rack.md). ## Fields diff --git a/docs/models/extras/customfield.md b/docs/models/extras/customfield.md index 9aab66a36..a5d083492 100644 --- a/docs/models/extras/customfield.md +++ b/docs/models/extras/customfield.md @@ -44,8 +44,6 @@ For object and multiple-object fields only. Designates the type of NetBox object ### Related Object Filter -!!! info "This field was introduced in NetBox v4.1." - For object and multi-object custom fields, a filter may be defined to limit the available objects when populating a field value. This filter maps object attributes to values. For example, `{"status": "active"}` will include only objects with a status of "active." !!! warning diff --git a/docs/models/extras/eventrule.md b/docs/models/extras/eventrule.md index b48e17a1e..9dca04529 100644 --- a/docs/models/extras/eventrule.md +++ b/docs/models/extras/eventrule.md @@ -10,7 +10,7 @@ See the [event rules documentation](../../features/event-rules.md) for more inf A unique human-friendly name. -### Content Types +### Object Types The type(s) of object in NetBox that will trigger the rule. @@ -38,3 +38,15 @@ The event types which will trigger the rule. At least one event type must be sel ### Conditions A set of [prescribed conditions](../../reference/conditions.md) against which the triggering object will be evaluated. If the conditions are defined but not met by the object, no action will be taken. An event rule that does not define any conditions will _always_ trigger. + +### Action Type + +The type of action to take when the rule triggers. This must be one of the following choices: + +* Webhook +* Custom script +* Notification + +### Action Data + +An optional dictionary of JSON data to pass when executing the rule. This can be useful to include additional context data, e.g. when transmitting a webhook. diff --git a/docs/models/ipam/prefix.md b/docs/models/ipam/prefix.md index 2fb01daf0..939ca3ea5 100644 --- a/docs/models/ipam/prefix.md +++ b/docs/models/ipam/prefix.md @@ -34,9 +34,11 @@ Designates whether the prefix should be treated as a pool. If selected, the firs If selected, this prefix will report 100% utilization regardless of how many child objects have been defined within it. -### Site +### Scope -The [site](../dcim/site.md) to which this prefix is assigned (optional). +!!! info "This field replaced the `site` field in NetBox v4.2." + +The [region](../dcim/region.md), [site](../dcim/site.md), [site group](../dcim/sitegroup.md) or [location](../dcim/location.md) to which the prefix is assigned (optional). ### VLAN diff --git a/docs/models/ipam/vlan.md b/docs/models/ipam/vlan.md index 2dd5ec2d3..3c90d8cc9 100644 --- a/docs/models/ipam/vlan.md +++ b/docs/models/ipam/vlan.md @@ -26,3 +26,15 @@ The user-defined functional [role](./role.md) assigned to the VLAN. ### VLAN Group or Site The [VLAN group](./vlangroup.md) or [site](../dcim/site.md) to which the VLAN is assigned. + +### Q-in-Q Role + +!!! info "This field was introduced in NetBox v4.2." + +For VLANs which comprise a Q-in-Q/IEEE 802.1ad topology, this field indicates whether the VLAN is treated as a service or customer VLAN. + +### Q-in-Q Service VLAN + +!!! info "This field was introduced in NetBox v4.2." + +The designated parent service VLAN for a Q-in-Q customer VLAN. This may be set only for Q-in-Q custom VLANs. diff --git a/docs/models/ipam/vlangroup.md b/docs/models/ipam/vlangroup.md index 20989452f..67050ab4c 100644 --- a/docs/models/ipam/vlangroup.md +++ b/docs/models/ipam/vlangroup.md @@ -16,8 +16,6 @@ A unique URL-friendly identifier. (This value can be used for filtering.) ### VLAN ID Ranges -!!! info "This field replaced the legacy `min_vid` and `max_vid` fields in NetBox v4.1." - The set of VLAN IDs which are encompassed by the group. By default, this will be the entire range of valid IEEE 802.1Q VLAN IDs (1 to 4094, inclusive). VLANs created within a group must have a VID that falls within one of these ranges. Ranges may not overlap. ### Scope diff --git a/docs/models/ipam/vlantranslationpolicy.md b/docs/models/ipam/vlantranslationpolicy.md new file mode 100644 index 000000000..9e3e8de98 --- /dev/null +++ b/docs/models/ipam/vlantranslationpolicy.md @@ -0,0 +1,28 @@ +# VLAN Translation Policies + +!!! info "This feature was introduced in NetBox v4.2." + +VLAN translation is a feature that consists of VLAN translation policies and [VLAN translation rules](./vlantranslationrule.md). Many rules can belong to a policy, and each rule defines a mapping of a local to remote VLAN ID (VID). A policy can then be assigned to an [Interface](../dcim/interface.md) or [VMInterface](../virtualization/vminterface.md), and all VLAN translation rules associated with that policy will be visible in the interface details. + +There are uniqueness constraints on `(policy, local_vid)` and on `(policy, remote_vid)` in the `VLANTranslationRule` model. Thus, you cannot have multiple rules linked to the same policy that have the same local VID or the same remote VID. A set of policies and rules might look like this: + +Policy 1: +- Rule: 100 -> 200 +- Rule: 101 -> 201 + +Policy 2: +- Rule: 100 -> 300 +- Rule: 101 -> 301 + +However this is not allowed: + +Policy 3: +- Rule: 100 -> 200 +- Rule: 100 -> 300 + + +## Fields + +### Name + +A unique human-friendly name. diff --git a/docs/models/ipam/vlantranslationrule.md b/docs/models/ipam/vlantranslationrule.md new file mode 100644 index 000000000..eb356d0d0 --- /dev/null +++ b/docs/models/ipam/vlantranslationrule.md @@ -0,0 +1,21 @@ +# VLAN Translation Rules + +!!! info "This feature was introduced in NetBox v4.2." + +A VLAN translation rule represents a one-to-one mapping of a local VLAN ID (VID) to a remote VID. Many rules can belong to a single policy. + +See [VLAN translation policies](./vlantranslationpolicy.md) for an overview of the VLAN Translation feature. + +## Fields + +### Policy + +The [VLAN Translation Policy](./vlantranslationpolicy.md) to which this rule belongs. + +### Local VID + +VLAN ID (1-4094) in the local network which is to be translated to a remote VID. + +### Remote VID + +VLAN ID (1-4094) in the remote network to which the local VID will be translated. diff --git a/docs/models/virtualization/cluster.md b/docs/models/virtualization/cluster.md index 50b5dbd1d..b9e6b608f 100644 --- a/docs/models/virtualization/cluster.md +++ b/docs/models/virtualization/cluster.md @@ -23,6 +23,8 @@ The cluster's operational status. !!! tip Additional statuses may be defined by setting `Cluster.status` under the [`FIELD_CHOICES`](../../configuration/data-validation.md#field_choices) configuration parameter. -### Site +### Scope -The [site](../dcim/site.md) with which the cluster is associated. +!!! info "This field replaced the `site` field in NetBox v4.2." + +The [region](../dcim/region.md), [site](../dcim/site.md), [site group](../dcim/sitegroup.md) or [location](../dcim/location.md) with which this cluster is associated. diff --git a/docs/models/virtualization/virtualmachine.md b/docs/models/virtualization/virtualmachine.md index 7ea31111c..a90b2752d 100644 --- a/docs/models/virtualization/virtualmachine.md +++ b/docs/models/virtualization/virtualmachine.md @@ -57,6 +57,4 @@ The amount of disk storage provisioned, in megabytes. ### Serial Number -!!! info "This field was introduced in NetBox v4.1." - Optional serial number assigned to this virtual machine. Unlike devices, uniqueness is not enforced for virtual machine serial numbers. diff --git a/docs/models/virtualization/vminterface.md b/docs/models/virtualization/vminterface.md index d923bdd5d..ba0c68b15 100644 --- a/docs/models/virtualization/vminterface.md +++ b/docs/models/virtualization/vminterface.md @@ -27,9 +27,12 @@ An interface on the same VM with which this interface is bridged. If not selected, this interface will be treated as disabled/inoperative. -### MAC Address +### Primary MAC Address -The 48-bit MAC address (for Ethernet interfaces). +The [MAC address](../dcim/macaddress.md) assigned to this interface which is designated as its primary. + +!!! note "Changed in NetBox v4.2" + The MAC address of an interface (formerly a concrete database field) is available as a property, `mac_address`, which reflects the value of the primary linked [MAC address](../dcim/macaddress.md) object. ### MTU @@ -42,6 +45,7 @@ For switched Ethernet interfaces, this identifies the 802.1Q encapsulation strat * **Access:** All traffic is assigned to a single VLAN, with no tagging. * **Tagged:** One untagged "native" VLAN is allowed, as well as any number of tagged VLANs. * **Tagged (all):** Implies that all VLANs are carried by the interface. One untagged VLAN may be designated. +* **Q-in-Q:** Q-in-Q (IEEE 802.1ad) encapsulation is performed using the assigned SVLAN. This field must be left blank for routed interfaces which do employ 802.1Q encapsulation. @@ -53,6 +57,18 @@ The "native" (untagged) VLAN for the interface. Valid only when one of the above The tagged VLANs which are configured to be carried by this interface. Valid only for the "tagged" 802.1Q mode above. +### Q-in-Q SVLAN + +!!! info "This field was introduced in NetBox v4.2." + +The assigned service VLAN (for Q-in-Q/802.1ad interfaces). + ### VRF The [virtual routing and forwarding](../ipam/vrf.md) instance to which this interface is assigned. + +### VLAN Translation Policy + +!!! info "This field was introduced in NetBox v4.2." + +The [VLAN translation policy](../ipam/vlantranslationpolicy.md) that applies to this interface (optional). diff --git a/docs/models/vpn/ikepolicy.md b/docs/models/vpn/ikepolicy.md index d2da28d16..b78b0fe50 100644 --- a/docs/models/vpn/ikepolicy.md +++ b/docs/models/vpn/ikepolicy.md @@ -1,6 +1,6 @@ # IKE Policies -An [Internet Key Exhcnage (IKE)](https://en.wikipedia.org/wiki/Internet_Key_Exchange) policy defines an IKE version, mode, and set of [proposals](./ikeproposal.md) to be used in IKE negotiation. These policies are referenced by [IPSec profiles](./ipsecprofile.md). +An [Internet Key Exchange (IKE)](https://en.wikipedia.org/wiki/Internet_Key_Exchange) policy defines an IKE version, mode, and set of [proposals](./ikeproposal.md) to be used in IKE negotiation. These policies are referenced by [IPSec profiles](./ipsecprofile.md). ## Fields diff --git a/docs/models/wireless/wirelesslan.md b/docs/models/wireless/wirelesslan.md index 0f50fa75f..2ce673086 100644 --- a/docs/models/wireless/wirelesslan.md +++ b/docs/models/wireless/wirelesslan.md @@ -43,3 +43,9 @@ The security cipher used to apply wireless authentication. Options include: ### Pre-Shared Key The security key configured on each client to grant access to the secured wireless LAN. This applies only to certain authentication types. + +### Scope + +!!! info "This field was introduced in NetBox v4.2." + +The [region](../dcim/region.md), [site](../dcim/site.md), [site group](../dcim/sitegroup.md) or [location](../dcim/location.md) with which this wireless LAN is associated. diff --git a/docs/models/wireless/wirelesslink.md b/docs/models/wireless/wirelesslink.md index 7553902b0..a9fd6b4fc 100644 --- a/docs/models/wireless/wirelesslink.md +++ b/docs/models/wireless/wirelesslink.md @@ -22,8 +22,6 @@ The service set identifier (SSID) for the wireless link (optional). ### Distance -!!! info "This field was introduced in NetBox v4.1." - The distance between the link's two endpoints, including a unit designation (e.g. 100 meters or 25 feet). ### Authentication Type diff --git a/docs/netbox_logo_dark.svg b/docs/netbox_logo_dark.svg new file mode 100644 index 000000000..958a1d401 --- /dev/null +++ b/docs/netbox_logo_dark.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/netbox_logo.svg b/docs/netbox_logo_light.svg similarity index 100% rename from docs/netbox_logo.svg rename to docs/netbox_logo_light.svg diff --git a/docs/plugins/development/background-jobs.md b/docs/plugins/development/background-jobs.md index 873390a58..9be52c3ca 100644 --- a/docs/plugins/development/background-jobs.md +++ b/docs/plugins/development/background-jobs.md @@ -1,7 +1,5 @@ # Background Jobs -!!! info "This feature was introduced in NetBox v4.1." - NetBox plugins can defer certain operations by enqueuing [background jobs](../../features/background-jobs.md), which are executed asynchronously by background workers. This is helpful for decoupling long-running processes from the user-facing request-response cycle. For example, your plugin might need to fetch data from a remote system. Depending on the amount of data and the responsiveness of the remote server, this could take a few minutes. Deferring this task to a queued job ensures that it can be completed in the background, without interrupting the user. The data it fetches can be made available once the job has completed. @@ -29,6 +27,9 @@ class MyTestJob(JobRunner): You can schedule the background job from within your code (e.g. from a model's `save()` method or a view) by calling `MyTestJob.enqueue()`. This method passes through all arguments to `Job.enqueue()`. However, no `name` argument must be passed, as the background job name will be used instead. +!!! tip + A set of predefined intervals is available at `core.choices.JobIntervalChoices` for convenience. + ### Attributes `JobRunner` attributes are defined under a class named `Meta` within the job. These are optional, but encouraged. @@ -46,26 +47,57 @@ As described above, jobs can be scheduled for immediate execution or at any late #### Example +```python title="models.py" +from django.db import models +from core.choices import JobIntervalChoices +from netbox.models import NetBoxModel +from .jobs import MyTestJob + +class MyModel(NetBoxModel): + foo = models.CharField() + + def save(self, *args, **kwargs): + MyTestJob.enqueue_once(instance=self, interval=JobIntervalChoices.INTERVAL_HOURLY) + return super().save(*args, **kwargs) + + def sync(self): + MyTestJob.enqueue(instance=self) +``` + + +### System Jobs + +!!! info "This feature was introduced in NetBox v4.2." + +Some plugins may implement background jobs that are decoupled from the request/response cycle. Typical use cases would be housekeeping tasks or synchronization jobs. These can be registered as _system jobs_ using the `system_job()` decorator. The job interval must be passed as an integer (in minutes) when registering a system job. System jobs are scheduled automatically when the RQ worker (`manage.py rqworker`) is run. + +#### Example + ```python title="jobs.py" -from netbox.jobs import JobRunner - +from core.choices import JobIntervalChoices +from netbox.jobs import JobRunner, system_job +from .models import MyModel +# Specify a predefined choice or an integer indicating +# the number of minutes between job executions +@system_job(interval=JobIntervalChoices.INTERVAL_HOURLY) class MyHousekeepingJob(JobRunner): class Meta: - name = "Housekeeping" + name = "My Housekeeping Job" def run(self, *args, **kwargs): - # your logic goes here + MyModel.objects.filter(foo='bar').delete() ``` -```python title="__init__.py" -from netbox.plugins import PluginConfig +!!! note + Ensure that any system jobs are imported on initialization. Otherwise, they won't be registered. This can be achieved by extending the PluginConfig's `ready()` method. For example: -class MyPluginConfig(PluginConfig): + ```python def ready(self): + super().ready() + from .jobs import MyHousekeepingJob - MyHousekeepingJob.setup(interval=60) -``` + ``` ## Task queues diff --git a/docs/plugins/development/data-backends.md b/docs/plugins/development/data-backends.md index 8b7226a41..0c6d44d95 100644 --- a/docs/plugins/development/data-backends.md +++ b/docs/plugins/development/data-backends.md @@ -18,6 +18,6 @@ backends = [MyDataBackend] ``` !!! tip - The path to the list of search indexes can be modified by setting `data_backends` in the PluginConfig instance. + The path to the list of data backends can be modified by setting `data_backends` in the PluginConfig instance. ::: netbox.data_backends.DataBackend diff --git a/docs/plugins/development/event-types.md b/docs/plugins/development/event-types.md index 4bcdeea31..65e2bbc5c 100644 --- a/docs/plugins/development/event-types.md +++ b/docs/plugins/development/event-types.md @@ -1,7 +1,5 @@ # Event Types -!!! info "This feature was introduced in NetBox v4.1." - Plugins can register their own custom event types for use with NetBox [event rules](../../models/extras/eventrule.md). This is accomplished by calling the `register()` method on an instance of the `EventType` class. This can be done anywhere within the plugin. An example is provided below. ```python diff --git a/docs/plugins/development/index.md b/docs/plugins/development/index.md index f3f9a3e4f..246816349 100644 --- a/docs/plugins/development/index.md +++ b/docs/plugins/development/index.md @@ -98,28 +98,29 @@ NetBox looks for the `config` variable within a plugin's `__init__.py` to load i ### PluginConfig Attributes -| Name | Description | -|-----------------------|--------------------------------------------------------------------------------------------------------------------------| -| `name` | Raw plugin name; same as the plugin's source directory | -| `verbose_name` | Human-friendly name for the plugin | -| `version` | Current release ([semantic versioning](https://semver.org/) is encouraged) | -| `description` | Brief description of the plugin's purpose | -| `author` | Name of plugin's author | -| `author_email` | Author's public email address | -| `base_url` | Base path to use for plugin URLs (optional). If not specified, the project's `name` will be used. | -| `required_settings` | A list of any configuration parameters that **must** be defined by the user | -| `default_settings` | A dictionary of configuration parameters and their default values | -| `django_apps` | A list of additional Django apps to load alongside the plugin | -| `min_version` | Minimum version of NetBox with which the plugin is compatible | -| `max_version` | Maximum version of NetBox with which the plugin is compatible | -| `middleware` | A list of middleware classes to append after NetBox's build-in middleware | -| `queues` | A list of custom background task queues to create | -| `search_extensions` | The dotted path to the list of search index classes (default: `search.indexes`) | -| `data_backends` | The dotted path to the list of data source backend classes (default: `data_backends.backends`) | -| `template_extensions` | The dotted path to the list of template extension classes (default: `template_content.template_extensions`) | -| `menu_items` | The dotted path to the list of menu items provided by the plugin (default: `navigation.menu_items`) | -| `graphql_schema` | The dotted path to the plugin's GraphQL schema class, if any (default: `graphql.schema`) | -| `user_preferences` | The dotted path to the dictionary mapping of user preferences defined by the plugin (default: `preferences.preferences`) | +| Name | Description | +|-----------------------|------------------------------------------------------------------------------------------------------------------------------------| +| `name` | Raw plugin name; same as the plugin's source directory | +| `verbose_name` | Human-friendly name for the plugin | +| `version` | Current release ([semantic versioning](https://semver.org/) is encouraged) | +| `description` | Brief description of the plugin's purpose | +| `author` | Name of plugin's author | +| `author_email` | Author's public email address | +| `base_url` | Base path to use for plugin URLs (optional). If not specified, the project's `name` will be used. | +| `required_settings` | A list of any configuration parameters that **must** be defined by the user | +| `default_settings` | A dictionary of configuration parameters and their default values | +| `django_apps` | A list of additional Django apps to load alongside the plugin | +| `min_version` | Minimum version of NetBox with which the plugin is compatible | +| `max_version` | Maximum version of NetBox with which the plugin is compatible | +| `middleware` | A list of middleware classes to append after NetBox's build-in middleware | +| `queues` | A list of custom background task queues to create | +| `events_pipeline` | A list of handlers to add to [`EVENTS_PIPELINE`](../../configuration/miscellaneous.md#events_pipeline), identified by dotted paths | +| `search_extensions` | The dotted path to the list of search index classes (default: `search.indexes`) | +| `data_backends` | The dotted path to the list of data source backend classes (default: `data_backends.backends`) | +| `template_extensions` | The dotted path to the list of template extension classes (default: `template_content.template_extensions`) | +| `menu_items` | The dotted path to the list of menu items provided by the plugin (default: `navigation.menu_items`) | +| `graphql_schema` | The dotted path to the plugin's GraphQL schema class, if any (default: `graphql.schema`) | +| `user_preferences` | The dotted path to the dictionary mapping of user preferences defined by the plugin (default: `preferences.preferences`) | All required settings must be configured by the user. If a configuration parameter is listed in both `required_settings` and `default_settings`, the default setting will be ignored. diff --git a/docs/plugins/development/views.md b/docs/plugins/development/views.md index 1f5f164fd..e3740de59 100644 --- a/docs/plugins/development/views.md +++ b/docs/plugins/development/views.md @@ -185,6 +185,9 @@ class MyView(generic.ObjectView): ) ``` +!!! note "Changed in NetBox v4.2" + The `register_model_view()` function was extended in NetBox v4.2 to support registration of list views by passing `detail=False`. + ::: utilities.views.register_model_view ::: utilities.views.ViewTab @@ -203,8 +206,6 @@ Plugins can inject custom content into certain areas of core NetBox views. This | `right_page()` | Object view | Inject content on the right side of the page | | `full_width_page()` | Object view | Inject content across the entire bottom of the page | -!!! info "The `navbar()` and `alerts()` methods were introduced in NetBox v4.1." - Additionally, a `render()` method is available for convenience. This method accepts the name of a template to render, and any additional context data you want to pass. Its use is optional, however. To control where the custom content is injected, plugin authors can specify an iterable of models by overriding the `models` attribute on the subclass. Extensions which do not specify a set of models will be invoked on every view, where supported. diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md index b1f23ae55..d996224c1 100644 --- a/docs/release-notes/index.md +++ b/docs/release-notes/index.md @@ -10,6 +10,23 @@ Minor releases are published in April, August, and December of each calendar yea This page contains a history of all major and minor releases since NetBox v2.0. For more detail on a specific patch release, please see the release notes page for that specific minor release. +#### [Version 4.2](./version-4.2.md) (January 2025) + +* Assign Multiple MAC Addresses per Interface ([#4867](https://github.com/netbox-community/netbox/issues/4867)) +* Quick Add UI Widget ([#5858](https://github.com/netbox-community/netbox/issues/5858)) +* VLAN Translation ([#7336](https://github.com/netbox-community/netbox/issues/7336)) +* Virtual Circuits ([#13086](https://github.com/netbox-community/netbox/issues/13086)) +* Q-in-Q Encapsulation ([#13428](https://github.com/netbox-community/netbox/issues/13428)) + +#### [Version 4.1](./version-4.1.md) (September 2024) + +* Circuit Groups ([#7025](https://github.com/netbox-community/netbox/issues/7025)) +* VLAN Group ID Ranges ([#9627](https://github.com/netbox-community/netbox/issues/9627)) +* Nested Device Modules ([#10500](https://github.com/netbox-community/netbox/issues/10500)) +* Rack Types ([#12826](https://github.com/netbox-community/netbox/issues/12826)) +* Plugins Catalog Integration ([#14731](https://github.com/netbox-community/netbox/issues/14731)) +* User Notifications ([#15621](https://github.com/netbox-community/netbox/issues/15621)) + #### [Version 4.0](./version-4.0.md) (April 2024) * Complete UI Refresh ([#12128](https://github.com/netbox-community/netbox/issues/12128)) diff --git a/docs/release-notes/version-4.1.md b/docs/release-notes/version-4.1.md index d48bb899f..9a2f79ece 100644 --- a/docs/release-notes/version-4.1.md +++ b/docs/release-notes/version-4.1.md @@ -1,5 +1,126 @@ # NetBox v4.1 +## v4.1.11 (2025-01-06) + +### Bug Fixes + +* [#17771](https://github.com/netbox-community/netbox/issues/17771) - Fix duplicate entries appearing on VLAN list when filtering by interface assignment +* [#18222](https://github.com/netbox-community/netbox/issues/18222) - Pass event rule action data to webhooks as context data +* [#18263](https://github.com/netbox-community/netbox/issues/18263) - Fix recalculation of cable paths when modifying cable terminations via the REST API +* [#18271](https://github.com/netbox-community/netbox/issues/18271) - Require only encryption _or_ authentication algorithm when creating an IPSec proposal via the REST API +* [#18289](https://github.com/netbox-community/netbox/issues/18289) - Enable ordering modules and module types by created & last updated times + +--- + +## v4.1.10 (2024-12-23) + +### Bug Fixes + +* [#18260](https://github.com/netbox-community/netbox/issues/18260) - Fix object change logging + +--- + +## v4.1.9 (2024-12-17) + +!!! danger "Do Not Use" + This release contains a regression which breaks change logging. Please use release v4.1.10 instead. + +### Enhancements + +* [#17215](https://github.com/netbox-community/netbox/issues/17215) - Change the highlighted color of disabled interfaces in interface lists +* [#18224](https://github.com/netbox-community/netbox/issues/18224) - Apply all registered request processors when running custom scripts + +### Bug Fixes + +* [#16757](https://github.com/netbox-community/netbox/issues/16757) - Fix rendering of IP addresses table when assigning an existing IP address to an interface with global HTMX navigation enabled +* [#17868](https://github.com/netbox-community/netbox/issues/17868) - Fix `ZeroDivisionError` exception under specific circumstances when generating a cable trace +* [#18124](https://github.com/netbox-community/netbox/issues/18124) - Enable referencing cable attributes when querying a `cabletermination_set` via the GraphQL API +* [#18230](https://github.com/netbox-community/netbox/issues/18230) - Fix `AttributeError` exception when attempting to edit an IP address assigned to a virtual machine interface + +--- + +## v4.1.8 (2024-12-12) + +### Enhancements + +* [#17071](https://github.com/netbox-community/netbox/issues/17071) - Enable OOB IP address designation during bulk import +* [#17465](https://github.com/netbox-community/netbox/issues/17465) - Enable designation of rack type during bulk import & bulk edit +* [#17889](https://github.com/netbox-community/netbox/issues/17889) - Enable designating an IP address as out-of-band for a device upon creation +* [#17960](https://github.com/netbox-community/netbox/issues/17960) - Add L2TP, PPTP, Wireguard, and OpenVPN tunnel types +* [#18021](https://github.com/netbox-community/netbox/issues/18021) - Automatically clear cache on restart when `DEBUG` is enabled +* [#18061](https://github.com/netbox-community/netbox/issues/18061) - Omit stack trace from rendered device/VM configuration when an exception is raised +* [#18065](https://github.com/netbox-community/netbox/issues/18065) - Include status in device details when hovering on rack elevation +* [#18211](https://github.com/netbox-community/netbox/issues/18211) - Enable the dynamic registration of context managers for request processing + +### Bug Fixes + +* [#14044](https://github.com/netbox-community/netbox/issues/14044) - Fix unhandled AttributeError exception when bulk renaming objects +* [#17490](https://github.com/netbox-community/netbox/issues/17490) - Fix dynamic inclusion support for config templates +* [#17810](https://github.com/netbox-community/netbox/issues/17810) - Fix validation of racked device fields when modifying via REST API +* [#17820](https://github.com/netbox-community/netbox/issues/17820) - Ensure default custom field values are populated when creating new modules +* [#18044](https://github.com/netbox-community/netbox/issues/18044) - Show plugin-generated alerts within UI views for custom scripts +* [#18150](https://github.com/netbox-community/netbox/issues/18150) - Fix REST API pagination for low `MAX_PAGE_SIZE` values +* [#18183](https://github.com/netbox-community/netbox/issues/18183) - Omit UI navigation bar when printing +* [#18213](https://github.com/netbox-community/netbox/issues/18213) - Fix searching for ASN ranges by name + +--- + +## v4.1.7 (2024-11-21) + +### Enhancements + +* [#15239](https://github.com/netbox-community/netbox/issues/15239) - Enable adding/removing individual VLANs while bulk editing device interfaces +* [#17871](https://github.com/netbox-community/netbox/issues/17871) - Enable the assignment/removal of virtualization cluster via device bulk edit +* [#17934](https://github.com/netbox-community/netbox/issues/17934) - Add 1000Base-LX interface type +* [#18007](https://github.com/netbox-community/netbox/issues/18007) - Hide sensitive parameters under data source view (even for privileged users) + +### Bug Fixes + +* [#17459](https://github.com/netbox-community/netbox/issues/17459) - Correct help text on `name` field of module type component templates +* [#17901](https://github.com/netbox-community/netbox/issues/17901) - Ensure GraphiQL UI resources are served locally +* [#17921](https://github.com/netbox-community/netbox/issues/17921) - Fix scheduling of recurring custom scripts +* [#17923](https://github.com/netbox-community/netbox/issues/17923) - Fix the execution of custom scripts via REST API & management command +* [#17963](https://github.com/netbox-community/netbox/issues/17963) - Fix selection of all listed objects during bulk edit +* [#17969](https://github.com/netbox-community/netbox/issues/17969) - Fix system info export when a config revision exists +* [#17972](https://github.com/netbox-community/netbox/issues/17972) - Force evaluation of `LOGIN_REQUIRED` when requesting static media +* [#17986](https://github.com/netbox-community/netbox/issues/17986) - Correct labels for virtual machine & virtual disk size properties +* [#18037](https://github.com/netbox-community/netbox/issues/18037) - Fix validation of maximum VLAN ID value when defining VLAN groups +* [#18038](https://github.com/netbox-community/netbox/issues/18038) - The `to_grams()` utility function should always return an integer value + +--- + +## v4.1.6 (2024-10-31) + +### Bug Fixes + +* [#17700](https://github.com/netbox-community/netbox/issues/17700) - Fix warning when no scripts are found within a script module +* [#17884](https://github.com/netbox-community/netbox/issues/17884) - Fix translation support for certain tab headings +* [#17885](https://github.com/netbox-community/netbox/issues/17885) - Fix regression preventing custom scripts from executing + +## v4.1.5 (2024-10-28) + +### Enhancements + +* [#17789](https://github.com/netbox-community/netbox/issues/17789) - Provide a single "scope" field for bulk editing VLAN group scope assignments + +### Bug Fixes + +* [#17358](https://github.com/netbox-community/netbox/issues/17358) - Fix validation of overlapping IP ranges +* [#17374](https://github.com/netbox-community/netbox/issues/17374) - Fix styling of highlighted table rows in dark mode +* [#17460](https://github.com/netbox-community/netbox/issues/17460) - Ensure bulk action buttons are consistent for device type components +* [#17635](https://github.com/netbox-community/netbox/issues/17635) - Ensure AbortTransaction is caught when running a custom script with `commit=False` +* [#17685](https://github.com/netbox-community/netbox/issues/17685) - Ensure background jobs are validated before being scheduled +* [#17710](https://github.com/netbox-community/netbox/issues/17710) - Remove cached fields on CableTermination model from GraphQL API +* [#17740](https://github.com/netbox-community/netbox/issues/17740) - Ensure support for image attachments with a `.webp` file extension +* [#17749](https://github.com/netbox-community/netbox/issues/17749) - Restore missing `devicetypes` and `children` fields for several objects in GraphQL API +* [#17754](https://github.com/netbox-community/netbox/issues/17754) - Remove paginator from version history table under plugin view +* [#17759](https://github.com/netbox-community/netbox/issues/17759) - Retain `job_timeout` value when scheduling a recurring custom script +* [#17774](https://github.com/netbox-community/netbox/issues/17774) - Fix SSO login support for Entra ID (formerly Azure AD) +* [#17802](https://github.com/netbox-community/netbox/issues/17802) - Fix background color for bulk rename buttons in list views +* [#17838](https://github.com/netbox-community/netbox/issues/17838) - Adjust `manage.py` to reference `python3` executable + +--- + ## v4.1.4 (2024-10-15) ### Enhancements diff --git a/docs/release-notes/version-4.2.md b/docs/release-notes/version-4.2.md new file mode 100644 index 000000000..f0ad3766c --- /dev/null +++ b/docs/release-notes/version-4.2.md @@ -0,0 +1,126 @@ +# NetBox v4.2 + +## v4.2-beta1 (2024-12-02) + +!!! danger "Not for Production Use" + This is a beta release of NetBox intended for testing and evaluation. **Do not use this software in production.** Also be aware that no upgrade path is provided to future releases. + +### Breaking Changes + +* Support for the Django admin UI has been completely removed. (The Django admin UI was disabled by default in NetBox v4.0.) +* NetBox has adopted collation-based natural ordering for many models. This may alter the order in which some objects are listed by default. +* Automatic redirects from pre-v4.1 UI views for virtual disks have been removed. +* The `site` and `provider_network` foreign key fields on `circuits.CircuitTermination` have been replaced by the `termination` generic foreign key. +* The `site` foreign key field on `ipam.Prefix` has been replaced by the `scope` generic foreign key. +* The `site` foreign key field on `virtualization.Cluster` has been replaced by the `scope` generic foreign key. +* The `circuit` foreign key field on `circuits.CircuitGroupAssignment` has been replaced by the `member` generic foreign key. +* Obsolete nested REST API serializers have been removed. These were deprecated in NetBox v4.1 under [#17143](https://github.com/netbox-community/netbox/issues/17143). + +### New Features + +#### Assign Multiple MAC Addresses per Interface ([#4867](https://github.com/netbox-community/netbox/issues/4867)) + +MAC addresses are now managed as independent objects, rather than attributes on device and VM interfaces. NetBox now supports the assignment of multiple MAC addresses per interface, and allows a primary MAC address to be designated for each. + +#### Quick Add UI Widget ([#5858](https://github.com/netbox-community/netbox/issues/5858)) + +A new UI widget has been introduced to enable conveniently creating new related objects while creating or editing an object. For instance, it is now possible to create and assign a new device role when creating or editing a device from within the device form. + +#### VLAN Translation ([#7336](https://github.com/netbox-community/netbox/issues/7336)) + +User can now define policies which track the translation of VLAN IDs on IEEE 802.1Q-encapsulated interfaces. Translation policies can be reused across multiple interfaces. + +#### Virtual Circuits ([#13086](https://github.com/netbox-community/netbox/issues/13086)) + +New models have been introduced to support the documentation of virtual circuits as an extension to the physical circuit modeling already supported. This enables users to accurately reflect point-to-point or multipoint virtual circuits atop infrastructure comprising physical circuits and cables. + +#### Q-in-Q Encapsulation ([#13428](https://github.com/netbox-community/netbox/issues/13428)) + +NetBox now supports the designation of customer VLANs (CVLANs) and service VLANs (SVLANs) to support IEEE 802.1ad/Q-in-Q encapsulation. Each interface can now have it mode designated "Q-in-Q" and be assigned an SVLAN. + +### Enhancements + +* [#6414](https://github.com/netbox-community/netbox/issues/6414) - Prefixes can now be scoped by region, site group, site, or location +* [#7699](https://github.com/netbox-community/netbox/issues/7699) - Virtualization clusters can now be scoped by region, site group, site, or location +* [#9604](https://github.com/netbox-community/netbox/issues/9604) - The scope of a circuit termination now include a region, site group, site, location, or provider network +* [#10711](https://github.com/netbox-community/netbox/issues/10711) - Wireless LANs can now be scoped by region, site group, site, or location +* [#11279](https://github.com/netbox-community/netbox/issues/11279) - Improved the use of natural ordering for various models throughout the application +* [#12596](https://github.com/netbox-community/netbox/issues/12596) - Extended the virtualization clusters REST API endpoint to report on allocated VM resources +* [#16547](https://github.com/netbox-community/netbox/issues/16547) - Add a geographic distance field for circuits +* [#16783](https://github.com/netbox-community/netbox/issues/16783) - Add an operational status field for inventory items +* [#17195](https://github.com/netbox-community/netbox/issues/17195) - Add a color field for power outlets + +### Plugins + +* [#15093](https://github.com/netbox-community/netbox/issues/15093) - Introduced the `events_pipeline` configuration parameter, which allows plugins to hook into NetBox event processing +* [#16546](https://github.com/netbox-community/netbox/issues/16546) - NetBoxModel now provides a default `get_absolute_url()` method +* [#16971](https://github.com/netbox-community/netbox/issues/16971) - Plugins can now easily register system jobs to perform background tasks +* [#17029](https://github.com/netbox-community/netbox/issues/17029) - Registering a `PluginTemplateExtension` subclass for a single model has been deprecated (replace `model` with `models`) +* [#18023](https://github.com/netbox-community/netbox/issues/18023) - Extend `register_model_view()` to handle list views + +### Other Changes + +* [#16136](https://github.com/netbox-community/netbox/issues/16136) - Removed support for the Django admin UI +* [#17165](https://github.com/netbox-community/netbox/issues/17165) - All obsolete nested REST API serializers have been removed +* [#17472](https://github.com/netbox-community/netbox/issues/17472) - The legacy staged changes API has been deprecated, and will be removed in Netbox v4.3 +* [#17476](https://github.com/netbox-community/netbox/issues/17476) - Upgrade to Django 5.1 +* [#17752](https://github.com/netbox-community/netbox/issues/17752) - Bulk object import URL paths have been renamed from `*_import` to `*_bulk_import` +* [#17761](https://github.com/netbox-community/netbox/issues/17761) - Optional choice fields now store empty values as null (rather than empty strings) in the database +* [#18093](https://github.com/netbox-community/netbox/issues/18093) - Redirects for pre-v4.1 virtual disk UI views have been removed + +### REST API Changes + +* Added the following endpoints: + * `/api/circuits/virtual-circuits/` + * `/api/circuits/virtual-circuit-terminations/` + * `/api/dcim/mac-addresses/` + * `/api/ipam/vlan-translation-policies/` + * `/api/ipam/vlan-translation-rules/` +* circuits.Circuit + * Added the optional `distance` and `distance_unit` fields +* circuits.CircuitGroupAssignment + * Replaced the `circuit` field with `member_type` and `member_id` to support virtual circuit assignment +* circuits.CircuitTermination + * Removed the `site` & `provider_network` fields + * Added the `termination_type` & `termination_id` fields to facilitate termination assignment + * Added the read-only `termination` field +* dcim.Interface + * The `mac_address` field is now read-only + * Added the `primary_mac_address` relation to dcim.MACAddress + * Added the read-only `mac_addresses` list + * Added the `qinq_svlan` relation to ipam.VLAN + * Added the `vlan_translation_policy` relation to ipam.VLANTranslationPolicy + * Added `mode` choice "Q-in-Q" +* dcim.InventoryItem + * Added the optional `status` choice field +* dcim.Location + * Added the read-only `prefix_count` field +* dcim.PowerOutlet + * Added the optional `color` field +* dcim.Region + * Added the read-only `prefix_count` field +* dcim.SiteGroup + * Added the read-only `prefix_count` field +* ipam.Prefix + * Removed the `site` field + * Added the `scope_type` & `scope_id` fields to facilitate scope assignment + * Added the read-only `scope` field +* ipam.VLAN + * Added the optional `qinq_role` selection field + * Added the `qinq_svlan` recursive relation +* virtualization.Cluster + * Removed the `site` field + * Added the `scope_type` & `scope_id` fields to facilitate scope assignment + * Added the read-only `scope` field +* virtualization.Cluster + * Added the read-only fields `allocated_vcpus`, `allocated_memory`, and `allocated_disk` +* virtualization.VMInterface + * The `mac_address` field is now read-only + * Added the `primary_mac_address` relation to dcim.MACAddress + * Added the read-only `mac_addresses` list + * Added the `qinq_svlan` relation to ipam.VLAN + * Added the `vlan_translation_policy` relation to ipam.VLANTranslationPolicy + * Added `mode` choice "Q-in-Q" +* wireless.WirelessLAN + * Added the `scope_type` & `scope_id` fields to support scope assignment + * Added the read-only `scope` field diff --git a/mkdocs.yml b/mkdocs.yml index 94a4edcb3..f870b69d6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -156,6 +156,7 @@ nav: - Administration: - Authentication: - Overview: 'administration/authentication/overview.md' + - Google: 'administration/authentication/google.md' - Microsoft Entra ID: 'administration/authentication/microsoft-entra-id.md' - Okta: 'administration/authentication/okta.md' - Permissions: 'administration/permissions.md' @@ -173,6 +174,8 @@ nav: - Provider: 'models/circuits/provider.md' - Provider Account: 'models/circuits/provideraccount.md' - Provider Network: 'models/circuits/providernetwork.md' + - Virtual Circuit: 'models/circuits/virtualcircuit.md' + - Virtual Circuit Termination: 'models/circuits/virtualcircuittermination.md' - Core: - DataFile: 'models/core/datafile.md' - DataSource: 'models/core/datasource.md' @@ -196,6 +199,7 @@ nav: - InventoryItemRole: 'models/dcim/inventoryitemrole.md' - InventoryItemTemplate: 'models/dcim/inventoryitemtemplate.md' - Location: 'models/dcim/location.md' + - MACAddress: 'models/dcim/macaddress.md' - Manufacturer: 'models/dcim/manufacturer.md' - Module: 'models/dcim/module.md' - ModuleBay: 'models/dcim/modulebay.md' @@ -254,6 +258,8 @@ nav: - ServiceTemplate: 'models/ipam/servicetemplate.md' - VLAN: 'models/ipam/vlan.md' - VLANGroup: 'models/ipam/vlangroup.md' + - VLANTranslationPolicy: 'models/ipam/vlantranslationpolicy.md' + - VLANTranslationRule: 'models/ipam/vlantranslationrule.md' - VRF: 'models/ipam/vrf.md' - Tenancy: - Contact: 'models/tenancy/contact.md' @@ -305,6 +311,7 @@ nav: - git Cheat Sheet: 'development/git-cheat-sheet.md' - Release Notes: - Summary: 'release-notes/index.md' + - Version 4.2: 'release-notes/version-4.2.md' - Version 4.1: 'release-notes/version-4.1.md' - Version 4.0: 'release-notes/version-4.0.md' - Version 3.7: 'release-notes/version-3.7.md' diff --git a/netbox/circuits/api/nested_serializers.py b/netbox/circuits/api/nested_serializers.py deleted file mode 100644 index 487749872..000000000 --- a/netbox/circuits/api/nested_serializers.py +++ /dev/null @@ -1,79 +0,0 @@ -import warnings - -from drf_spectacular.utils import extend_schema_serializer - -from circuits.models import * -from netbox.api.fields import RelatedObjectCountField -from netbox.api.serializers import WritableNestedSerializer -from .serializers_.nested import NestedProviderAccountSerializer - -__all__ = [ - 'NestedCircuitSerializer', - 'NestedCircuitTerminationSerializer', - 'NestedCircuitTypeSerializer', - 'NestedProviderNetworkSerializer', - 'NestedProviderSerializer', - 'NestedProviderAccountSerializer', -] - -# TODO: Remove in v4.2 -warnings.warn( - "Dedicated nested serializers will be removed in NetBox v4.2. Use Serializer(nested=True) instead.", - DeprecationWarning -) - - -# -# Provider networks -# - -class NestedProviderNetworkSerializer(WritableNestedSerializer): - - class Meta: - model = ProviderNetwork - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -# -# Providers -# - -@extend_schema_serializer( - exclude_fields=('circuit_count',), -) -class NestedProviderSerializer(WritableNestedSerializer): - circuit_count = RelatedObjectCountField('circuits') - - class Meta: - model = Provider - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'circuit_count'] - - -# -# Circuits -# - -@extend_schema_serializer( - exclude_fields=('circuit_count',), -) -class NestedCircuitTypeSerializer(WritableNestedSerializer): - circuit_count = RelatedObjectCountField('circuits') - - class Meta: - model = CircuitType - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'circuit_count'] - - -class NestedCircuitSerializer(WritableNestedSerializer): - - class Meta: - model = Circuit - fields = ['id', 'url', 'display_url', 'display', 'cid'] - - -class NestedCircuitTerminationSerializer(WritableNestedSerializer): - circuit = NestedCircuitSerializer() - - class Meta: - model = CircuitTermination - fields = ['id', 'url', 'display_url', 'display', 'circuit', 'term_side', 'cable', '_occupied'] diff --git a/netbox/circuits/api/serializers_/circuits.py b/netbox/circuits/api/serializers_/circuits.py index 111fa6f87..70b57a688 100644 --- a/netbox/circuits/api/serializers_/circuits.py +++ b/netbox/circuits/api/serializers_/circuits.py @@ -1,12 +1,20 @@ -from circuits.choices import CircuitPriorityChoices, CircuitStatusChoices -from circuits.models import Circuit, CircuitGroup, CircuitGroupAssignment, CircuitTermination, CircuitType +from django.contrib.contenttypes.models import ContentType +from drf_spectacular.utils import extend_schema_field +from rest_framework import serializers + +from circuits.choices import CircuitPriorityChoices, CircuitStatusChoices, VirtualCircuitTerminationRoleChoices +from circuits.constants import CIRCUIT_GROUP_ASSIGNMENT_MEMBER_MODELS, CIRCUIT_TERMINATION_TERMINATION_TYPES +from circuits.models import ( + Circuit, CircuitGroup, CircuitGroupAssignment, CircuitTermination, CircuitType, VirtualCircuit, + VirtualCircuitTermination, VirtualCircuitType, +) +from dcim.api.serializers_.device_components import InterfaceSerializer from dcim.api.serializers_.cables import CabledObjectSerializer -from dcim.api.serializers_.sites import SiteSerializer -from netbox.api.fields import ChoiceField, RelatedObjectCountField +from netbox.api.fields import ChoiceField, ContentTypeField, RelatedObjectCountField from netbox.api.serializers import NetBoxModelSerializer, WritableNestedSerializer from netbox.choices import DistanceUnitChoices from tenancy.api.serializers_.tenants import TenantSerializer - +from utilities.api import get_serializer_for_model from .providers import ProviderAccountSerializer, ProviderNetworkSerializer, ProviderSerializer __all__ = ( @@ -15,6 +23,9 @@ __all__ = ( 'CircuitGroupSerializer', 'CircuitTerminationSerializer', 'CircuitTypeSerializer', + 'VirtualCircuitSerializer', + 'VirtualCircuitTerminationSerializer', + 'VirtualCircuitTypeSerializer', ) @@ -33,16 +44,32 @@ class CircuitTypeSerializer(NetBoxModelSerializer): class CircuitCircuitTerminationSerializer(WritableNestedSerializer): - site = SiteSerializer(nested=True, allow_null=True) - provider_network = ProviderNetworkSerializer(nested=True, allow_null=True) + termination_type = ContentTypeField( + queryset=ContentType.objects.filter( + model__in=CIRCUIT_TERMINATION_TERMINATION_TYPES + ), + allow_null=True, + required=False, + default=None + ) + termination_id = serializers.IntegerField(allow_null=True, required=False, default=None) + termination = serializers.SerializerMethodField(read_only=True) class Meta: model = CircuitTermination fields = [ - 'id', 'url', 'display_url', 'display', 'site', 'provider_network', 'port_speed', 'upstream_speed', - 'xconnect_id', 'description', + 'id', 'url', 'display_url', 'display', 'termination_type', 'termination_id', 'termination', 'port_speed', + 'upstream_speed', 'xconnect_id', 'description', ] + @extend_schema_field(serializers.JSONField(allow_null=True)) + def get_termination(self, obj): + if obj.termination_id is None: + return None + serializer = get_serializer_for_model(obj.termination) + context = {'request': self.context['request']} + return serializer(obj.termination, nested=True, context=context).data + class CircuitGroupSerializer(NetBoxModelSerializer): tenant = TenantSerializer(nested=True, required=False, allow_null=True) @@ -77,43 +104,117 @@ class CircuitSerializer(NetBoxModelSerializer): provider_account = ProviderAccountSerializer(nested=True, required=False, allow_null=True, default=None) status = ChoiceField(choices=CircuitStatusChoices, required=False) type = CircuitTypeSerializer(nested=True) + distance_unit = ChoiceField(choices=DistanceUnitChoices, allow_blank=True, required=False, allow_null=True) tenant = TenantSerializer(nested=True, required=False, allow_null=True) termination_a = CircuitCircuitTerminationSerializer(read_only=True, allow_null=True) termination_z = CircuitCircuitTerminationSerializer(read_only=True, allow_null=True) assignments = CircuitGroupAssignmentSerializer_(nested=True, many=True, required=False) - distance_unit = ChoiceField(choices=DistanceUnitChoices, allow_blank=True, required=False, allow_null=True) class Meta: model = Circuit fields = [ 'id', 'url', 'display_url', 'display', 'cid', 'provider', 'provider_account', 'type', 'status', 'tenant', - 'install_date', 'termination_date', 'commit_rate', 'description', 'termination_a', 'termination_z', - 'distance', 'distance_unit', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'assignments', + 'install_date', 'termination_date', 'commit_rate', 'description', 'distance', 'distance_unit', + 'termination_a', 'termination_z', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', + 'assignments', ] brief_fields = ('id', 'url', 'display', 'provider', 'cid', 'description') class CircuitTerminationSerializer(NetBoxModelSerializer, CabledObjectSerializer): circuit = CircuitSerializer(nested=True) - site = SiteSerializer(nested=True, required=False, allow_null=True) - provider_network = ProviderNetworkSerializer(nested=True, required=False, allow_null=True) + termination_type = ContentTypeField( + queryset=ContentType.objects.filter( + model__in=CIRCUIT_TERMINATION_TERMINATION_TYPES + ), + allow_null=True, + required=False, + default=None + ) + termination_id = serializers.IntegerField(allow_null=True, required=False, default=None) + termination = serializers.SerializerMethodField(read_only=True) class Meta: model = CircuitTermination fields = [ - 'id', 'url', 'display_url', 'display', 'circuit', 'term_side', 'site', 'provider_network', 'port_speed', - 'upstream_speed', 'xconnect_id', 'pp_info', 'description', 'mark_connected', 'cable', 'cable_end', - 'link_peers', 'link_peers_type', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied', + 'id', 'url', 'display_url', 'display', 'circuit', 'term_side', 'termination_type', 'termination_id', + 'termination', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description', 'mark_connected', + 'cable', 'cable_end', 'link_peers', 'link_peers_type', 'tags', 'custom_fields', 'created', 'last_updated', + '_occupied', ] brief_fields = ('id', 'url', 'display', 'circuit', 'term_side', 'description', 'cable', '_occupied') + @extend_schema_field(serializers.JSONField(allow_null=True)) + def get_termination(self, obj): + if obj.termination_id is None: + return None + serializer = get_serializer_for_model(obj.termination) + context = {'request': self.context['request']} + return serializer(obj.termination, nested=True, context=context).data + class CircuitGroupAssignmentSerializer(CircuitGroupAssignmentSerializer_): - circuit = CircuitSerializer(nested=True) + member_type = ContentTypeField( + queryset=ContentType.objects.filter(CIRCUIT_GROUP_ASSIGNMENT_MEMBER_MODELS) + ) + member = serializers.SerializerMethodField(read_only=True) class Meta: model = CircuitGroupAssignment fields = [ - 'id', 'url', 'display_url', 'display', 'group', 'circuit', 'priority', 'tags', 'created', 'last_updated', + 'id', 'url', 'display_url', 'display', 'group', 'member_type', 'member_id', 'member', 'priority', 'tags', + 'created', 'last_updated', ] - brief_fields = ('id', 'url', 'display', 'group', 'circuit', 'priority') + brief_fields = ('id', 'url', 'display', 'group', 'member_type', 'member_id', 'member', 'priority') + + @extend_schema_field(serializers.JSONField(allow_null=True)) + def get_member(self, obj): + if obj.member_id is None: + return None + serializer = get_serializer_for_model(obj.member) + context = {'request': self.context['request']} + return serializer(obj.member, nested=True, context=context).data + + +class VirtualCircuitTypeSerializer(NetBoxModelSerializer): + + # Related object counts + virtual_circuit_count = RelatedObjectCountField('virtual_circuits') + + class Meta: + model = VirtualCircuitType + fields = [ + 'id', 'url', 'display_url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields', + 'created', 'last_updated', 'virtual_circuit_count', + ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'virtual_circuit_count') + + +class VirtualCircuitSerializer(NetBoxModelSerializer): + provider_network = ProviderNetworkSerializer(nested=True) + provider_account = ProviderAccountSerializer(nested=True, required=False, allow_null=True, default=None) + type = VirtualCircuitTypeSerializer(nested=True) + status = ChoiceField(choices=CircuitStatusChoices, required=False) + tenant = TenantSerializer(nested=True, required=False, allow_null=True) + + class Meta: + model = VirtualCircuit + fields = [ + 'id', 'url', 'display_url', 'display', 'cid', 'provider_network', 'provider_account', 'type', 'status', + 'tenant', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', + ] + brief_fields = ('id', 'url', 'display', 'provider_network', 'cid', 'description') + + +class VirtualCircuitTerminationSerializer(NetBoxModelSerializer, CabledObjectSerializer): + virtual_circuit = VirtualCircuitSerializer(nested=True) + role = ChoiceField(choices=VirtualCircuitTerminationRoleChoices, required=False) + interface = InterfaceSerializer(nested=True) + + class Meta: + model = VirtualCircuitTermination + fields = [ + 'id', 'url', 'display_url', 'display', 'virtual_circuit', 'role', 'interface', 'description', 'tags', + 'custom_fields', 'created', 'last_updated', + ] + brief_fields = ('id', 'url', 'display', 'virtual_circuit', 'role', 'interface', 'description') diff --git a/netbox/circuits/api/urls.py b/netbox/circuits/api/urls.py index 00af3dec6..3be620bd2 100644 --- a/netbox/circuits/api/urls.py +++ b/netbox/circuits/api/urls.py @@ -17,5 +17,10 @@ router.register('circuit-terminations', views.CircuitTerminationViewSet) router.register('circuit-groups', views.CircuitGroupViewSet) router.register('circuit-group-assignments', views.CircuitGroupAssignmentViewSet) +# Virtual circuits +router.register('virtual-circuits', views.VirtualCircuitViewSet) +router.register('virtual-circuit-types', views.VirtualCircuitTypeViewSet) +router.register('virtual-circuit-terminations', views.VirtualCircuitTerminationViewSet) + app_name = 'circuits-api' urlpatterns = router.urls diff --git a/netbox/circuits/api/views.py b/netbox/circuits/api/views.py index 8cce013d7..05540d9ad 100644 --- a/netbox/circuits/api/views.py +++ b/netbox/circuits/api/views.py @@ -93,3 +93,33 @@ class ProviderNetworkViewSet(NetBoxModelViewSet): queryset = ProviderNetwork.objects.all() serializer_class = serializers.ProviderNetworkSerializer filterset_class = filtersets.ProviderNetworkFilterSet + + +# +# Virtual circuit types +# + +class VirtualCircuitTypeViewSet(NetBoxModelViewSet): + queryset = VirtualCircuitType.objects.all() + serializer_class = serializers.VirtualCircuitTypeSerializer + filterset_class = filtersets.VirtualCircuitTypeFilterSet + + +# +# Virtual circuits +# + +class VirtualCircuitViewSet(NetBoxModelViewSet): + queryset = VirtualCircuit.objects.all() + serializer_class = serializers.VirtualCircuitSerializer + filterset_class = filtersets.VirtualCircuitFilterSet + + +# +# Virtual circuit terminations +# + +class VirtualCircuitTerminationViewSet(PassThroughPortMixin, NetBoxModelViewSet): + queryset = VirtualCircuitTermination.objects.all() + serializer_class = serializers.VirtualCircuitTerminationSerializer + filterset_class = filtersets.VirtualCircuitTerminationFilterSet diff --git a/netbox/circuits/choices.py b/netbox/circuits/choices.py index 8c25c7459..4d6132d7a 100644 --- a/netbox/circuits/choices.py +++ b/netbox/circuits/choices.py @@ -92,3 +92,19 @@ class CircuitPriorityChoices(ChoiceSet): (PRIORITY_TERTIARY, _('Tertiary')), (PRIORITY_INACTIVE, _('Inactive')), ] + + +# +# Virtual circuits +# + +class VirtualCircuitTerminationRoleChoices(ChoiceSet): + ROLE_PEER = 'peer' + ROLE_HUB = 'hub' + ROLE_SPOKE = 'spoke' + + CHOICES = [ + (ROLE_PEER, _('Peer'), 'green'), + (ROLE_HUB, _('Hub'), 'blue'), + (ROLE_SPOKE, _('Spoke'), 'orange'), + ] diff --git a/netbox/circuits/constants.py b/netbox/circuits/constants.py new file mode 100644 index 000000000..4642c22a3 --- /dev/null +++ b/netbox/circuits/constants.py @@ -0,0 +1,12 @@ +from django.db.models import Q + + +# models values for ContentTypes which may be CircuitTermination termination types +CIRCUIT_TERMINATION_TERMINATION_TYPES = ( + 'region', 'sitegroup', 'site', 'location', 'providernetwork', +) + +CIRCUIT_GROUP_ASSIGNMENT_MEMBER_MODELS = Q( + app_label='circuits', + model__in=['circuit', 'virtualcircuit'] +) diff --git a/netbox/circuits/filtersets.py b/netbox/circuits/filtersets.py index ebd1fe28d..964f69f83 100644 --- a/netbox/circuits/filtersets.py +++ b/netbox/circuits/filtersets.py @@ -1,13 +1,16 @@ import django_filters +from django.contrib.contenttypes.models import ContentType from django.db.models import Q from django.utils.translation import gettext as _ from dcim.filtersets import CabledObjectFilterSet -from dcim.models import Region, Site, SiteGroup +from dcim.models import Interface, Location, Region, Site, SiteGroup from ipam.models import ASN from netbox.filtersets import NetBoxModelFilterSet, OrganizationalModelFilterSet from tenancy.filtersets import ContactModelFilterSet, TenancyFilterSet -from utilities.filters import TreeNodeMultipleChoiceFilter +from utilities.filters import ( + ContentTypeFilter, MultiValueCharFilter, MultiValueNumberFilter, TreeNodeMultipleChoiceFilter, +) from .choices import * from .models import * @@ -20,43 +23,46 @@ __all__ = ( 'ProviderNetworkFilterSet', 'ProviderAccountFilterSet', 'ProviderFilterSet', + 'VirtualCircuitFilterSet', + 'VirtualCircuitTerminationFilterSet', + 'VirtualCircuitTypeFilterSet', ) class ProviderFilterSet(NetBoxModelFilterSet, ContactModelFilterSet): region_id = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), - field_name='circuits__terminations__site__region', + field_name='circuits__terminations___region', lookup_expr='in', label=_('Region (ID)'), ) region = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), - field_name='circuits__terminations__site__region', + field_name='circuits__terminations___region', lookup_expr='in', to_field_name='slug', label=_('Region (slug)'), ) site_group_id = TreeNodeMultipleChoiceFilter( queryset=SiteGroup.objects.all(), - field_name='circuits__terminations__site__group', + field_name='circuits__terminations___site_group', lookup_expr='in', label=_('Site group (ID)'), ) site_group = TreeNodeMultipleChoiceFilter( queryset=SiteGroup.objects.all(), - field_name='circuits__terminations__site__group', + field_name='circuits__terminations___site_group', lookup_expr='in', to_field_name='slug', label=_('Site group (slug)'), ) site_id = django_filters.ModelMultipleChoiceFilter( - field_name='circuits__terminations__site', + field_name='circuits__terminations___site', queryset=Site.objects.all(), label=_('Site'), ) site = django_filters.ModelMultipleChoiceFilter( - field_name='circuits__terminations__site__slug', + field_name='circuits__terminations___site__slug', queryset=Site.objects.all(), to_field_name='slug', label=_('Site (slug)'), @@ -173,7 +179,7 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte label=_('Provider account (account)'), ) provider_network_id = django_filters.ModelMultipleChoiceFilter( - field_name='terminations__provider_network', + field_name='terminations___provider_network', queryset=ProviderNetwork.objects.all(), label=_('Provider network (ID)'), ) @@ -193,37 +199,37 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte ) region_id = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), - field_name='terminations__site__region', + field_name='terminations___region', lookup_expr='in', label=_('Region (ID)'), ) region = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), - field_name='terminations__site__region', + field_name='terminations___region', lookup_expr='in', to_field_name='slug', label=_('Region (slug)'), ) site_group_id = TreeNodeMultipleChoiceFilter( queryset=SiteGroup.objects.all(), - field_name='terminations__site__group', + field_name='terminations___site_group', lookup_expr='in', label=_('Site group (ID)'), ) site_group = TreeNodeMultipleChoiceFilter( queryset=SiteGroup.objects.all(), - field_name='terminations__site__group', + field_name='terminations___site_group', lookup_expr='in', to_field_name='slug', label=_('Site group (slug)'), ) site_id = django_filters.ModelMultipleChoiceFilter( - field_name='terminations__site', + field_name='terminations___site', queryset=Site.objects.all(), label=_('Site (ID)'), ) site = django_filters.ModelMultipleChoiceFilter( - field_name='terminations__site__slug', + field_name='terminations___site__slug', queryset=Site.objects.all(), to_field_name='slug', label=_('Site (slug)'), @@ -239,7 +245,9 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte class Meta: model = Circuit - fields = ('id', 'cid', 'description', 'install_date', 'termination_date', 'commit_rate', 'distance', 'distance_unit') + fields = ( + 'id', 'cid', 'description', 'install_date', 'termination_date', 'commit_rate', 'distance', 'distance_unit', + ) def search(self, queryset, name, value): if not value.strip(): @@ -263,18 +271,60 @@ class CircuitTerminationFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet): queryset=Circuit.objects.all(), label=_('Circuit'), ) + termination_type = ContentTypeFilter() + region_id = TreeNodeMultipleChoiceFilter( + queryset=Region.objects.all(), + field_name='_region', + lookup_expr='in', + label=_('Region (ID)'), + ) + region = TreeNodeMultipleChoiceFilter( + queryset=Region.objects.all(), + field_name='_region', + lookup_expr='in', + to_field_name='slug', + label=_('Region (slug)'), + ) + site_group_id = TreeNodeMultipleChoiceFilter( + queryset=SiteGroup.objects.all(), + field_name='_site_group', + lookup_expr='in', + label=_('Site group (ID)'), + ) + site_group = TreeNodeMultipleChoiceFilter( + queryset=SiteGroup.objects.all(), + field_name='_site_group', + lookup_expr='in', + to_field_name='slug', + label=_('Site group (slug)'), + ) site_id = django_filters.ModelMultipleChoiceFilter( queryset=Site.objects.all(), + field_name='_site', label=_('Site (ID)'), ) site = django_filters.ModelMultipleChoiceFilter( - field_name='site__slug', + field_name='_site__slug', queryset=Site.objects.all(), to_field_name='slug', label=_('Site (slug)'), ) + location_id = TreeNodeMultipleChoiceFilter( + queryset=Location.objects.all(), + field_name='_location', + lookup_expr='in', + label=_('Location (ID)'), + ) + location = TreeNodeMultipleChoiceFilter( + queryset=Location.objects.all(), + field_name='_location', + lookup_expr='in', + to_field_name='slug', + label=_('Location (slug)'), + ) provider_network_id = django_filters.ModelMultipleChoiceFilter( queryset=ProviderNetwork.objects.all(), + field_name='_provider_network', label=_('ProviderNetwork (ID)'), ) provider_id = django_filters.ModelMultipleChoiceFilter( @@ -292,8 +342,8 @@ class CircuitTerminationFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet): class Meta: model = CircuitTermination fields = ( - 'id', 'term_side', 'port_speed', 'upstream_speed', 'xconnect_id', 'description', 'mark_connected', - 'pp_info', 'cable_end', + 'id', 'termination_id', 'term_side', 'port_speed', 'upstream_speed', 'xconnect_id', 'description', + 'mark_connected', 'pp_info', 'cable_end', ) def search(self, queryset, name, value): @@ -319,26 +369,36 @@ class CircuitGroupAssignmentFilterSet(NetBoxModelFilterSet): method='search', label=_('Search'), ) - provider_id = django_filters.ModelMultipleChoiceFilter( - field_name='circuit__provider', - queryset=Provider.objects.all(), - label=_('Provider (ID)'), + member_type = ContentTypeFilter() + circuit = MultiValueCharFilter( + method='filter_circuit', + field_name='cid', + label=_('Circuit (CID)'), ) - provider = django_filters.ModelMultipleChoiceFilter( - field_name='circuit__provider__slug', - queryset=Provider.objects.all(), - to_field_name='slug', - label=_('Provider (slug)'), - ) - circuit_id = django_filters.ModelMultipleChoiceFilter( - queryset=Circuit.objects.all(), + circuit_id = MultiValueNumberFilter( + method='filter_circuit', + field_name='pk', label=_('Circuit (ID)'), ) - circuit = django_filters.ModelMultipleChoiceFilter( - field_name='circuit__cid', - queryset=Circuit.objects.all(), - to_field_name='cid', - label=_('Circuit (CID)'), + virtual_circuit = MultiValueCharFilter( + method='filter_virtual_circuit', + field_name='cid', + label=_('Virtual circuit (CID)'), + ) + virtual_circuit_id = MultiValueNumberFilter( + method='filter_virtual_circuit', + field_name='pk', + label=_('Virtual circuit (ID)'), + ) + provider = MultiValueCharFilter( + method='filter_provider', + field_name='slug', + label=_('Provider (name)'), + ) + provider_id = MultiValueNumberFilter( + method='filter_provider', + field_name='pk', + label=_('Provider (ID)'), ) group_id = django_filters.ModelMultipleChoiceFilter( queryset=CircuitGroup.objects.all(), @@ -353,12 +413,173 @@ class CircuitGroupAssignmentFilterSet(NetBoxModelFilterSet): class Meta: model = CircuitGroupAssignment - fields = ('id', 'priority') + fields = ('id', 'member_id', 'priority') def search(self, queryset, name, value): if not value.strip(): return queryset return queryset.filter( - Q(circuit__cid__icontains=value) | + Q(member__cid__icontains=value) | Q(group__name__icontains=value) ) + + def filter_circuit(self, queryset, name, value): + circuits = Circuit.objects.filter(**{f'{name}__in': value}) + if not circuits.exists(): + return queryset.none() + return queryset.filter( + Q( + member_type=ContentType.objects.get_for_model(Circuit), + member_id__in=circuits + ) + ) + + def filter_virtual_circuit(self, queryset, name, value): + virtual_circuits = VirtualCircuit.objects.filter(**{f'{name}__in': value}) + if not virtual_circuits.exists(): + return queryset.none() + return queryset.filter( + Q( + member_type=ContentType.objects.get_for_model(VirtualCircuit), + member_id__in=virtual_circuits + ) + ) + + def filter_provider(self, queryset, name, value): + providers = Provider.objects.filter(**{f'{name}__in': value}) + if not providers.exists(): + return queryset.none() + circuits = Circuit.objects.filter(provider__in=providers) + virtual_circuits = VirtualCircuit.objects.filter(provider_network__provider__in=providers) + return queryset.filter( + Q( + member_type=ContentType.objects.get_for_model(Circuit), + member_id__in=circuits + ) | + Q( + member_type=ContentType.objects.get_for_model(VirtualCircuit), + member_id__in=virtual_circuits + ) + ) + + +class VirtualCircuitTypeFilterSet(OrganizationalModelFilterSet): + + class Meta: + model = VirtualCircuitType + fields = ('id', 'name', 'slug', 'color', 'description') + + +class VirtualCircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet): + provider_id = django_filters.ModelMultipleChoiceFilter( + field_name='provider_network__provider', + queryset=Provider.objects.all(), + label=_('Provider (ID)'), + ) + provider = django_filters.ModelMultipleChoiceFilter( + field_name='provider_network__provider__slug', + queryset=Provider.objects.all(), + to_field_name='slug', + label=_('Provider (slug)'), + ) + provider_account_id = django_filters.ModelMultipleChoiceFilter( + field_name='provider_account', + queryset=ProviderAccount.objects.all(), + label=_('Provider account (ID)'), + ) + provider_account = django_filters.ModelMultipleChoiceFilter( + field_name='provider_account__account', + queryset=Provider.objects.all(), + to_field_name='account', + label=_('Provider account (account)'), + ) + provider_network_id = django_filters.ModelMultipleChoiceFilter( + queryset=ProviderNetwork.objects.all(), + label=_('Provider network (ID)'), + ) + type_id = django_filters.ModelMultipleChoiceFilter( + queryset=VirtualCircuitType.objects.all(), + label=_('Virtual circuit type (ID)'), + ) + type = django_filters.ModelMultipleChoiceFilter( + field_name='type__slug', + queryset=VirtualCircuitType.objects.all(), + to_field_name='slug', + label=_('Virtual circuit type (slug)'), + ) + status = django_filters.MultipleChoiceFilter( + choices=CircuitStatusChoices, + null_value=None + ) + + class Meta: + model = VirtualCircuit + fields = ('id', 'cid', 'description') + + def search(self, queryset, name, value): + if not value.strip(): + return queryset + return queryset.filter( + Q(cid__icontains=value) | + Q(description__icontains=value) | + Q(comments__icontains=value) + ).distinct() + + +class VirtualCircuitTerminationFilterSet(NetBoxModelFilterSet): + q = django_filters.CharFilter( + method='search', + label=_('Search'), + ) + virtual_circuit_id = django_filters.ModelMultipleChoiceFilter( + queryset=VirtualCircuit.objects.all(), + label=_('Virtual circuit'), + ) + role = django_filters.MultipleChoiceFilter( + choices=VirtualCircuitTerminationRoleChoices, + null_value=None + ) + provider_id = django_filters.ModelMultipleChoiceFilter( + field_name='virtual_circuit__provider_network__provider', + queryset=Provider.objects.all(), + label=_('Provider (ID)'), + ) + provider = django_filters.ModelMultipleChoiceFilter( + field_name='virtual_circuit__provider_network__provider__slug', + queryset=Provider.objects.all(), + to_field_name='slug', + label=_('Provider (slug)'), + ) + provider_account_id = django_filters.ModelMultipleChoiceFilter( + field_name='virtual_circuit__provider_account', + queryset=ProviderAccount.objects.all(), + label=_('Provider account (ID)'), + ) + provider_account = django_filters.ModelMultipleChoiceFilter( + field_name='virtual_circuit__provider_account__account', + queryset=ProviderAccount.objects.all(), + to_field_name='account', + label=_('Provider account (account)'), + ) + provider_network_id = django_filters.ModelMultipleChoiceFilter( + queryset=ProviderNetwork.objects.all(), + field_name='virtual_circuit__provider_network', + label=_('Provider network (ID)'), + ) + interface_id = django_filters.ModelMultipleChoiceFilter( + queryset=Interface.objects.all(), + field_name='interface', + label=_('Interface (ID)'), + ) + + class Meta: + model = VirtualCircuitTermination + fields = ('id', 'interface_id', 'description') + + def search(self, queryset, name, value): + if not value.strip(): + return queryset + return queryset.filter( + Q(virtual_circuit__cid__icontains=value) | + Q(description__icontains=value) + ).distinct() diff --git a/netbox/circuits/forms/bulk_edit.py b/netbox/circuits/forms/bulk_edit.py index 5cb7b5d30..8d6e8dec1 100644 --- a/netbox/circuits/forms/bulk_edit.py +++ b/netbox/circuits/forms/bulk_edit.py @@ -1,17 +1,25 @@ from django import forms +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ObjectDoesNotExist from django.utils.translation import gettext_lazy as _ -from circuits.choices import CircuitCommitRateChoices, CircuitPriorityChoices, CircuitStatusChoices +from circuits.choices import ( + CircuitCommitRateChoices, CircuitPriorityChoices, CircuitStatusChoices, VirtualCircuitTerminationRoleChoices, +) +from circuits.constants import CIRCUIT_TERMINATION_TERMINATION_TYPES from circuits.models import * from dcim.models import Site from ipam.models import ASN from netbox.choices import DistanceUnitChoices from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant -from utilities.forms import add_blank_choice -from utilities.forms.fields import ColorField, CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField -from utilities.forms.rendering import FieldSet, TabbedGroups -from utilities.forms.widgets import BulkEditNullBooleanSelect, DatePicker, NumberWithOptions +from utilities.forms import add_blank_choice, get_field_value +from utilities.forms.fields import ( + ColorField, CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, +) +from utilities.forms.rendering import FieldSet +from utilities.forms.widgets import BulkEditNullBooleanSelect, DatePicker, HTMXSelect, NumberWithOptions +from utilities.templatetags.builtins.filters import bettertitle __all__ = ( 'CircuitBulkEditForm', @@ -22,6 +30,9 @@ __all__ = ( 'ProviderBulkEditForm', 'ProviderAccountBulkEditForm', 'ProviderNetworkBulkEditForm', + 'VirtualCircuitBulkEditForm', + 'VirtualCircuitTerminationBulkEditForm', + 'VirtualCircuitTypeBulkEditForm', ) @@ -197,15 +208,18 @@ class CircuitTerminationBulkEditForm(NetBoxModelBulkEditForm): max_length=200, required=False ) - site = DynamicModelChoiceField( - label=_('Site'), - queryset=Site.objects.all(), - required=False + termination_type = ContentTypeChoiceField( + queryset=ContentType.objects.filter(model__in=CIRCUIT_TERMINATION_TERMINATION_TYPES), + widget=HTMXSelect(method='post', attrs={'hx-select': '#form_fields'}), + required=False, + label=_('Termination type') ) - provider_network = DynamicModelChoiceField( - label=_('Provider Network'), - queryset=ProviderNetwork.objects.all(), - required=False + termination = DynamicModelChoiceField( + label=_('Termination'), + queryset=Site.objects.none(), # Initial queryset + required=False, + disabled=True, + selector=True ) port_speed = forms.IntegerField( required=False, @@ -225,15 +239,26 @@ class CircuitTerminationBulkEditForm(NetBoxModelBulkEditForm): fieldsets = ( FieldSet( 'description', - TabbedGroups( - FieldSet('site', name=_('Site')), - FieldSet('provider_network', name=_('Provider Network')), - ), + 'termination_type', 'termination', 'mark_connected', name=_('Circuit Termination') ), FieldSet('port_speed', 'upstream_speed', name=_('Termination Details')), ) - nullable_fields = ('description') + nullable_fields = ('description', 'termination') + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + if termination_type_id := get_field_value(self, 'termination_type'): + try: + termination_type = ContentType.objects.get(pk=termination_type_id) + model = termination_type.model_class() + self.fields['termination'].queryset = model.objects.all() + self.fields['termination'].widget.attrs['selector'] = model._meta.label_lower + self.fields['termination'].disabled = False + self.fields['termination'].label = _(bettertitle(model._meta.verbose_name)) + except ObjectDoesNotExist: + pass class CircuitGroupBulkEditForm(NetBoxModelBulkEditForm): @@ -255,7 +280,7 @@ class CircuitGroupBulkEditForm(NetBoxModelBulkEditForm): class CircuitGroupAssignmentBulkEditForm(NetBoxModelBulkEditForm): - circuit = DynamicModelChoiceField( + member = DynamicModelChoiceField( label=_('Circuit'), queryset=Circuit.objects.all(), required=False @@ -268,6 +293,88 @@ class CircuitGroupAssignmentBulkEditForm(NetBoxModelBulkEditForm): model = CircuitGroupAssignment fieldsets = ( - FieldSet('circuit', 'priority'), + FieldSet('member', 'priority'), ) nullable_fields = ('priority',) + + +class VirtualCircuitTypeBulkEditForm(NetBoxModelBulkEditForm): + color = ColorField( + label=_('Color'), + required=False + ) + description = forms.CharField( + label=_('Description'), + max_length=200, + required=False + ) + + model = VirtualCircuitType + fieldsets = ( + FieldSet('color', 'description'), + ) + nullable_fields = ('color', 'description') + + +class VirtualCircuitBulkEditForm(NetBoxModelBulkEditForm): + provider_network = DynamicModelChoiceField( + label=_('Provider network'), + queryset=ProviderNetwork.objects.all(), + required=False + ) + provider_account = DynamicModelChoiceField( + label=_('Provider account'), + queryset=ProviderAccount.objects.all(), + required=False + ) + type = DynamicModelChoiceField( + label=_('Type'), + queryset=VirtualCircuitType.objects.all(), + required=False + ) + status = forms.ChoiceField( + label=_('Status'), + choices=add_blank_choice(CircuitStatusChoices), + required=False, + initial='' + ) + tenant = DynamicModelChoiceField( + label=_('Tenant'), + queryset=Tenant.objects.all(), + required=False + ) + description = forms.CharField( + label=_('Description'), + max_length=100, + required=False + ) + comments = CommentField() + + model = VirtualCircuit + fieldsets = ( + FieldSet('provider_network', 'provider_account', 'status', 'description', name=_('Virtual circuit')), + FieldSet('tenant', name=_('Tenancy')), + ) + nullable_fields = ( + 'provider_account', 'tenant', 'description', 'comments', + ) + + +class VirtualCircuitTerminationBulkEditForm(NetBoxModelBulkEditForm): + role = forms.ChoiceField( + label=_('Role'), + choices=add_blank_choice(VirtualCircuitTerminationRoleChoices), + required=False, + initial='' + ) + description = forms.CharField( + label=_('Description'), + max_length=200, + required=False + ) + + model = VirtualCircuitTermination + fieldsets = ( + FieldSet('role', 'description'), + ) + nullable_fields = ('description',) diff --git a/netbox/circuits/forms/bulk_import.py b/netbox/circuits/forms/bulk_import.py index d5cdc00a7..43700d16b 100644 --- a/netbox/circuits/forms/bulk_import.py +++ b/netbox/circuits/forms/bulk_import.py @@ -1,13 +1,15 @@ from django import forms +from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext_lazy as _ from circuits.choices import * +from circuits.constants import * from circuits.models import * -from dcim.models import Site +from dcim.models import Interface from netbox.choices import DistanceUnitChoices from netbox.forms import NetBoxModelImportForm from tenancy.models import Tenant -from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField, SlugField +from utilities.forms.fields import CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, SlugField __all__ = ( 'CircuitImportForm', @@ -19,6 +21,10 @@ __all__ = ( 'ProviderImportForm', 'ProviderAccountImportForm', 'ProviderNetworkImportForm', + 'VirtualCircuitImportForm', + 'VirtualCircuitTerminationImportForm', + 'VirtualCircuitTerminationImportRelatedForm', + 'VirtualCircuitTypeImportForm', ) @@ -127,17 +133,10 @@ class BaseCircuitTerminationImportForm(forms.ModelForm): label=_('Termination'), choices=CircuitTerminationSideChoices, ) - site = CSVModelChoiceField( - label=_('Site'), - queryset=Site.objects.all(), - to_field_name='name', - required=False - ) - provider_network = CSVModelChoiceField( - label=_('Provider network'), - queryset=ProviderNetwork.objects.all(), - to_field_name='name', - required=False + termination_type = CSVContentTypeField( + queryset=ContentType.objects.filter(model__in=CIRCUIT_TERMINATION_TERMINATION_TYPES), + required=False, + label=_('Termination type (app & model)') ) @@ -145,9 +144,12 @@ class CircuitTerminationImportRelatedForm(BaseCircuitTerminationImportForm): class Meta: model = CircuitTermination fields = [ - 'circuit', 'term_side', 'site', 'provider_network', 'port_speed', 'upstream_speed', 'xconnect_id', + 'circuit', 'term_side', 'termination_type', 'termination_id', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description' ] + labels = { + 'termination_id': _('Termination ID'), + } class CircuitTerminationImportForm(NetBoxModelImportForm, BaseCircuitTerminationImportForm): @@ -155,9 +157,12 @@ class CircuitTerminationImportForm(NetBoxModelImportForm, BaseCircuitTermination class Meta: model = CircuitTermination fields = [ - 'circuit', 'term_side', 'site', 'provider_network', 'port_speed', 'upstream_speed', 'xconnect_id', + 'circuit', 'term_side', 'termination_type', 'termination_id', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description', 'tags' ] + labels = { + 'termination_id': _('Termination ID'), + } class CircuitGroupImportForm(NetBoxModelImportForm): @@ -175,7 +180,101 @@ class CircuitGroupImportForm(NetBoxModelImportForm): class CircuitGroupAssignmentImportForm(NetBoxModelImportForm): + member_type = CSVContentTypeField( + queryset=ContentType.objects.filter(CIRCUIT_GROUP_ASSIGNMENT_MEMBER_MODELS), + label=_('Circuit type (app & model)') + ) + priority = CSVChoiceField( + label=_('Priority'), + choices=CircuitPriorityChoices, + required=False + ) class Meta: model = CircuitGroupAssignment - fields = ('circuit', 'group', 'priority') + fields = ('member_type', 'member_id', 'group', 'priority') + + +class VirtualCircuitTypeImportForm(NetBoxModelImportForm): + slug = SlugField() + + class Meta: + model = VirtualCircuitType + fields = ('name', 'slug', 'color', 'description', 'tags') + + +class VirtualCircuitImportForm(NetBoxModelImportForm): + provider_network = CSVModelChoiceField( + label=_('Provider network'), + queryset=ProviderNetwork.objects.all(), + to_field_name='name', + help_text=_('The network to which this virtual circuit belongs') + ) + provider_account = CSVModelChoiceField( + label=_('Provider account'), + queryset=ProviderAccount.objects.all(), + to_field_name='account', + help_text=_('Assigned provider account (if any)'), + required=False + ) + type = CSVModelChoiceField( + label=_('Type'), + queryset=VirtualCircuitType.objects.all(), + to_field_name='name', + help_text=_('Type of virtual circuit') + ) + status = CSVChoiceField( + label=_('Status'), + choices=CircuitStatusChoices, + help_text=_('Operational status') + ) + tenant = CSVModelChoiceField( + label=_('Tenant'), + queryset=Tenant.objects.all(), + required=False, + to_field_name='name', + help_text=_('Assigned tenant') + ) + + class Meta: + model = VirtualCircuit + fields = [ + 'cid', 'provider_network', 'provider_account', 'type', 'status', 'tenant', 'description', 'comments', + 'tags', + ] + + +class BaseVirtualCircuitTerminationImportForm(forms.ModelForm): + virtual_circuit = CSVModelChoiceField( + label=_('Virtual circuit'), + queryset=VirtualCircuit.objects.all(), + to_field_name='cid', + ) + role = CSVChoiceField( + label=_('Role'), + choices=VirtualCircuitTerminationRoleChoices, + help_text=_('Operational role') + ) + interface = CSVModelChoiceField( + label=_('Interface'), + queryset=Interface.objects.all(), + to_field_name='pk', + ) + + +class VirtualCircuitTerminationImportRelatedForm(BaseVirtualCircuitTerminationImportForm): + + class Meta: + model = VirtualCircuitTermination + fields = [ + 'virtual_circuit', 'role', 'interface', 'description', + ] + + +class VirtualCircuitTerminationImportForm(NetBoxModelImportForm, BaseVirtualCircuitTerminationImportForm): + + class Meta: + model = VirtualCircuitTermination + fields = [ + 'virtual_circuit', 'role', 'interface', 'description', 'tags', + ] diff --git a/netbox/circuits/forms/filtersets.py b/netbox/circuits/forms/filtersets.py index 2e9b358e8..aefc62655 100644 --- a/netbox/circuits/forms/filtersets.py +++ b/netbox/circuits/forms/filtersets.py @@ -1,9 +1,12 @@ from django import forms from django.utils.translation import gettext as _ -from circuits.choices import CircuitCommitRateChoices, CircuitPriorityChoices, CircuitStatusChoices, CircuitTerminationSideChoices +from circuits.choices import ( + CircuitCommitRateChoices, CircuitPriorityChoices, CircuitStatusChoices, CircuitTerminationSideChoices, + VirtualCircuitTerminationRoleChoices, +) from circuits.models import * -from dcim.models import Region, Site, SiteGroup +from dcim.models import Location, Region, Site, SiteGroup from ipam.models import ASN from netbox.choices import DistanceUnitChoices from netbox.forms import NetBoxModelFilterSetForm @@ -22,6 +25,9 @@ __all__ = ( 'ProviderFilterForm', 'ProviderAccountFilterForm', 'ProviderNetworkFilterForm', + 'VirtualCircuitFilterForm', + 'VirtualCircuitTerminationFilterForm', + 'VirtualCircuitTypeFilterForm', ) @@ -116,7 +122,10 @@ class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFi fieldsets = ( FieldSet('q', 'filter_id', 'tag'), FieldSet('provider_id', 'provider_account_id', 'provider_network_id', name=_('Provider')), - FieldSet('type_id', 'status', 'install_date', 'termination_date', 'commit_rate', 'distance', 'distance_unit', name=_('Attributes')), + FieldSet( + 'type_id', 'status', 'install_date', 'termination_date', 'commit_rate', 'distance', 'distance_unit', + name=_('Attributes') + ), FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')), @@ -207,18 +216,29 @@ class CircuitTerminationFilterForm(NetBoxModelFilterSetForm): fieldsets = ( FieldSet('q', 'filter_id', 'tag'), FieldSet('circuit_id', 'term_side', name=_('Circuit')), - FieldSet('provider_id', 'provider_network_id', name=_('Provider')), - FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), + FieldSet('provider_id', name=_('Provider')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Termination')), + ) + region_id = DynamicModelMultipleChoiceField( + queryset=Region.objects.all(), + required=False, + label=_('Region') + ) + site_group_id = DynamicModelMultipleChoiceField( + queryset=SiteGroup.objects.all(), + required=False, + label=_('Site group') ) site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - query_params={ - 'region_id': '$region_id', - 'site_group_id': '$site_group_id', - }, label=_('Site') ) + location_id = DynamicModelMultipleChoiceField( + queryset=Location.objects.all(), + required=False, + label=_('Location') + ) circuit_id = DynamicModelMultipleChoiceField( queryset=Circuit.objects.all(), required=False, @@ -258,14 +278,14 @@ class CircuitGroupAssignmentFilterForm(NetBoxModelFilterSetForm): model = CircuitGroupAssignment fieldsets = ( FieldSet('q', 'filter_id', 'tag'), - FieldSet('provider_id', 'circuit_id', 'group_id', 'priority', name=_('Assignment')), + FieldSet('provider_id', 'member_id', 'group_id', 'priority', name=_('Assignment')), ) provider_id = DynamicModelMultipleChoiceField( queryset=Provider.objects.all(), required=False, label=_('Provider') ) - circuit_id = DynamicModelMultipleChoiceField( + member_id = DynamicModelMultipleChoiceField( queryset=Circuit.objects.all(), required=False, label=_('Circuit') @@ -281,3 +301,93 @@ class CircuitGroupAssignmentFilterForm(NetBoxModelFilterSetForm): required=False ) tag = TagFilterField(model) + + +class VirtualCircuitTypeFilterForm(NetBoxModelFilterSetForm): + model = VirtualCircuitType + fieldsets = ( + FieldSet('q', 'filter_id', 'tag'), + FieldSet('color', name=_('Attributes')), + ) + tag = TagFilterField(model) + + color = ColorField( + label=_('Color'), + required=False + ) + + +class VirtualCircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm): + model = VirtualCircuit + fieldsets = ( + FieldSet('q', 'filter_id', 'tag'), + FieldSet('provider_id', 'provider_account_id', 'provider_network_id', name=_('Provider')), + FieldSet('type', 'status', name=_('Attributes')), + FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), + ) + selector_fields = ('filter_id', 'q', 'provider_id', 'provider_network_id') + provider_id = DynamicModelMultipleChoiceField( + queryset=Provider.objects.all(), + required=False, + label=_('Provider') + ) + provider_account_id = DynamicModelMultipleChoiceField( + queryset=ProviderAccount.objects.all(), + required=False, + query_params={ + 'provider_id': '$provider_id' + }, + label=_('Provider account') + ) + provider_network_id = DynamicModelMultipleChoiceField( + queryset=ProviderNetwork.objects.all(), + required=False, + query_params={ + 'provider_id': '$provider_id' + }, + label=_('Provider network') + ) + type_id = DynamicModelMultipleChoiceField( + queryset=VirtualCircuitType.objects.all(), + required=False, + label=_('Type') + ) + status = forms.MultipleChoiceField( + label=_('Status'), + choices=CircuitStatusChoices, + required=False + ) + tag = TagFilterField(model) + + +class VirtualCircuitTerminationFilterForm(NetBoxModelFilterSetForm): + model = VirtualCircuitTermination + fieldsets = ( + FieldSet('q', 'filter_id', 'tag'), + FieldSet('virtual_circuit_id', 'role', name=_('Virtual circuit')), + FieldSet('provider_id', 'provider_account_id', 'provider_network_id', name=_('Provider')), + ) + virtual_circuit_id = DynamicModelMultipleChoiceField( + queryset=VirtualCircuit.objects.all(), + required=False, + label=_('Virtual circuit') + ) + role = forms.MultipleChoiceField( + label=_('Role'), + choices=VirtualCircuitTerminationRoleChoices, + required=False + ) + provider_network_id = DynamicModelMultipleChoiceField( + queryset=ProviderNetwork.objects.all(), + required=False, + query_params={ + 'provider_id': '$provider_id' + }, + label=_('Provider network') + ) + provider_id = DynamicModelMultipleChoiceField( + queryset=Provider.objects.all(), + required=False, + label=_('Provider') + ) + tag = TagFilterField(model) diff --git a/netbox/circuits/forms/model_forms.py b/netbox/circuits/forms/model_forms.py index e00034a10..6f8ab783d 100644 --- a/netbox/circuits/forms/model_forms.py +++ b/netbox/circuits/forms/model_forms.py @@ -1,14 +1,24 @@ +from django import forms +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ObjectDoesNotExist from django.utils.translation import gettext_lazy as _ -from circuits.choices import CircuitCommitRateChoices, CircuitTerminationPortSpeedChoices +from circuits.choices import ( + CircuitCommitRateChoices, CircuitTerminationPortSpeedChoices, VirtualCircuitTerminationRoleChoices, +) +from circuits.constants import * from circuits.models import * -from dcim.models import Site +from dcim.models import Interface, Site from ipam.models import ASN from netbox.forms import NetBoxModelForm from tenancy.forms import TenancyForm -from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField -from utilities.forms.rendering import FieldSet, InlineFields, TabbedGroups -from utilities.forms.widgets import DatePicker, NumberWithOptions +from utilities.forms import get_field_value +from utilities.forms.fields import ( + CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField, +) +from utilities.forms.rendering import FieldSet, InlineFields +from utilities.forms.widgets import DatePicker, HTMXSelect, NumberWithOptions +from utilities.templatetags.builtins.filters import bettertitle __all__ = ( 'CircuitForm', @@ -19,6 +29,9 @@ __all__ = ( 'ProviderForm', 'ProviderAccountForm', 'ProviderNetworkForm', + 'VirtualCircuitForm', + 'VirtualCircuitTerminationForm', + 'VirtualCircuitTypeForm', ) @@ -45,7 +58,9 @@ class ProviderForm(NetBoxModelForm): class ProviderAccountForm(NetBoxModelForm): provider = DynamicModelChoiceField( label=_('Provider'), - queryset=Provider.objects.all() + queryset=Provider.objects.all(), + selector=True, + quick_add=True ) comments = CommentField() @@ -59,7 +74,9 @@ class ProviderAccountForm(NetBoxModelForm): class ProviderNetworkForm(NetBoxModelForm): provider = DynamicModelChoiceField( label=_('Provider'), - queryset=Provider.objects.all() + queryset=Provider.objects.all(), + selector=True, + quick_add=True ) comments = CommentField() @@ -92,7 +109,8 @@ class CircuitForm(TenancyForm, NetBoxModelForm): provider = DynamicModelChoiceField( label=_('Provider'), queryset=Provider.objects.all(), - selector=True + selector=True, + quick_add=True ) provider_account = DynamicModelChoiceField( label=_('Provider account'), @@ -103,7 +121,8 @@ class CircuitForm(TenancyForm, NetBoxModelForm): } ) type = DynamicModelChoiceField( - queryset=CircuitType.objects.all() + queryset=CircuitType.objects.all(), + quick_add=True ) comments = CommentField() @@ -144,26 +163,24 @@ class CircuitTerminationForm(NetBoxModelForm): queryset=Circuit.objects.all(), selector=True ) - site = DynamicModelChoiceField( - label=_('Site'), - queryset=Site.objects.all(), + termination_type = ContentTypeChoiceField( + queryset=ContentType.objects.filter(model__in=CIRCUIT_TERMINATION_TERMINATION_TYPES), + widget=HTMXSelect(), required=False, - selector=True + label=_('Termination type') ) - provider_network = DynamicModelChoiceField( - label=_('Provider network'), - queryset=ProviderNetwork.objects.all(), + termination = DynamicModelChoiceField( + label=_('Termination'), + queryset=Site.objects.none(), # Initial queryset required=False, + disabled=True, selector=True ) fieldsets = ( FieldSet( 'circuit', 'term_side', 'description', 'tags', - TabbedGroups( - FieldSet('site', name=_('Site')), - FieldSet('provider_network', name=_('Provider Network')), - ), + 'termination_type', 'termination', 'mark_connected', name=_('Circuit Termination') ), FieldSet('port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', name=_('Termination Details')), @@ -172,7 +189,7 @@ class CircuitTerminationForm(NetBoxModelForm): class Meta: model = CircuitTermination fields = [ - 'circuit', 'term_side', 'site', 'provider_network', 'mark_connected', 'port_speed', 'upstream_speed', + 'circuit', 'term_side', 'termination_type', 'mark_connected', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description', 'tags', ] widgets = { @@ -184,6 +201,36 @@ class CircuitTerminationForm(NetBoxModelForm): ), } + def __init__(self, *args, **kwargs): + instance = kwargs.get('instance') + initial = kwargs.get('initial', {}) + + if instance is not None and instance.termination: + initial['termination'] = instance.termination + kwargs['initial'] = initial + + super().__init__(*args, **kwargs) + + if termination_type_id := get_field_value(self, 'termination_type'): + try: + termination_type = ContentType.objects.get(pk=termination_type_id) + model = termination_type.model_class() + self.fields['termination'].queryset = model.objects.all() + self.fields['termination'].widget.attrs['selector'] = model._meta.label_lower + self.fields['termination'].disabled = False + self.fields['termination'].label = _(bettertitle(model._meta.verbose_name)) + except ObjectDoesNotExist: + pass + + if self.instance and termination_type_id != self.instance.termination_type_id: + self.initial['termination'] = None + + def clean(self): + super().clean() + + # Assign the selected termination (if any) + self.instance.termination = self.cleaned_data.get('termination') + class CircuitGroupForm(TenancyForm, NetBoxModelForm): slug = SlugField() @@ -205,14 +252,137 @@ class CircuitGroupAssignmentForm(NetBoxModelForm): label=_('Group'), queryset=CircuitGroup.objects.all(), ) - circuit = DynamicModelChoiceField( + member_type = ContentTypeChoiceField( + queryset=ContentType.objects.filter(CIRCUIT_GROUP_ASSIGNMENT_MEMBER_MODELS), + widget=HTMXSelect(), + required=False, + label=_('Circuit type') + ) + member = DynamicModelChoiceField( label=_('Circuit'), - queryset=Circuit.objects.all(), + queryset=Circuit.objects.none(), # Initial queryset + required=False, + disabled=True, selector=True ) + fieldsets = ( + FieldSet('group', 'member_type', 'member', 'priority', 'tags', name=_('Group Assignment')), + ) + class Meta: model = CircuitGroupAssignment fields = [ - 'group', 'circuit', 'priority', 'tags', + 'group', 'member_type', 'priority', 'tags', + ] + + def __init__(self, *args, **kwargs): + instance = kwargs.get('instance') + initial = kwargs.get('initial', {}) + + if instance is not None and instance.member: + initial['member'] = instance.member + kwargs['initial'] = initial + + super().__init__(*args, **kwargs) + + if member_type_id := get_field_value(self, 'member_type'): + try: + model = ContentType.objects.get(pk=member_type_id).model_class() + self.fields['member'].queryset = model.objects.all() + self.fields['member'].widget.attrs['selector'] = model._meta.label_lower + self.fields['member'].disabled = False + self.fields['member'].label = _(bettertitle(model._meta.verbose_name)) + except ObjectDoesNotExist: + pass + + if self.instance.pk and member_type_id != self.instance.member_type_id: + self.initial['member'] = None + + def clean(self): + super().clean() + + # Assign the selected circuit (if any) + self.instance.member = self.cleaned_data.get('member') + + +class VirtualCircuitTypeForm(NetBoxModelForm): + slug = SlugField() + + fieldsets = ( + FieldSet('name', 'slug', 'color', 'description', 'tags'), + ) + + class Meta: + model = VirtualCircuitType + fields = [ + 'name', 'slug', 'color', 'description', 'tags', + ] + + +class VirtualCircuitForm(TenancyForm, NetBoxModelForm): + provider_network = DynamicModelChoiceField( + label=_('Provider network'), + queryset=ProviderNetwork.objects.all(), + selector=True + ) + provider_account = DynamicModelChoiceField( + label=_('Provider account'), + queryset=ProviderAccount.objects.all(), + required=False + ) + type = DynamicModelChoiceField( + queryset=VirtualCircuitType.objects.all(), + quick_add=True + ) + comments = CommentField() + + fieldsets = ( + FieldSet( + 'provider_network', 'provider_account', 'cid', 'type', 'status', 'description', 'tags', + name=_('Virtual circuit'), + ), + FieldSet('tenant_group', 'tenant', name=_('Tenancy')), + ) + + class Meta: + model = VirtualCircuit + fields = [ + 'cid', 'provider_network', 'provider_account', 'type', 'status', 'description', 'tenant_group', 'tenant', + 'comments', 'tags', + ] + + +class VirtualCircuitTerminationForm(NetBoxModelForm): + virtual_circuit = DynamicModelChoiceField( + label=_('Virtual circuit'), + queryset=VirtualCircuit.objects.all(), + selector=True + ) + role = forms.ChoiceField( + choices=VirtualCircuitTerminationRoleChoices, + widget=HTMXSelect(), + label=_('Role') + ) + interface = DynamicModelChoiceField( + label=_('Interface'), + queryset=Interface.objects.all(), + selector=True, + query_params={ + 'kind': 'virtual', + 'virtual_circuit_termination_id': 'null', + }, + context={ + 'parent': 'device', + } + ) + + fieldsets = ( + FieldSet('virtual_circuit', 'role', 'interface', 'description', 'tags'), + ) + + class Meta: + model = VirtualCircuitTermination + fields = [ + 'virtual_circuit', 'role', 'interface', 'description', 'tags', ] diff --git a/netbox/circuits/graphql/filters.py b/netbox/circuits/graphql/filters.py index b8398b2b9..7d066f428 100644 --- a/netbox/circuits/graphql/filters.py +++ b/netbox/circuits/graphql/filters.py @@ -4,14 +4,17 @@ from circuits import filtersets, models from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin __all__ = ( - 'CircuitTerminationFilter', 'CircuitFilter', 'CircuitGroupAssignmentFilter', 'CircuitGroupFilter', + 'CircuitTerminationFilter', 'CircuitTypeFilter', 'ProviderFilter', 'ProviderAccountFilter', 'ProviderNetworkFilter', + 'VirtualCircuitFilter', + 'VirtualCircuitTerminationFilter', + 'VirtualCircuitTypeFilter', ) @@ -61,3 +64,21 @@ class ProviderAccountFilter(BaseFilterMixin): @autotype_decorator(filtersets.ProviderNetworkFilterSet) class ProviderNetworkFilter(BaseFilterMixin): pass + + +@strawberry_django.filter(models.VirtualCircuitType, lookups=True) +@autotype_decorator(filtersets.VirtualCircuitTypeFilterSet) +class VirtualCircuitTypeFilter(BaseFilterMixin): + pass + + +@strawberry_django.filter(models.VirtualCircuit, lookups=True) +@autotype_decorator(filtersets.VirtualCircuitFilterSet) +class VirtualCircuitFilter(BaseFilterMixin): + pass + + +@strawberry_django.filter(models.VirtualCircuitTermination, lookups=True) +@autotype_decorator(filtersets.VirtualCircuitTerminationFilterSet) +class VirtualCircuitTerminationFilter(BaseFilterMixin): + pass diff --git a/netbox/circuits/graphql/schema.py b/netbox/circuits/graphql/schema.py index ac23421ce..63bd7bba6 100644 --- a/netbox/circuits/graphql/schema.py +++ b/netbox/circuits/graphql/schema.py @@ -31,3 +31,12 @@ class CircuitsQuery: provider_network: ProviderNetworkType = strawberry_django.field() provider_network_list: List[ProviderNetworkType] = strawberry_django.field() + + virtual_circuit: VirtualCircuitType = strawberry_django.field() + virtual_circuit_list: List[VirtualCircuitType] = strawberry_django.field() + + virtual_circuit_termination: VirtualCircuitTerminationType = strawberry_django.field() + virtual_circuit_termination_list: List[VirtualCircuitTerminationType] = strawberry_django.field() + + virtual_circuit_type: VirtualCircuitTypeType = strawberry_django.field() + virtual_circuit_type_list: List[VirtualCircuitTypeType] = strawberry_django.field() diff --git a/netbox/circuits/graphql/types.py b/netbox/circuits/graphql/types.py index 45f0d065d..564b5ed6f 100644 --- a/netbox/circuits/graphql/types.py +++ b/netbox/circuits/graphql/types.py @@ -1,4 +1,4 @@ -from typing import Annotated, List +from typing import Annotated, List, Union import strawberry import strawberry_django @@ -19,6 +19,9 @@ __all__ = ( 'ProviderType', 'ProviderAccountType', 'ProviderNetworkType', + 'VirtualCircuitTerminationType', + 'VirtualCircuitType', + 'VirtualCircuitTypeType', ) @@ -59,13 +62,21 @@ class ProviderNetworkType(NetBoxObjectType): @strawberry_django.type( models.CircuitTermination, - fields='__all__', + exclude=('termination_type', 'termination_id', '_location', '_region', '_site', '_site_group', '_provider_network'), filters=CircuitTerminationFilter ) class CircuitTerminationType(CustomFieldsMixin, TagsMixin, CabledObjectMixin, ObjectType): circuit: Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')] - provider_network: Annotated["ProviderNetworkType", strawberry.lazy('circuits.graphql.types')] | None - site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] | None + + @strawberry_django.field + def termination(self) -> Annotated[Union[ + Annotated["LocationType", strawberry.lazy('dcim.graphql.types')], + Annotated["RegionType", strawberry.lazy('dcim.graphql.types')], + Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')], + Annotated["SiteType", strawberry.lazy('dcim.graphql.types')], + Annotated["ProviderNetworkType", strawberry.lazy('circuits.graphql.types')], + ], strawberry.union("CircuitTerminationTerminationType")] | None: + return self.termination @strawberry_django.type( @@ -106,9 +117,58 @@ class CircuitGroupType(OrganizationalObjectType): @strawberry_django.type( models.CircuitGroupAssignment, - fields='__all__', + exclude=('member_type', 'member_id'), filters=CircuitGroupAssignmentFilter ) class CircuitGroupAssignmentType(TagsMixin, BaseObjectType): group: Annotated["CircuitGroupType", strawberry.lazy('circuits.graphql.types')] - circuit: Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')] + + @strawberry_django.field + def member(self) -> Annotated[Union[ + Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')], + Annotated["VirtualCircuitType", strawberry.lazy('circuits.graphql.types')], + ], strawberry.union("CircuitGroupAssignmentMemberType")] | None: + return self.member + + +@strawberry_django.type( + models.VirtualCircuitType, + fields='__all__', + filters=VirtualCircuitTypeFilter +) +class VirtualCircuitTypeType(OrganizationalObjectType): + color: str + + virtual_circuits: List[Annotated["VirtualCircuitType", strawberry.lazy('circuits.graphql.types')]] + + +@strawberry_django.type( + models.VirtualCircuitTermination, + fields='__all__', + filters=VirtualCircuitTerminationFilter +) +class VirtualCircuitTerminationType(CustomFieldsMixin, TagsMixin, ObjectType): + virtual_circuit: Annotated[ + "VirtualCircuitType", + strawberry.lazy('circuits.graphql.types') + ] = strawberry_django.field(select_related=["virtual_circuit"]) + interface: Annotated[ + "InterfaceType", + strawberry.lazy('dcim.graphql.types') + ] = strawberry_django.field(select_related=["interface"]) + + +@strawberry_django.type( + models.VirtualCircuit, + fields='__all__', + filters=VirtualCircuitFilter +) +class VirtualCircuitType(NetBoxObjectType): + provider_network: ProviderNetworkType = strawberry_django.field(select_related=["provider_network"]) + provider_account: ProviderAccountType | None + type: Annotated["VirtualCircuitTypeType", strawberry.lazy('circuits.graphql.types')] = strawberry_django.field( + select_related=["type"] + ) + tenant: TenantType | None + + terminations: List[VirtualCircuitTerminationType] diff --git a/netbox/circuits/migrations/0001_squashed.py b/netbox/circuits/migrations/0001_squashed.py index 96fa3c086..0b3d729e6 100644 --- a/netbox/circuits/migrations/0001_squashed.py +++ b/netbox/circuits/migrations/0001_squashed.py @@ -5,11 +5,9 @@ import django.db.models.deletion class Migration(migrations.Migration): - initial = True - dependencies = [ - ] + dependencies = [] replaces = [ ('circuits', '0001_initial'), @@ -98,7 +96,12 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=100)), ('description', models.CharField(blank=True, max_length=200)), ('comments', models.TextField(blank=True)), - ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='networks', to='circuits.provider')), + ( + 'provider', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='networks', to='circuits.provider' + ), + ), ], options={ 'ordering': ('provider', 'name'), diff --git a/netbox/circuits/migrations/0002_squashed_0029.py b/netbox/circuits/migrations/0002_squashed_0029.py index 11fcbd6e6..cb61d8feb 100644 --- a/netbox/circuits/migrations/0002_squashed_0029.py +++ b/netbox/circuits/migrations/0002_squashed_0029.py @@ -4,7 +4,6 @@ import taggit.managers class Migration(migrations.Migration): - dependencies = [ ('dcim', '0001_initial'), ('contenttypes', '0002_remove_content_type_name'), @@ -58,32 +57,56 @@ class Migration(migrations.Migration): migrations.AddField( model_name='circuittermination', name='_cable_peer_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='circuittermination', name='cable', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable' + ), ), migrations.AddField( model_name='circuittermination', name='circuit', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='terminations', to='circuits.circuit'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='terminations', to='circuits.circuit' + ), ), migrations.AddField( model_name='circuittermination', name='provider_network', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='circuit_terminations', to='circuits.providernetwork'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='circuit_terminations', + to='circuits.providernetwork', + ), ), migrations.AddField( model_name='circuittermination', name='site', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='circuit_terminations', to='dcim.site'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='circuit_terminations', + to='dcim.site', + ), ), migrations.AddField( model_name='circuit', name='provider', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='circuits.provider'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='circuits.provider' + ), ), migrations.AddField( model_name='circuit', @@ -93,26 +116,50 @@ class Migration(migrations.Migration): migrations.AddField( model_name='circuit', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='circuits', + to='tenancy.tenant', + ), ), migrations.AddField( model_name='circuit', name='termination_a', - field=models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='circuits.circuittermination'), + field=models.ForeignKey( + blank=True, + editable=False, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='circuits.circuittermination', + ), ), migrations.AddField( model_name='circuit', name='termination_z', - field=models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='circuits.circuittermination'), + field=models.ForeignKey( + blank=True, + editable=False, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='circuits.circuittermination', + ), ), migrations.AddField( model_name='circuit', name='type', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='circuits.circuittype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='circuits.circuittype' + ), ), migrations.AddConstraint( model_name='providernetwork', - constraint=models.UniqueConstraint(fields=('provider', 'name'), name='circuits_providernetwork_provider_name'), + constraint=models.UniqueConstraint( + fields=('provider', 'name'), name='circuits_providernetwork_provider_name' + ), ), migrations.AlterUniqueTogether( name='providernetwork', diff --git a/netbox/circuits/migrations/0003_squashed_0037.py b/netbox/circuits/migrations/0003_squashed_0037.py index 69c3e1c68..c536e422f 100644 --- a/netbox/circuits/migrations/0003_squashed_0037.py +++ b/netbox/circuits/migrations/0003_squashed_0037.py @@ -5,7 +5,6 @@ import utilities.json class Migration(migrations.Migration): - replaces = [ ('circuits', '0003_extend_tag_support'), ('circuits', '0004_rename_cable_peer'), @@ -14,7 +13,7 @@ class Migration(migrations.Migration): ('circuits', '0034_created_datetimefield'), ('circuits', '0035_provider_asns'), ('circuits', '0036_circuit_termination_date_tags_custom_fields'), - ('circuits', '0037_new_cabling_models') + ('circuits', '0037_new_cabling_models'), ] dependencies = [ diff --git a/netbox/circuits/migrations/0038_squashed_0042.py b/netbox/circuits/migrations/0038_squashed_0042.py index f57fde3db..fa944b763 100644 --- a/netbox/circuits/migrations/0038_squashed_0042.py +++ b/netbox/circuits/migrations/0038_squashed_0042.py @@ -6,13 +6,12 @@ import utilities.json class Migration(migrations.Migration): - replaces = [ ('circuits', '0038_cabling_cleanup'), ('circuits', '0039_unique_constraints'), ('circuits', '0040_provider_remove_deprecated_fields'), ('circuits', '0041_standardize_description_comments'), - ('circuits', '0042_provideraccount') + ('circuits', '0042_provideraccount'), ] dependencies = [ @@ -51,11 +50,15 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='circuittermination', - constraint=models.UniqueConstraint(fields=('circuit', 'term_side'), name='circuits_circuittermination_unique_circuit_term_side'), + constraint=models.UniqueConstraint( + fields=('circuit', 'term_side'), name='circuits_circuittermination_unique_circuit_term_side' + ), ), migrations.AddConstraint( model_name='providernetwork', - constraint=models.UniqueConstraint(fields=('provider', 'name'), name='circuits_providernetwork_unique_provider_name'), + constraint=models.UniqueConstraint( + fields=('provider', 'name'), name='circuits_providernetwork_unique_provider_name' + ), ), migrations.RemoveField( model_name='provider', @@ -84,12 +87,20 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('description', models.CharField(blank=True, max_length=200)), ('comments', models.TextField(blank=True)), ('account', models.CharField(max_length=100)), ('name', models.CharField(blank=True, max_length=100)), - ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='accounts', to='circuits.provider')), + ( + 'provider', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='accounts', to='circuits.provider' + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], options={ @@ -98,11 +109,17 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='provideraccount', - constraint=models.UniqueConstraint(condition=models.Q(('name', ''), _negated=True), fields=('provider', 'name'), name='circuits_provideraccount_unique_provider_name'), + constraint=models.UniqueConstraint( + condition=models.Q(('name', ''), _negated=True), + fields=('provider', 'name'), + name='circuits_provideraccount_unique_provider_name', + ), ), migrations.AddConstraint( model_name='provideraccount', - constraint=models.UniqueConstraint(fields=('provider', 'account'), name='circuits_provideraccount_unique_provider_account'), + constraint=models.UniqueConstraint( + fields=('provider', 'account'), name='circuits_provideraccount_unique_provider_account' + ), ), migrations.RemoveField( model_name='provider', @@ -111,7 +128,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='circuit', name='provider_account', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='circuits.provideraccount'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='circuits', + to='circuits.provideraccount', + ), preserve_default=False, ), migrations.AlterModelOptions( @@ -120,6 +143,8 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='circuit', - constraint=models.UniqueConstraint(fields=('provider_account', 'cid'), name='circuits_circuit_unique_provideraccount_cid'), + constraint=models.UniqueConstraint( + fields=('provider_account', 'cid'), name='circuits_circuit_unique_provideraccount_cid' + ), ), ] diff --git a/netbox/circuits/migrations/0044_circuit_groups.py b/netbox/circuits/migrations/0044_circuit_groups.py index 98c3b8f3d..08f6bc158 100644 --- a/netbox/circuits/migrations/0044_circuit_groups.py +++ b/netbox/circuits/migrations/0044_circuit_groups.py @@ -5,7 +5,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('circuits', '0043_circuittype_color'), ('extras', '0119_notifications'), diff --git a/netbox/circuits/migrations/0045_circuit_distance.py b/netbox/circuits/migrations/0045_circuit_distance.py index 6c970339d..9e512e7ee 100644 --- a/netbox/circuits/migrations/0045_circuit_distance.py +++ b/netbox/circuits/migrations/0045_circuit_distance.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('circuits', '0044_circuit_groups'), ] diff --git a/netbox/circuits/migrations/0046_charfield_null_choices.py b/netbox/circuits/migrations/0046_charfield_null_choices.py new file mode 100644 index 000000000..2a8bcde90 --- /dev/null +++ b/netbox/circuits/migrations/0046_charfield_null_choices.py @@ -0,0 +1,39 @@ +from django.db import migrations, models + + +def set_null_values(apps, schema_editor): + """ + Replace empty strings with null values. + """ + Circuit = apps.get_model('circuits', 'Circuit') + CircuitGroupAssignment = apps.get_model('circuits', 'CircuitGroupAssignment') + CircuitTermination = apps.get_model('circuits', 'CircuitTermination') + + Circuit.objects.filter(distance_unit='').update(distance_unit=None) + CircuitGroupAssignment.objects.filter(priority='').update(priority=None) + CircuitTermination.objects.filter(cable_end='').update(cable_end=None) + + +class Migration(migrations.Migration): + dependencies = [ + ('circuits', '0045_circuit_distance'), + ] + + operations = [ + migrations.AlterField( + model_name='circuit', + name='distance_unit', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='circuitgroupassignment', + name='priority', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='circuittermination', + name='cable_end', + field=models.CharField(blank=True, max_length=1, null=True), + ), + migrations.RunPython(code=set_null_values, reverse_code=migrations.RunPython.noop), + ] diff --git a/netbox/circuits/migrations/0047_circuittermination__termination.py b/netbox/circuits/migrations/0047_circuittermination__termination.py new file mode 100644 index 000000000..f78e17ec3 --- /dev/null +++ b/netbox/circuits/migrations/0047_circuittermination__termination.py @@ -0,0 +1,53 @@ +import django.db.models.deletion +from django.db import migrations, models + + +def copy_site_assignments(apps, schema_editor): + """ + Copy site ForeignKey values to the Termination GFK. + """ + ContentType = apps.get_model('contenttypes', 'ContentType') + CircuitTermination = apps.get_model('circuits', 'CircuitTermination') + Site = apps.get_model('dcim', 'Site') + + CircuitTermination.objects.filter(site__isnull=False).update( + termination_type=ContentType.objects.get_for_model(Site), termination_id=models.F('site_id') + ) + + ProviderNetwork = apps.get_model('circuits', 'ProviderNetwork') + CircuitTermination.objects.filter(provider_network__isnull=False).update( + termination_type=ContentType.objects.get_for_model(ProviderNetwork), + termination_id=models.F('provider_network_id'), + ) + + +class Migration(migrations.Migration): + dependencies = [ + ('circuits', '0046_charfield_null_choices'), + ('contenttypes', '0002_remove_content_type_name'), + ('dcim', '0193_poweroutlet_color'), + ] + + operations = [ + migrations.AddField( + model_name='circuittermination', + name='termination_id', + field=models.PositiveBigIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='circuittermination', + name='termination_type', + field=models.ForeignKey( + blank=True, + limit_choices_to=models.Q( + ('model__in', ('region', 'sitegroup', 'site', 'location', 'providernetwork')) + ), + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), + ), + # Copy over existing site assignments + migrations.RunPython(code=copy_site_assignments, reverse_code=migrations.RunPython.noop), + ] diff --git a/netbox/circuits/migrations/0048_circuitterminations_cached_relations.py b/netbox/circuits/migrations/0048_circuitterminations_cached_relations.py new file mode 100644 index 000000000..fc1cef0e5 --- /dev/null +++ b/netbox/circuits/migrations/0048_circuitterminations_cached_relations.py @@ -0,0 +1,84 @@ +# Generated by Django 5.0.9 on 2024-10-21 17:34 +import django.db.models.deletion +from django.db import migrations, models + + +def populate_denormalized_fields(apps, schema_editor): + """ + Copy site ForeignKey values to the Termination GFK. + """ + CircuitTermination = apps.get_model('circuits', 'CircuitTermination') + + terminations = CircuitTermination.objects.filter(site__isnull=False).prefetch_related('site') + for termination in terminations: + termination._region_id = termination.site.region_id + termination._site_group_id = termination.site.group_id + termination._site_id = termination.site_id + # Note: Location cannot be set prior to migration + + CircuitTermination.objects.bulk_update(terminations, ['_region', '_site_group', '_site']) + + +class Migration(migrations.Migration): + dependencies = [ + ('circuits', '0047_circuittermination__termination'), + ] + + operations = [ + migrations.AddField( + model_name='circuittermination', + name='_location', + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='circuit_terminations', + to='dcim.location', + ), + ), + migrations.AddField( + model_name='circuittermination', + name='_region', + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='circuit_terminations', + to='dcim.region', + ), + ), + migrations.AddField( + model_name='circuittermination', + name='_site', + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='circuit_terminations', + to='dcim.site', + ), + ), + migrations.AddField( + model_name='circuittermination', + name='_site_group', + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='circuit_terminations', + to='dcim.sitegroup', + ), + ), + # Populate denormalized FK values + migrations.RunPython(code=populate_denormalized_fields, reverse_code=migrations.RunPython.noop), + # Delete the site ForeignKey + migrations.RemoveField( + model_name='circuittermination', + name='site', + ), + migrations.RenameField( + model_name='circuittermination', + old_name='provider_network', + new_name='_provider_network', + ), + ] diff --git a/netbox/circuits/migrations/0049_natural_ordering.py b/netbox/circuits/migrations/0049_natural_ordering.py new file mode 100644 index 000000000..556d6ec7c --- /dev/null +++ b/netbox/circuits/migrations/0049_natural_ordering.py @@ -0,0 +1,21 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('circuits', '0048_circuitterminations_cached_relations'), + ('dcim', '0197_natural_sort_collation'), + ] + + operations = [ + migrations.AlterField( + model_name='provider', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='providernetwork', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + ] diff --git a/netbox/circuits/migrations/0050_virtual_circuits.py b/netbox/circuits/migrations/0050_virtual_circuits.py new file mode 100644 index 000000000..9987b95ac --- /dev/null +++ b/netbox/circuits/migrations/0050_virtual_circuits.py @@ -0,0 +1,147 @@ +import django.db.models.deletion +import taggit.managers +from django.db import migrations, models + +import utilities.fields +import utilities.json + + +class Migration(migrations.Migration): + dependencies = [ + ('circuits', '0049_natural_ordering'), + ('dcim', '0196_qinq_svlan'), + ('extras', '0122_charfield_null_choices'), + ('tenancy', '0016_charfield_null_choices'), + ] + + operations = [ + migrations.CreateModel( + name='VirtualCircuitType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('custom_field_data', models.JSONField( + blank=True, + default=dict, + encoder=utilities.json.CustomFieldJSONEncoder + )), + ('name', models.CharField(max_length=100, unique=True)), + ('slug', models.SlugField(max_length=100, unique=True)), + ('description', models.CharField(blank=True, max_length=200)), + ('color', utilities.fields.ColorField(blank=True, max_length=6)), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ], + options={ + 'verbose_name': 'virtual circuit type', + 'verbose_name_plural': 'virtual circuit types', + 'ordering': ('name',), + }, + ), + migrations.CreateModel( + name='VirtualCircuit', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), + ('description', models.CharField(blank=True, max_length=200)), + ('comments', models.TextField(blank=True)), + ('cid', models.CharField(max_length=100)), + ('status', models.CharField(default='active', max_length=50)), + ( + 'provider_account', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='virtual_circuits', + to='circuits.provideraccount', + ), + ), + ( + 'provider_network', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name='virtual_circuits', + to='circuits.providernetwork', + ), + ), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ( + 'type', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name='virtual_circuits', + to='circuits.virtualcircuittype' + ) + ), + ( + 'tenant', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='virtual_circuits', + to='tenancy.tenant', + ), + ), + ], + options={ + 'verbose_name': 'circuit', + 'verbose_name_plural': 'circuits', + 'ordering': ['provider_network', 'provider_account', 'cid'], + }, + ), + migrations.CreateModel( + name='VirtualCircuitTermination', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), + ('role', models.CharField(default='peer', max_length=50)), + ('description', models.CharField(blank=True, max_length=200)), + ( + 'interface', + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + related_name='virtual_circuit_termination', + to='dcim.interface', + ), + ), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ( + 'virtual_circuit', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name='terminations', + to='circuits.virtualcircuit', + ), + ), + ], + options={ + 'verbose_name': 'virtual circuit termination', + 'verbose_name_plural': 'virtual circuit terminations', + 'ordering': ['virtual_circuit', 'role', 'pk'], + }, + ), + migrations.AddConstraint( + model_name='virtualcircuit', + constraint=models.UniqueConstraint( + fields=('provider_network', 'cid'), name='circuits_virtualcircuit_unique_provider_network_cid' + ), + ), + migrations.AddConstraint( + model_name='virtualcircuit', + constraint=models.UniqueConstraint( + fields=('provider_account', 'cid'), name='circuits_virtualcircuit_unique_provideraccount_cid' + ), + ), + ] diff --git a/netbox/circuits/migrations/0051_virtualcircuit_group_assignment.py b/netbox/circuits/migrations/0051_virtualcircuit_group_assignment.py new file mode 100644 index 000000000..f8c0fd653 --- /dev/null +++ b/netbox/circuits/migrations/0051_virtualcircuit_group_assignment.py @@ -0,0 +1,85 @@ +import django.db.models.deletion +from django.db import migrations, models + + +def set_member_type(apps, schema_editor): + """ + Set member_type on any existing CircuitGroupAssignments to the content type for Circuit. + """ + ContentType = apps.get_model('contenttypes', 'ContentType') + Circuit = apps.get_model('circuits', 'Circuit') + CircuitGroupAssignment = apps.get_model('circuits', 'CircuitGroupAssignment') + + CircuitGroupAssignment.objects.update( + member_type=ContentType.objects.get_for_model(Circuit) + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('circuits', '0050_virtual_circuits'), + ('contenttypes', '0002_remove_content_type_name'), + ('extras', '0122_charfield_null_choices'), + ] + + operations = [ + migrations.RemoveConstraint( + model_name='circuitgroupassignment', + name='circuits_circuitgroupassignment_unique_circuit_group', + ), + migrations.AlterModelOptions( + name='circuitgroupassignment', + options={'ordering': ('group', 'member_type', 'member_id', 'priority', 'pk')}, + ), + + # Change member_id to an integer field for the member GFK + migrations.RenameField( + model_name='circuitgroupassignment', + old_name='circuit', + new_name='member_id', + ), + migrations.AlterField( + model_name='circuitgroupassignment', + name='member_id', + field=models.PositiveBigIntegerField(), + ), + + # Add content type pointer for the member GFK + migrations.AddField( + model_name='circuitgroupassignment', + name='member_type', + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + limit_choices_to=models.Q(('app_label', 'circuits'), ('model__in', ['circuit', 'virtualcircuit'])), + related_name='+', + to='contenttypes.contenttype', + blank=True, + null=True + ), + preserve_default=False, + ), + + # Populate member_type for any existing assignments + migrations.RunPython(code=set_member_type, reverse_code=migrations.RunPython.noop), + + # Disallow null values for member_type + migrations.AlterField( + model_name='circuitgroupassignment', + name='member_type', + field=models.ForeignKey( + limit_choices_to=models.Q(('app_label', 'circuits'), ('model__in', ['circuit', 'virtualcircuit'])), + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype' + ), + ), + + migrations.AddConstraint( + model_name='circuitgroupassignment', + constraint=models.UniqueConstraint( + fields=('member_type', 'member_id', 'group'), + name='circuits_circuitgroupassignment_unique_member_group' + ), + ), + ] diff --git a/netbox/circuits/models/__init__.py b/netbox/circuits/models/__init__.py index 7bbaf75d3..77382358b 100644 --- a/netbox/circuits/models/__init__.py +++ b/netbox/circuits/models/__init__.py @@ -1,2 +1,3 @@ from .circuits import * from .providers import * +from .virtual_circuits import * diff --git a/netbox/circuits/models/base.py b/netbox/circuits/models/base.py new file mode 100644 index 000000000..5b2a3c1b8 --- /dev/null +++ b/netbox/circuits/models/base.py @@ -0,0 +1,23 @@ +from django.utils.translation import gettext_lazy as _ + +from netbox.models import OrganizationalModel +from utilities.fields import ColorField + +__all__ = ( + 'BaseCircuitType', +) + + +class BaseCircuitType(OrganizationalModel): + """ + Abstract base model to represent a type of physical or virtual circuit. + Circuits can be organized by their functional role. For example, a user might wish to define CircuitTypes named + "Long Haul," "Metro," or "Out-of-Band". + """ + color = ColorField( + verbose_name=_('color'), + blank=True + ) + + class Meta: + abstract = True diff --git a/netbox/circuits/models/circuits.py b/netbox/circuits/models/circuits.py index 2df83e97e..9c7714153 100644 --- a/netbox/circuits/models/circuits.py +++ b/netbox/circuits/models/circuits.py @@ -1,14 +1,19 @@ +from django.apps import apps +from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.core.exceptions import ValidationError from django.db import models from django.urls import reverse from django.utils.translation import gettext_lazy as _ from circuits.choices import * +from circuits.constants import * from dcim.models import CabledObjectModel from netbox.models import ChangeLoggedModel, OrganizationalModel, PrimaryModel from netbox.models.mixins import DistanceMixin -from netbox.models.features import ContactsMixin, CustomFieldsMixin, CustomLinksMixin, ExportTemplatesMixin, ImageAttachmentsMixin, TagsMixin -from utilities.fields import ColorField +from netbox.models.features import ( + ContactsMixin, CustomFieldsMixin, CustomLinksMixin, ExportTemplatesMixin, ImageAttachmentsMixin, TagsMixin, +) +from .base import BaseCircuitType __all__ = ( 'Circuit', @@ -19,16 +24,11 @@ __all__ = ( ) -class CircuitType(OrganizationalModel): +class CircuitType(BaseCircuitType): """ Circuits can be organized by their functional role. For example, a user might wish to define CircuitTypes named "Long Haul," "Metro," or "Out-of-Band". """ - color = ColorField( - verbose_name=_('color'), - blank=True - ) - class Meta: ordering = ('name',) verbose_name = _('circuit type') @@ -59,7 +59,7 @@ class Circuit(ContactsMixin, ImageAttachmentsMixin, DistanceMixin, PrimaryModel) null=True ) type = models.ForeignKey( - to='CircuitType', + to='circuits.CircuitType', on_delete=models.PROTECT, related_name='circuits' ) @@ -111,6 +111,13 @@ class Circuit(ContactsMixin, ImageAttachmentsMixin, DistanceMixin, PrimaryModel) null=True ) + group_assignments = GenericRelation( + to='circuits.CircuitGroupAssignment', + content_type_field='member_type', + object_id_field='member_id', + related_query_name='circuit' + ) + clone_fields = ( 'provider', 'provider_account', 'type', 'status', 'tenant', 'install_date', 'termination_date', 'commit_rate', 'description', @@ -171,15 +178,23 @@ class CircuitGroup(OrganizationalModel): class CircuitGroupAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedModel): """ - Assignment of a Circuit to a CircuitGroup with an optional priority. + Assignment of a physical or virtual circuit to a CircuitGroup with an optional priority. """ - circuit = models.ForeignKey( - Circuit, - on_delete=models.CASCADE, - related_name='assignments' + member_type = models.ForeignKey( + to='contenttypes.ContentType', + limit_choices_to=CIRCUIT_GROUP_ASSIGNMENT_MEMBER_MODELS, + on_delete=models.PROTECT, + related_name='+' + ) + member_id = models.PositiveBigIntegerField( + verbose_name=_('member ID') + ) + member = GenericForeignKey( + ct_field='member_type', + fk_field='member_id' ) group = models.ForeignKey( - CircuitGroup, + to='circuits.CircuitGroup', on_delete=models.CASCADE, related_name='assignments' ) @@ -187,19 +202,19 @@ class CircuitGroupAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, verbose_name=_('priority'), max_length=50, choices=CircuitPriorityChoices, - blank=True + blank=True, + null=True ) prerequisite_models = ( - 'circuits.Circuit', 'circuits.CircuitGroup', ) class Meta: - ordering = ('group', 'circuit', 'priority', 'pk') + ordering = ('group', 'member_type', 'member_id', 'priority', 'pk') constraints = ( models.UniqueConstraint( - fields=('circuit', 'group'), - name='%(app_label)s_%(class)s_unique_circuit_group' + fields=('member_type', 'member_id', 'group'), + name='%(app_label)s_%(class)s_unique_member_group' ), ) verbose_name = _('Circuit group assignment') @@ -229,22 +244,24 @@ class CircuitTermination( term_side = models.CharField( max_length=1, choices=CircuitTerminationSideChoices, - verbose_name=_('termination') + verbose_name=_('termination side') ) - site = models.ForeignKey( - to='dcim.Site', + termination_type = models.ForeignKey( + to='contenttypes.ContentType', on_delete=models.PROTECT, - related_name='circuit_terminations', + limit_choices_to=Q(model__in=CIRCUIT_TERMINATION_TERMINATION_TYPES), + related_name='+', blank=True, null=True ) - provider_network = models.ForeignKey( - to='circuits.ProviderNetwork', - on_delete=models.PROTECT, - related_name='circuit_terminations', + termination_id = models.PositiveBigIntegerField( blank=True, null=True ) + termination = GenericForeignKey( + ct_field='termination_type', + fk_field='termination_id' + ) port_speed = models.PositiveIntegerField( verbose_name=_('port speed (Kbps)'), blank=True, @@ -275,6 +292,43 @@ class CircuitTermination( blank=True ) + # Cached associations to enable efficient filtering + _provider_network = models.ForeignKey( + to='circuits.ProviderNetwork', + on_delete=models.PROTECT, + related_name='circuit_terminations', + blank=True, + null=True + ) + _location = models.ForeignKey( + to='dcim.Location', + on_delete=models.CASCADE, + related_name='circuit_terminations', + blank=True, + null=True + ) + _site = models.ForeignKey( + to='dcim.Site', + on_delete=models.CASCADE, + related_name='circuit_terminations', + blank=True, + null=True + ) + _region = models.ForeignKey( + to='dcim.Region', + on_delete=models.CASCADE, + related_name='circuit_terminations', + blank=True, + null=True + ) + _site_group = models.ForeignKey( + to='dcim.SiteGroup', + on_delete=models.CASCADE, + related_name='circuit_terminations', + blank=True, + null=True + ) + class Meta: ordering = ['circuit', 'term_side'] constraints = ( @@ -296,10 +350,35 @@ class CircuitTermination( super().clean() # Must define either site *or* provider network - if self.site is None and self.provider_network is None: - raise ValidationError(_("A circuit termination must attach to either a site or a provider network.")) - if self.site and self.provider_network: - raise ValidationError(_("A circuit termination cannot attach to both a site and a provider network.")) + if self.termination is None: + raise ValidationError(_("A circuit termination must attach to termination.")) + + def save(self, *args, **kwargs): + # Cache objects associated with the terminating object (for filtering) + self.cache_related_objects() + + super().save(*args, **kwargs) + + def cache_related_objects(self): + self._provider_network = self._region = self._site_group = self._site = self._location = None + if self.termination_type: + termination_type = self.termination_type.model_class() + if termination_type == apps.get_model('dcim', 'region'): + self._region = self.termination + elif termination_type == apps.get_model('dcim', 'sitegroup'): + self._site_group = self.termination + elif termination_type == apps.get_model('dcim', 'site'): + self._region = self.termination.region + self._site_group = self.termination.group + self._site = self.termination + elif termination_type == apps.get_model('dcim', 'location'): + self._region = self.termination.site.region + self._site_group = self.termination.site.group + self._site = self.termination.site + self._location = self.termination + elif termination_type == apps.get_model('circuits', 'providernetwork'): + self._provider_network = self.termination + cache_related_objects.alters_data = True def to_objectchange(self, action): objectchange = super().to_objectchange(action) @@ -313,7 +392,7 @@ class CircuitTermination( def get_peer_termination(self): peer_side = 'Z' if self.term_side == 'A' else 'A' try: - return CircuitTermination.objects.prefetch_related('site').get( + return CircuitTermination.objects.prefetch_related('termination').get( circuit=self.circuit, term_side=peer_side ) diff --git a/netbox/circuits/models/providers.py b/netbox/circuits/models/providers.py index f0fe77b1a..be81caa54 100644 --- a/netbox/circuits/models/providers.py +++ b/netbox/circuits/models/providers.py @@ -21,7 +21,8 @@ class Provider(ContactsMixin, PrimaryModel): verbose_name=_('name'), max_length=100, unique=True, - help_text=_('Full name of the provider') + help_text=_('Full name of the provider'), + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), @@ -95,7 +96,8 @@ class ProviderNetwork(PrimaryModel): """ name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) provider = models.ForeignKey( to='circuits.Provider', diff --git a/netbox/circuits/models/virtual_circuits.py b/netbox/circuits/models/virtual_circuits.py new file mode 100644 index 000000000..ff910549d --- /dev/null +++ b/netbox/circuits/models/virtual_circuits.py @@ -0,0 +1,191 @@ +from functools import cached_property + +from django.contrib.contenttypes.fields import GenericRelation +from django.core.exceptions import ValidationError +from django.db import models +from django.urls import reverse +from django.utils.translation import gettext_lazy as _ + +from circuits.choices import * +from netbox.models import ChangeLoggedModel, PrimaryModel +from netbox.models.features import CustomFieldsMixin, CustomLinksMixin, TagsMixin +from .base import BaseCircuitType + +__all__ = ( + 'VirtualCircuit', + 'VirtualCircuitTermination', + 'VirtualCircuitType', +) + + +class VirtualCircuitType(BaseCircuitType): + """ + Like physical circuits, virtual circuits can be organized by their functional role. For example, a user might wish + to categorize virtual circuits by their technological nature or by product name. + """ + class Meta: + ordering = ('name',) + verbose_name = _('virtual circuit type') + verbose_name_plural = _('virtual circuit types') + + +class VirtualCircuit(PrimaryModel): + """ + A virtual connection between two or more endpoints, delivered across one or more physical circuits. + """ + cid = models.CharField( + max_length=100, + verbose_name=_('circuit ID'), + help_text=_('Unique circuit ID') + ) + provider_network = models.ForeignKey( + to='circuits.ProviderNetwork', + on_delete=models.PROTECT, + related_name='virtual_circuits' + ) + provider_account = models.ForeignKey( + to='circuits.ProviderAccount', + on_delete=models.PROTECT, + related_name='virtual_circuits', + blank=True, + null=True + ) + type = models.ForeignKey( + to='circuits.VirtualCircuitType', + on_delete=models.PROTECT, + related_name='virtual_circuits' + ) + status = models.CharField( + verbose_name=_('status'), + max_length=50, + choices=CircuitStatusChoices, + default=CircuitStatusChoices.STATUS_ACTIVE + ) + tenant = models.ForeignKey( + to='tenancy.Tenant', + on_delete=models.PROTECT, + related_name='virtual_circuits', + blank=True, + null=True + ) + + group_assignments = GenericRelation( + to='circuits.CircuitGroupAssignment', + content_type_field='member_type', + object_id_field='member_id', + related_query_name='virtual_circuit' + ) + + clone_fields = ( + 'provider_network', 'provider_account', 'status', 'tenant', 'description', + ) + prerequisite_models = ( + 'circuits.ProviderNetwork', + 'circuits.VirtualCircuitType', + ) + + class Meta: + ordering = ['provider_network', 'provider_account', 'cid'] + constraints = ( + models.UniqueConstraint( + fields=('provider_network', 'cid'), + name='%(app_label)s_%(class)s_unique_provider_network_cid' + ), + models.UniqueConstraint( + fields=('provider_account', 'cid'), + name='%(app_label)s_%(class)s_unique_provideraccount_cid' + ), + ) + verbose_name = _('virtual circuit') + verbose_name_plural = _('virtual circuits') + + def __str__(self): + return self.cid + + def get_status_color(self): + return CircuitStatusChoices.colors.get(self.status) + + def clean(self): + super().clean() + + if self.provider_account and self.provider_network.provider != self.provider_account.provider: + raise ValidationError({ + 'provider_account': "The assigned account must belong to the provider of the assigned network." + }) + + @property + def provider(self): + return self.provider_network.provider + + +class VirtualCircuitTermination( + CustomFieldsMixin, + CustomLinksMixin, + TagsMixin, + ChangeLoggedModel +): + virtual_circuit = models.ForeignKey( + to='circuits.VirtualCircuit', + on_delete=models.CASCADE, + related_name='terminations' + ) + role = models.CharField( + verbose_name=_('role'), + max_length=50, + choices=VirtualCircuitTerminationRoleChoices, + default=VirtualCircuitTerminationRoleChoices.ROLE_PEER + ) + interface = models.OneToOneField( + to='dcim.Interface', + on_delete=models.CASCADE, + related_name='virtual_circuit_termination' + ) + description = models.CharField( + verbose_name=_('description'), + max_length=200, + blank=True + ) + + class Meta: + ordering = ['virtual_circuit', 'role', 'pk'] + verbose_name = _('virtual circuit termination') + verbose_name_plural = _('virtual circuit terminations') + + def __str__(self): + return f'{self.virtual_circuit}: {self.get_role_display()} termination' + + def get_absolute_url(self): + return reverse('circuits:virtualcircuittermination', args=[self.pk]) + + def get_role_color(self): + return VirtualCircuitTerminationRoleChoices.colors.get(self.role) + + def to_objectchange(self, action): + objectchange = super().to_objectchange(action) + objectchange.related_object = self.virtual_circuit + return objectchange + + @property + def parent_object(self): + return self.virtual_circuit + + @cached_property + def peer_terminations(self): + if self.role == VirtualCircuitTerminationRoleChoices.ROLE_PEER: + return self.virtual_circuit.terminations.exclude(pk=self.pk).filter( + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER + ) + if self.role == VirtualCircuitTerminationRoleChoices.ROLE_HUB: + return self.virtual_circuit.terminations.filter( + role=VirtualCircuitTerminationRoleChoices.ROLE_SPOKE + ) + if self.role == VirtualCircuitTerminationRoleChoices.ROLE_SPOKE: + return self.virtual_circuit.terminations.filter( + role=VirtualCircuitTerminationRoleChoices.ROLE_HUB + ) + + def clean(self): + super().clean() + + if self.interface and not self.interface.is_virtual: + raise ValidationError("Virtual circuits may be terminated only to virtual interfaces.") diff --git a/netbox/circuits/search.py b/netbox/circuits/search.py index 7a5711f03..2ea11b7fd 100644 --- a/netbox/circuits/search.py +++ b/netbox/circuits/search.py @@ -80,3 +80,34 @@ class ProviderNetworkIndex(SearchIndex): ('comments', 5000), ) display_attrs = ('provider', 'service_id', 'description') + + +@register_search +class VirtualCircuitIndex(SearchIndex): + model = models.VirtualCircuit + fields = ( + ('cid', 100), + ('description', 500), + ('comments', 5000), + ) + display_attrs = ('provider', 'provider_network', 'provider_account', 'status', 'tenant', 'description') + + +@register_search +class VirtualCircuitTerminationIndex(SearchIndex): + model = models.VirtualCircuitTermination + fields = ( + ('description', 500), + ) + display_attrs = ('virtual_circuit', 'role', 'description') + + +@register_search +class VirtualCircuitTypeIndex(SearchIndex): + model = models.VirtualCircuitType + fields = ( + ('name', 100), + ('slug', 110), + ('description', 500), + ) + display_attrs = ('description',) diff --git a/netbox/circuits/tables/__init__.py b/netbox/circuits/tables/__init__.py index b61c13cae..a436eb88d 100644 --- a/netbox/circuits/tables/__init__.py +++ b/netbox/circuits/tables/__init__.py @@ -1,3 +1,4 @@ from .circuits import * from .columns import * from .providers import * +from .virtual_circuits import * diff --git a/netbox/circuits/tables/circuits.py b/netbox/circuits/tables/circuits.py index e79212a14..9e59ec019 100644 --- a/netbox/circuits/tables/circuits.py +++ b/netbox/circuits/tables/circuits.py @@ -18,10 +18,8 @@ __all__ = ( CIRCUITTERMINATION_LINK = """ -{% if value.site %} - {{ value.site }} -{% elif value.provider_network %} - {{ value.provider_network }} +{% if value.termination %} + {{ value.termination }} {% endif %} """ @@ -44,9 +42,10 @@ class CircuitTypeTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = CircuitType fields = ( - 'pk', 'id', 'name', 'circuit_count', 'color', 'description', 'slug', 'tags', 'created', 'last_updated', 'actions', + 'pk', 'id', 'name', 'circuit_count', 'color', 'description', 'slug', 'tags', 'created', 'last_updated', + 'actions', ) - default_columns = ('pk', 'name', 'circuit_count', 'description', 'slug') + default_columns = ('pk', 'name', 'circuit_count', 'color', 'description') class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): @@ -62,13 +61,17 @@ class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): linkify=True, verbose_name=_('Account') ) + type = tables.Column( + verbose_name=_('Type'), + linkify=True + ) status = columns.ChoiceFieldColumn() - termination_a = tables.TemplateColumn( + termination_a = columns.TemplateColumn( template_code=CIRCUITTERMINATION_LINK, orderable=False, verbose_name=_('Side A') ) - termination_z = tables.TemplateColumn( + termination_z = columns.TemplateColumn( template_code=CIRCUITTERMINATION_LINK, orderable=False, verbose_name=_('Side Z') @@ -110,22 +113,54 @@ class CircuitTerminationTable(NetBoxTable): linkify=True, accessor='circuit.provider' ) + term_side = tables.Column( + verbose_name=_('Side') + ) + termination_type = columns.ContentTypeColumn( + verbose_name=_('Termination Type'), + ) + termination = tables.Column( + verbose_name=_('Termination Point'), + linkify=True + ) + + # Termination types site = tables.Column( verbose_name=_('Site'), - linkify=True + linkify=True, + accessor='_site' + ) + site_group = tables.Column( + verbose_name=_('Site Group'), + linkify=True, + accessor='_sitegroup' + ) + region = tables.Column( + verbose_name=_('Region'), + linkify=True, + accessor='_region' + ) + location = tables.Column( + verbose_name=_('Location'), + linkify=True, + accessor='_location' ) provider_network = tables.Column( verbose_name=_('Provider Network'), - linkify=True + linkify=True, + accessor='_provider_network' ) class Meta(NetBoxTable.Meta): model = CircuitTermination fields = ( - 'pk', 'id', 'circuit', 'provider', 'term_side', 'site', 'provider_network', 'port_speed', 'upstream_speed', - 'xconnect_id', 'pp_info', 'description', 'created', 'last_updated', 'actions', + 'pk', 'id', 'circuit', 'provider', 'term_side', 'termination_type', 'termination', 'site_group', 'region', + 'site', 'location', 'provider_network', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', + 'description', 'created', 'last_updated', 'actions', + ) + default_columns = ( + 'pk', 'id', 'circuit', 'provider', 'term_side', 'termination_type', 'termination', 'description', ) - default_columns = ('pk', 'id', 'circuit', 'provider', 'term_side', 'description') class CircuitGroupTable(NetBoxTable): @@ -157,11 +192,14 @@ class CircuitGroupAssignmentTable(NetBoxTable): linkify=True ) provider = tables.Column( - accessor='circuit__provider', + accessor='member__provider', verbose_name=_('Provider'), linkify=True ) - circuit = tables.Column( + member_type = columns.ContentTypeColumn( + verbose_name=_('Type') + ) + member = tables.Column( verbose_name=_('Circuit'), linkify=True ) @@ -175,6 +213,7 @@ class CircuitGroupAssignmentTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = CircuitGroupAssignment fields = ( - 'pk', 'id', 'group', 'provider', 'circuit', 'priority', 'created', 'last_updated', 'actions', 'tags', + 'pk', 'id', 'group', 'provider', 'member_type', 'member', 'priority', 'created', 'last_updated', 'actions', + 'tags', ) - default_columns = ('pk', 'group', 'provider', 'circuit', 'priority') + default_columns = ('pk', 'group', 'provider', 'member_type', 'member', 'priority') diff --git a/netbox/circuits/tables/virtual_circuits.py b/netbox/circuits/tables/virtual_circuits.py new file mode 100644 index 000000000..67ac03d59 --- /dev/null +++ b/netbox/circuits/tables/virtual_circuits.py @@ -0,0 +1,124 @@ +import django_tables2 as tables +from django.utils.translation import gettext_lazy as _ + +from circuits.models import * +from netbox.tables import NetBoxTable, columns +from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin + +__all__ = ( + 'VirtualCircuitTable', + 'VirtualCircuitTerminationTable', + 'VirtualCircuitTypeTable', +) + + +class VirtualCircuitTypeTable(NetBoxTable): + name = tables.Column( + linkify=True, + verbose_name=_('Name'), + ) + color = columns.ColorColumn() + tags = columns.TagColumn( + url_name='circuits:virtualcircuittype_list' + ) + virtual_circuit_count = columns.LinkedCountColumn( + viewname='circuits:virtualcircuit_list', + url_params={'type_id': 'pk'}, + verbose_name=_('Circuits') + ) + + class Meta(NetBoxTable.Meta): + model = VirtualCircuitType + fields = ( + 'pk', 'id', 'name', 'virtual_circuit_count', 'color', 'description', 'slug', 'tags', 'created', + 'last_updated', 'actions', + ) + default_columns = ('pk', 'name', 'virtual_circuit_count', 'color', 'description') + + +class VirtualCircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): + cid = tables.Column( + linkify=True, + verbose_name=_('Circuit ID') + ) + provider = tables.Column( + accessor=tables.A('provider_network__provider'), + verbose_name=_('Provider'), + linkify=True + ) + provider_network = tables.Column( + linkify=True, + verbose_name=_('Provider network') + ) + provider_account = tables.Column( + linkify=True, + verbose_name=_('Account') + ) + type = tables.Column( + verbose_name=_('Type'), + linkify=True + ) + status = columns.ChoiceFieldColumn() + termination_count = columns.LinkedCountColumn( + viewname='circuits:virtualcircuittermination_list', + url_params={'virtual_circuit_id': 'pk'}, + verbose_name=_('Terminations') + ) + comments = columns.MarkdownColumn( + verbose_name=_('Comments') + ) + tags = columns.TagColumn( + url_name='circuits:virtualcircuit_list' + ) + + class Meta(NetBoxTable.Meta): + model = VirtualCircuit + fields = ( + 'pk', 'id', 'cid', 'provider', 'provider_account', 'provider_network', 'type', 'status', 'tenant', + 'tenant_group', 'description', 'comments', 'tags', 'created', 'last_updated', + ) + default_columns = ( + 'pk', 'cid', 'provider', 'provider_account', 'provider_network', 'type', 'status', 'tenant', + 'termination_count', 'description', + ) + + +class VirtualCircuitTerminationTable(NetBoxTable): + virtual_circuit = tables.Column( + verbose_name=_('Virtual circuit'), + linkify=True + ) + provider = tables.Column( + accessor=tables.A('virtual_circuit__provider_network__provider'), + verbose_name=_('Provider'), + linkify=True + ) + provider_network = tables.Column( + accessor=tables.A('virtual_circuit__provider_network'), + linkify=True, + verbose_name=_('Provider network') + ) + provider_account = tables.Column( + linkify=True, + verbose_name=_('Account') + ) + role = columns.ChoiceFieldColumn() + device = tables.Column( + accessor=tables.A('interface__device'), + linkify=True, + verbose_name=_('Device') + ) + interface = tables.Column( + verbose_name=_('Interface'), + linkify=True + ) + + class Meta(NetBoxTable.Meta): + model = VirtualCircuitTermination + fields = ( + 'pk', 'id', 'virtual_circuit', 'provider', 'provider_network', 'provider_account', 'role', 'interfaces', + 'description', 'created', 'last_updated', 'actions', + ) + default_columns = ( + 'pk', 'id', 'virtual_circuit', 'role', 'device', 'interface', 'description', + ) diff --git a/netbox/circuits/tests/test_api.py b/netbox/circuits/tests/test_api.py index 1edcd531b..3b8280236 100644 --- a/netbox/circuits/tests/test_api.py +++ b/netbox/circuits/tests/test_api.py @@ -2,7 +2,8 @@ from django.urls import reverse from circuits.choices import * from circuits.models import * -from dcim.models import Site +from dcim.choices import InterfaceTypeChoices +from dcim.models import Device, DeviceRole, DeviceType, Interface, Manufacturer, Site from ipam.models import ASN, RIR from utilities.testing import APITestCase, APIViewTestCases @@ -120,9 +121,15 @@ class CircuitTest(APIViewTestCases.APIViewTestCase): CircuitType.objects.bulk_create(circuit_types) circuits = ( - Circuit(cid='Circuit 1', provider=providers[0], provider_account=provider_accounts[0], type=circuit_types[0]), - Circuit(cid='Circuit 2', provider=providers[0], provider_account=provider_accounts[0], type=circuit_types[0]), - Circuit(cid='Circuit 3', provider=providers[0], provider_account=provider_accounts[0], type=circuit_types[0]), + Circuit( + cid='Circuit 1', provider=providers[0], provider_account=provider_accounts[0], type=circuit_types[0] + ), + Circuit( + cid='Circuit 2', provider=providers[0], provider_account=provider_accounts[0], type=circuit_types[0] + ), + Circuit( + cid='Circuit 3', provider=providers[0], provider_account=provider_accounts[0], type=circuit_types[0] + ), ) Circuit.objects.bulk_create(circuits) @@ -181,10 +188,10 @@ class CircuitTerminationTest(APIViewTestCases.APIViewTestCase): Circuit.objects.bulk_create(circuits) circuit_terminations = ( - CircuitTermination(circuit=circuits[0], term_side=SIDE_A, site=sites[0]), - CircuitTermination(circuit=circuits[0], term_side=SIDE_Z, provider_network=provider_networks[0]), - CircuitTermination(circuit=circuits[1], term_side=SIDE_A, site=sites[1]), - CircuitTermination(circuit=circuits[1], term_side=SIDE_Z, provider_network=provider_networks[1]), + CircuitTermination(circuit=circuits[0], term_side=SIDE_A, termination=sites[0]), + CircuitTermination(circuit=circuits[0], term_side=SIDE_Z, termination=provider_networks[0]), + CircuitTermination(circuit=circuits[1], term_side=SIDE_A, termination=sites[1]), + CircuitTermination(circuit=circuits[1], term_side=SIDE_Z, termination=provider_networks[1]), ) CircuitTermination.objects.bulk_create(circuit_terminations) @@ -192,13 +199,15 @@ class CircuitTerminationTest(APIViewTestCases.APIViewTestCase): { 'circuit': circuits[2].pk, 'term_side': SIDE_A, - 'site': sites[0].pk, + 'termination_type': 'dcim.site', + 'termination_id': sites[0].pk, 'port_speed': 200000, }, { 'circuit': circuits[2].pk, 'term_side': SIDE_Z, - 'provider_network': provider_networks[0].pk, + 'termination_type': 'circuits.providernetwork', + 'termination_id': provider_networks[0].pk, 'port_speed': 200000, }, ] @@ -286,7 +295,7 @@ class ProviderAccountTest(APIViewTestCases.APIViewTestCase): class CircuitGroupAssignmentTest(APIViewTestCases.APIViewTestCase): model = CircuitGroupAssignment - brief_fields = ['circuit', 'display', 'group', 'id', 'priority', 'url'] + brief_fields = ['display', 'group', 'id', 'member', 'member_id', 'member_type', 'priority', 'url'] bulk_update_data = { 'priority': CircuitPriorityChoices.PRIORITY_INACTIVE, } @@ -321,17 +330,17 @@ class CircuitGroupAssignmentTest(APIViewTestCases.APIViewTestCase): assignments = ( CircuitGroupAssignment( group=circuit_groups[0], - circuit=circuits[0], + member=circuits[0], priority=CircuitPriorityChoices.PRIORITY_PRIMARY ), CircuitGroupAssignment( group=circuit_groups[1], - circuit=circuits[1], + member=circuits[1], priority=CircuitPriorityChoices.PRIORITY_SECONDARY ), CircuitGroupAssignment( group=circuit_groups[2], - circuit=circuits[2], + member=circuits[2], priority=CircuitPriorityChoices.PRIORITY_TERTIARY ), ) @@ -340,17 +349,20 @@ class CircuitGroupAssignmentTest(APIViewTestCases.APIViewTestCase): cls.create_data = [ { 'group': circuit_groups[3].pk, - 'circuit': circuits[3].pk, + 'member_type': 'circuits.circuit', + 'member_id': circuits[3].pk, 'priority': CircuitPriorityChoices.PRIORITY_PRIMARY, }, { 'group': circuit_groups[4].pk, - 'circuit': circuits[4].pk, + 'member_type': 'circuits.circuit', + 'member_id': circuits[4].pk, 'priority': CircuitPriorityChoices.PRIORITY_SECONDARY, }, { 'group': circuit_groups[5].pk, - 'circuit': circuits[5].pk, + 'member_type': 'circuits.circuit', + 'member_id': circuits[5].pk, 'priority': CircuitPriorityChoices.PRIORITY_TERTIARY, }, ] @@ -395,3 +407,290 @@ class ProviderNetworkTest(APIViewTestCases.APIViewTestCase): 'provider': providers[1].pk, 'description': 'New description', } + + +class VirtualCircuitTypeTest(APIViewTestCases.APIViewTestCase): + model = VirtualCircuitType + brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url', 'virtual_circuit_count'] + create_data = ( + { + 'name': 'Virtual Circuit Type 4', + 'slug': 'virtual-circuit-type-4', + }, + { + 'name': 'Virtual Circuit Type 5', + 'slug': 'virtual-circuit-type-5', + }, + { + 'name': 'Virtual Circuit Type 6', + 'slug': 'virtual-circuit-type-6', + }, + ) + bulk_update_data = { + 'description': 'New description', + } + + @classmethod + def setUpTestData(cls): + + virtual_circuit_types = ( + VirtualCircuitType(name='Virtual Circuit Type 1', slug='virtual-circuit-type-1'), + VirtualCircuitType(name='Virtual Circuit Type 2', slug='virtual-circuit-type-2'), + VirtualCircuitType(name='Virtual Circuit Type 3', slug='virtual-circuit-type-3'), + ) + VirtualCircuitType.objects.bulk_create(virtual_circuit_types) + + +class VirtualCircuitTest(APIViewTestCases.APIViewTestCase): + model = VirtualCircuit + brief_fields = ['cid', 'description', 'display', 'id', 'provider_network', 'url'] + bulk_update_data = { + 'status': 'planned', + } + + @classmethod + def setUpTestData(cls): + provider = Provider.objects.create(name='Provider 1', slug='provider-1') + provider_network = ProviderNetwork.objects.create(provider=provider, name='Provider Network 1') + provider_account = ProviderAccount.objects.create(provider=provider, account='Provider Account 1') + virtual_circuit_type = VirtualCircuitType.objects.create( + name='Virtual Circuit Type 1', + slug='virtual-circuit-type-1' + ) + + virtual_circuits = ( + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + type=virtual_circuit_type, + cid='Virtual Circuit 1' + ), + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + type=virtual_circuit_type, + cid='Virtual Circuit 2' + ), + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + type=virtual_circuit_type, + cid='Virtual Circuit 3' + ), + ) + VirtualCircuit.objects.bulk_create(virtual_circuits) + + cls.create_data = [ + { + 'cid': 'Virtual Circuit 4', + 'provider_network': provider_network.pk, + 'provider_account': provider_account.pk, + 'type': virtual_circuit_type.pk, + 'status': CircuitStatusChoices.STATUS_PLANNED, + }, + { + 'cid': 'Virtual Circuit 5', + 'provider_network': provider_network.pk, + 'provider_account': provider_account.pk, + 'type': virtual_circuit_type.pk, + 'status': CircuitStatusChoices.STATUS_PLANNED, + }, + { + 'cid': 'Virtual Circuit 6', + 'provider_network': provider_network.pk, + 'provider_account': provider_account.pk, + 'type': virtual_circuit_type.pk, + 'status': CircuitStatusChoices.STATUS_PLANNED, + }, + ] + + +class VirtualCircuitTerminationTest(APIViewTestCases.APIViewTestCase): + model = VirtualCircuitTermination + brief_fields = ['description', 'display', 'id', 'interface', 'role', 'url', 'virtual_circuit'] + bulk_update_data = { + 'description': 'New description', + } + + @classmethod + def setUpTestData(cls): + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + site = Site.objects.create(name='Site 1', slug='site-1') + + devices = ( + Device(site=site, name='hub', device_type=device_type, role=device_role), + Device(site=site, name='spoke1', device_type=device_type, role=device_role), + Device(site=site, name='spoke2', device_type=device_type, role=device_role), + Device(site=site, name='spoke3', device_type=device_type, role=device_role), + ) + Device.objects.bulk_create(devices) + + physical_interfaces = ( + Interface(device=devices[0], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface(device=devices[1], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface(device=devices[2], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface(device=devices[3], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + ) + Interface.objects.bulk_create(physical_interfaces) + + virtual_interfaces = ( + # Point-to-point VCs + Interface( + device=devices[0], + name='eth0.1', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[0], + name='eth0.2', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[0], + name='eth0.3', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[1], + name='eth0.1', + parent=physical_interfaces[1], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[2], + name='eth0.1', + parent=physical_interfaces[2], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[3], + name='eth0.1', + parent=physical_interfaces[3], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + + # Hub and spoke VCs + Interface( + device=devices[0], + name='eth0.9', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[1], + name='eth0.9', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[2], + name='eth0.9', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[3], + name='eth0.9', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + ) + Interface.objects.bulk_create(virtual_interfaces) + + provider = Provider.objects.create(name='Provider 1', slug='provider-1') + provider_network = ProviderNetwork.objects.create(provider=provider, name='Provider Network 1') + provider_account = ProviderAccount.objects.create(provider=provider, account='Provider Account 1') + virtual_circuit_type = VirtualCircuitType.objects.create( + name='Virtual Circuit Type 1', + slug='virtual-circuit-type-1' + ) + + virtual_circuits = ( + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + cid='Virtual Circuit 1', + type=virtual_circuit_type + ), + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + cid='Virtual Circuit 2', + type=virtual_circuit_type + ), + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + cid='Virtual Circuit 3', + type=virtual_circuit_type + ), + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + cid='Virtual Circuit 4', + type=virtual_circuit_type + ), + ) + VirtualCircuit.objects.bulk_create(virtual_circuits) + + virtual_circuit_terminations = ( + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[0], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[0] + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[0], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[3] + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[1], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[1] + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[1], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[4] + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[2], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[2] + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[2], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[5] + ), + ) + VirtualCircuitTermination.objects.bulk_create(virtual_circuit_terminations) + + cls.create_data = [ + { + 'virtual_circuit': virtual_circuits[3].pk, + 'role': VirtualCircuitTerminationRoleChoices.ROLE_HUB, + 'interface': virtual_interfaces[6].pk + }, + { + 'virtual_circuit': virtual_circuits[3].pk, + 'role': VirtualCircuitTerminationRoleChoices.ROLE_SPOKE, + 'interface': virtual_interfaces[7].pk + }, + { + 'virtual_circuit': virtual_circuits[3].pk, + 'role': VirtualCircuitTerminationRoleChoices.ROLE_SPOKE, + 'interface': virtual_interfaces[8].pk + }, + { + 'virtual_circuit': virtual_circuits[3].pk, + 'role': VirtualCircuitTerminationRoleChoices.ROLE_SPOKE, + 'interface': virtual_interfaces[9].pk + }, + ] diff --git a/netbox/circuits/tests/test_filtersets.py b/netbox/circuits/tests/test_filtersets.py index 93958298c..b32abd34e 100644 --- a/netbox/circuits/tests/test_filtersets.py +++ b/netbox/circuits/tests/test_filtersets.py @@ -3,7 +3,8 @@ from django.test import TestCase from circuits.choices import * from circuits.filtersets import * from circuits.models import * -from dcim.models import Cable, Region, Site, SiteGroup +from dcim.choices import InterfaceTypeChoices +from dcim.models import Cable, Device, DeviceRole, DeviceType, Interface, Manufacturer, Region, Site, SiteGroup from ipam.models import ASN, RIR from netbox.choices import DistanceUnitChoices from tenancy.models import Tenant, TenantGroup @@ -70,10 +71,12 @@ class ProviderTestCase(TestCase, ChangeLoggedFilterSetTests): ) Circuit.objects.bulk_create(circuits) - CircuitTermination.objects.bulk_create(( - CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A'), - CircuitTermination(circuit=circuits[1], site=sites[0], term_side='A'), - )) + circuit_terminations = ( + CircuitTermination(circuit=circuits[0], termination=sites[0], term_side='A'), + CircuitTermination(circuit=circuits[1], termination=sites[0], term_side='A'), + ) + for ct in circuit_terminations: + ct.save() def test_q(self): params = {'q': 'foobar1'} @@ -223,24 +226,93 @@ class CircuitTestCase(TestCase, ChangeLoggedFilterSetTests): ProviderNetwork.objects.bulk_create(provider_networks) circuits = ( - Circuit(provider=providers[0], provider_account=provider_accounts[0], tenant=tenants[0], type=circuit_types[0], cid='Test Circuit 1', install_date='2020-01-01', termination_date='2021-01-01', commit_rate=1000, status=CircuitStatusChoices.STATUS_ACTIVE, description='foobar1', distance=10, distance_unit=DistanceUnitChoices.UNIT_FOOT), - Circuit(provider=providers[0], provider_account=provider_accounts[0], tenant=tenants[0], type=circuit_types[0], cid='Test Circuit 2', install_date='2020-01-02', termination_date='2021-01-02', commit_rate=2000, status=CircuitStatusChoices.STATUS_ACTIVE, description='foobar2', distance=20, distance_unit=DistanceUnitChoices.UNIT_METER), - Circuit(provider=providers[0], provider_account=provider_accounts[1], tenant=tenants[1], type=circuit_types[0], cid='Test Circuit 3', install_date='2020-01-03', termination_date='2021-01-03', commit_rate=3000, status=CircuitStatusChoices.STATUS_PLANNED, distance=30, distance_unit=DistanceUnitChoices.UNIT_METER), - Circuit(provider=providers[1], provider_account=provider_accounts[1], tenant=tenants[1], type=circuit_types[1], cid='Test Circuit 4', install_date='2020-01-04', termination_date='2021-01-04', commit_rate=4000, status=CircuitStatusChoices.STATUS_PLANNED), - Circuit(provider=providers[1], provider_account=provider_accounts[2], tenant=tenants[2], type=circuit_types[1], cid='Test Circuit 5', install_date='2020-01-05', termination_date='2021-01-05', commit_rate=5000, status=CircuitStatusChoices.STATUS_OFFLINE), - Circuit(provider=providers[1], provider_account=provider_accounts[2], tenant=tenants[2], type=circuit_types[1], cid='Test Circuit 6', install_date='2020-01-06', termination_date='2021-01-06', commit_rate=6000, status=CircuitStatusChoices.STATUS_OFFLINE), + Circuit( + provider=providers[0], + provider_account=provider_accounts[0], + tenant=tenants[0], + type=circuit_types[0], + cid='Test Circuit 1', + install_date='2020-01-01', + termination_date='2021-01-01', + commit_rate=1000, + status=CircuitStatusChoices.STATUS_ACTIVE, + description='foobar1', + distance=10, + distance_unit=DistanceUnitChoices.UNIT_FOOT, + ), + Circuit( + provider=providers[0], + provider_account=provider_accounts[0], + tenant=tenants[0], + type=circuit_types[0], + cid='Test Circuit 2', + install_date='2020-01-02', + termination_date='2021-01-02', + commit_rate=2000, + status=CircuitStatusChoices.STATUS_ACTIVE, + description='foobar2', + distance=20, + distance_unit=DistanceUnitChoices.UNIT_METER, + ), + Circuit( + provider=providers[0], + provider_account=provider_accounts[1], + tenant=tenants[1], + type=circuit_types[0], + cid='Test Circuit 3', + install_date='2020-01-03', + termination_date='2021-01-03', + commit_rate=3000, + status=CircuitStatusChoices.STATUS_PLANNED, + distance=30, + distance_unit=DistanceUnitChoices.UNIT_METER, + ), + Circuit( + provider=providers[1], + provider_account=provider_accounts[1], + tenant=tenants[1], + type=circuit_types[1], + cid='Test Circuit 4', + install_date='2020-01-04', + termination_date='2021-01-04', + commit_rate=4000, + status=CircuitStatusChoices.STATUS_PLANNED, + ), + Circuit( + provider=providers[1], + provider_account=provider_accounts[2], + tenant=tenants[2], + type=circuit_types[1], + cid='Test Circuit 5', + install_date='2020-01-05', + termination_date='2021-01-05', + commit_rate=5000, + status=CircuitStatusChoices.STATUS_OFFLINE, + ), + Circuit( + provider=providers[1], + provider_account=provider_accounts[2], + tenant=tenants[2], + type=circuit_types[1], + cid='Test Circuit 6', + install_date='2020-01-06', + termination_date='2021-01-06', + commit_rate=6000, + status=CircuitStatusChoices.STATUS_OFFLINE, + ), ) Circuit.objects.bulk_create(circuits) circuit_terminations = (( - CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A'), - CircuitTermination(circuit=circuits[1], site=sites[1], term_side='A'), - CircuitTermination(circuit=circuits[2], site=sites[2], term_side='A'), - CircuitTermination(circuit=circuits[3], provider_network=provider_networks[0], term_side='A'), - CircuitTermination(circuit=circuits[4], provider_network=provider_networks[1], term_side='A'), - CircuitTermination(circuit=circuits[5], provider_network=provider_networks[2], term_side='A'), + CircuitTermination(circuit=circuits[0], termination=sites[0], term_side='A'), + CircuitTermination(circuit=circuits[1], termination=sites[1], term_side='A'), + CircuitTermination(circuit=circuits[2], termination=sites[2], term_side='A'), + CircuitTermination(circuit=circuits[3], termination=provider_networks[0], term_side='A'), + CircuitTermination(circuit=circuits[4], termination=provider_networks[1], term_side='A'), + CircuitTermination(circuit=circuits[5], termination=provider_networks[2], term_side='A'), )) - CircuitTermination.objects.bulk_create(circuit_terminations) + for ct in circuit_terminations: + ct.save() def test_q(self): params = {'q': 'foobar1'} @@ -383,19 +455,66 @@ class CircuitTerminationTestCase(TestCase, ChangeLoggedFilterSetTests): ) Circuit.objects.bulk_create(circuits) - circuit_terminations = (( - CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A', port_speed=1000, upstream_speed=1000, xconnect_id='ABC', description='foobar1'), - CircuitTermination(circuit=circuits[0], site=sites[1], term_side='Z', port_speed=1000, upstream_speed=1000, xconnect_id='DEF', description='foobar2'), - CircuitTermination(circuit=circuits[1], site=sites[1], term_side='A', port_speed=2000, upstream_speed=2000, xconnect_id='GHI'), - CircuitTermination(circuit=circuits[1], site=sites[2], term_side='Z', port_speed=2000, upstream_speed=2000, xconnect_id='JKL'), - CircuitTermination(circuit=circuits[2], site=sites[2], term_side='A', port_speed=3000, upstream_speed=3000, xconnect_id='MNO'), - CircuitTermination(circuit=circuits[2], site=sites[0], term_side='Z', port_speed=3000, upstream_speed=3000, xconnect_id='PQR'), - CircuitTermination(circuit=circuits[3], provider_network=provider_networks[0], term_side='A'), - CircuitTermination(circuit=circuits[4], provider_network=provider_networks[1], term_side='A'), - CircuitTermination(circuit=circuits[5], provider_network=provider_networks[2], term_side='A'), - CircuitTermination(circuit=circuits[6], provider_network=provider_networks[0], term_side='A', mark_connected=True), - )) - CircuitTermination.objects.bulk_create(circuit_terminations) + circuit_terminations = ( + CircuitTermination( + circuit=circuits[0], + termination=sites[0], + term_side='A', + port_speed=1000, + upstream_speed=1000, + xconnect_id='ABC', + description='foobar1', + ), + CircuitTermination( + circuit=circuits[0], + termination=sites[1], + term_side='Z', + port_speed=1000, + upstream_speed=1000, + xconnect_id='DEF', + description='foobar2', + ), + CircuitTermination( + circuit=circuits[1], + termination=sites[1], + term_side='A', + port_speed=2000, + upstream_speed=2000, + xconnect_id='GHI', + ), + CircuitTermination( + circuit=circuits[1], + termination=sites[2], + term_side='Z', + port_speed=2000, + upstream_speed=2000, + xconnect_id='JKL', + ), + CircuitTermination( + circuit=circuits[2], + termination=sites[2], + term_side='A', + port_speed=3000, + upstream_speed=3000, + xconnect_id='MNO', + ), + CircuitTermination( + circuit=circuits[2], + termination=sites[0], + term_side='Z', + port_speed=3000, + upstream_speed=3000, + xconnect_id='PQR', + ), + CircuitTermination(circuit=circuits[3], termination=provider_networks[0], term_side='A'), + CircuitTermination(circuit=circuits[4], termination=provider_networks[1], term_side='A'), + CircuitTermination(circuit=circuits[5], termination=provider_networks[2], term_side='A'), + CircuitTermination( + circuit=circuits[6], termination=provider_networks[0], term_side='A', mark_connected=True + ), + ) + for ct in circuit_terminations: + ct.save() Cable(a_terminations=[circuit_terminations[0]], b_terminations=[circuit_terminations[1]]).save() @@ -529,7 +648,6 @@ class CircuitGroupAssignmentTestCase(TestCase, ChangeLoggedFilterSetTests): CircuitGroup(name='Circuit Group 1', slug='circuit-group-1'), CircuitGroup(name='Circuit Group 2', slug='circuit-group-2'), CircuitGroup(name='Circuit Group 3', slug='circuit-group-3'), - CircuitGroup(name='Circuit Group 4', slug='circuit-group-4'), ) CircuitGroup.objects.bulk_create(circuit_groups) @@ -537,43 +655,86 @@ class CircuitGroupAssignmentTestCase(TestCase, ChangeLoggedFilterSetTests): Provider(name='Provider 1', slug='provider-1'), Provider(name='Provider 2', slug='provider-2'), Provider(name='Provider 3', slug='provider-3'), - Provider(name='Provider 4', slug='provider-4'), )) - circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1') + circuit_type = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1') circuits = ( - Circuit(cid='Circuit 1', provider=providers[0], type=circuittype), - Circuit(cid='Circuit 2', provider=providers[1], type=circuittype), - Circuit(cid='Circuit 3', provider=providers[2], type=circuittype), - Circuit(cid='Circuit 4', provider=providers[3], type=circuittype), + Circuit(cid='Circuit 1', provider=providers[0], type=circuit_type), + Circuit(cid='Circuit 2', provider=providers[1], type=circuit_type), + Circuit(cid='Circuit 3', provider=providers[2], type=circuit_type), ) Circuit.objects.bulk_create(circuits) + provider_networks = ( + ProviderNetwork(name='Provider Network 1', provider=providers[0]), + ProviderNetwork(name='Provider Network 2', provider=providers[1]), + ProviderNetwork(name='Provider Network 3', provider=providers[2]), + ) + ProviderNetwork.objects.bulk_create(provider_networks) + + virtual_circuit_type = VirtualCircuitType.objects.create( + name='Virtual Circuit Type 1', + slug='virtual-circuit-type-1' + ) + virtual_circuits = ( + VirtualCircuit( + provider_network=provider_networks[0], + cid='Virtual Circuit 1', + type=virtual_circuit_type + ), + VirtualCircuit( + provider_network=provider_networks[1], + cid='Virtual Circuit 2', + type=virtual_circuit_type + ), + VirtualCircuit( + provider_network=provider_networks[2], + cid='Virtual Circuit 3', + type=virtual_circuit_type + ), + ) + VirtualCircuit.objects.bulk_create(virtual_circuits) + assignments = ( CircuitGroupAssignment( group=circuit_groups[0], - circuit=circuits[0], + member=circuits[0], priority=CircuitPriorityChoices.PRIORITY_PRIMARY ), CircuitGroupAssignment( group=circuit_groups[1], - circuit=circuits[1], + member=circuits[1], priority=CircuitPriorityChoices.PRIORITY_SECONDARY ), CircuitGroupAssignment( group=circuit_groups[2], - circuit=circuits[2], + member=circuits[2], + priority=CircuitPriorityChoices.PRIORITY_TERTIARY + ), + CircuitGroupAssignment( + group=circuit_groups[0], + member=virtual_circuits[0], + priority=CircuitPriorityChoices.PRIORITY_PRIMARY + ), + CircuitGroupAssignment( + group=circuit_groups[1], + member=virtual_circuits[1], + priority=CircuitPriorityChoices.PRIORITY_SECONDARY + ), + CircuitGroupAssignment( + group=circuit_groups[2], + member=virtual_circuits[2], priority=CircuitPriorityChoices.PRIORITY_TERTIARY ), ) CircuitGroupAssignment.objects.bulk_create(assignments) - def test_group_id(self): - groups = CircuitGroup.objects.filter(name__in=['Circuit Group 1', 'Circuit Group 2']) + def test_group(self): + groups = CircuitGroup.objects.all()[:2] params = {'group_id': [groups[0].pk, groups[1].pk]} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) params = {'group': [groups[0].slug, groups[1].slug]} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) def test_circuit(self): circuits = Circuit.objects.all()[:2] @@ -582,12 +743,19 @@ class CircuitGroupAssignmentTestCase(TestCase, ChangeLoggedFilterSetTests): params = {'circuit': [circuits[0].cid, circuits[1].cid]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_virtual_circuit(self): + virtual_circuits = VirtualCircuit.objects.all()[:2] + params = {'virtual_circuit_id': [virtual_circuits[0].pk, virtual_circuits[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'virtual_circuit': [virtual_circuits[0].cid, virtual_circuits[1].cid]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_provider(self): providers = Provider.objects.all()[:2] params = {'provider_id': [providers[0].pk, providers[1].pk]} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) params = {'provider': [providers[0].slug, providers[1].slug]} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) class ProviderNetworkTestCase(TestCase, ChangeLoggedFilterSetTests): @@ -674,3 +842,347 @@ class ProviderAccountTestCase(TestCase, ChangeLoggedFilterSetTests): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) params = {'provider': [providers[0].slug, providers[1].slug]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class VirtualCircuitTypeTestCase(TestCase, ChangeLoggedFilterSetTests): + queryset = VirtualCircuitType.objects.all() + filterset = VirtualCircuitTypeFilterSet + + @classmethod + def setUpTestData(cls): + + VirtualCircuitType.objects.bulk_create(( + VirtualCircuitType(name='Virtual Circuit Type 1', slug='virtual-circuit-type-1', description='foobar1'), + VirtualCircuitType(name='Virtual Circuit Type 2', slug='virtual-circuit-type-2', description='foobar2'), + VirtualCircuitType(name='Virtual Circuit Type 3', slug='virtual-circuit-type-3'), + )) + + def test_q(self): + params = {'q': 'foobar1'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_name(self): + params = {'name': ['Virtual Circuit Type 1']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_slug(self): + params = {'slug': ['virtual-circuit-type-1']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_description(self): + params = {'description': ['foobar1', 'foobar2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class VirtualCircuitTestCase(TestCase, ChangeLoggedFilterSetTests): + queryset = VirtualCircuit.objects.all() + filterset = VirtualCircuitFilterSet + + @classmethod + def setUpTestData(cls): + + tenant_groups = ( + TenantGroup(name='Tenant group 1', slug='tenant-group-1'), + TenantGroup(name='Tenant group 2', slug='tenant-group-2'), + TenantGroup(name='Tenant group 3', slug='tenant-group-3'), + ) + for tenantgroup in tenant_groups: + tenantgroup.save() + + tenants = ( + Tenant(name='Tenant 1', slug='tenant-1', group=tenant_groups[0]), + Tenant(name='Tenant 2', slug='tenant-2', group=tenant_groups[1]), + Tenant(name='Tenant 3', slug='tenant-3', group=tenant_groups[2]), + ) + Tenant.objects.bulk_create(tenants) + + providers = ( + Provider(name='Provider 1', slug='provider-1'), + Provider(name='Provider 2', slug='provider-2'), + Provider(name='Provider 3', slug='provider-3'), + ) + Provider.objects.bulk_create(providers) + + provider_accounts = ( + ProviderAccount(name='Provider Account 1', provider=providers[0], account='A'), + ProviderAccount(name='Provider Account 2', provider=providers[1], account='B'), + ProviderAccount(name='Provider Account 3', provider=providers[2], account='C'), + ) + ProviderAccount.objects.bulk_create(provider_accounts) + + provider_networks = ( + ProviderNetwork(name='Provider Network 1', provider=providers[0]), + ProviderNetwork(name='Provider Network 2', provider=providers[1]), + ProviderNetwork(name='Provider Network 3', provider=providers[2]), + ) + ProviderNetwork.objects.bulk_create(provider_networks) + + virtual_circuit_types = ( + VirtualCircuitType(name='Virtual Circuit Type 1', slug='virtual-circuit-type-1'), + VirtualCircuitType(name='Virtual Circuit Type 2', slug='virtual-circuit-type-2'), + VirtualCircuitType(name='Virtual Circuit Type 3', slug='virtual-circuit-type-3'), + ) + VirtualCircuitType.objects.bulk_create(virtual_circuit_types) + + virutal_circuits = ( + VirtualCircuit( + provider_network=provider_networks[0], + provider_account=provider_accounts[0], + tenant=tenants[0], + cid='Virtual Circuit 1', + type=virtual_circuit_types[0], + status=CircuitStatusChoices.STATUS_PLANNED, + description='virtualcircuit1', + ), + VirtualCircuit( + provider_network=provider_networks[1], + provider_account=provider_accounts[1], + tenant=tenants[1], + cid='Virtual Circuit 2', + type=virtual_circuit_types[1], + status=CircuitStatusChoices.STATUS_ACTIVE, + description='virtualcircuit2', + ), + VirtualCircuit( + provider_network=provider_networks[2], + provider_account=provider_accounts[2], + tenant=tenants[2], + cid='Virtual Circuit 3', + type=virtual_circuit_types[2], + status=CircuitStatusChoices.STATUS_DEPROVISIONING, + description='virtualcircuit3', + ), + ) + VirtualCircuit.objects.bulk_create(virutal_circuits) + + def test_q(self): + params = {'q': 'virtualcircuit1'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_cid(self): + params = {'cid': ['Virtual Circuit 1', 'Virtual Circuit 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_provider(self): + providers = Provider.objects.all()[:2] + params = {'provider_id': [providers[0].pk, providers[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'provider': [providers[0].slug, providers[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_provider_account(self): + provider_accounts = ProviderAccount.objects.all()[:2] + params = {'provider_account_id': [provider_accounts[0].pk, provider_accounts[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_provider_network(self): + provider_networks = ProviderNetwork.objects.all()[:2] + params = {'provider_network_id': [provider_networks[0].pk, provider_networks[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_type(self): + virtual_circuit_types = VirtualCircuitType.objects.all()[:2] + params = {'type_id': [virtual_circuit_types[0].pk, virtual_circuit_types[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'type': [virtual_circuit_types[0].slug, virtual_circuit_types[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_status(self): + params = {'status': [CircuitStatusChoices.STATUS_ACTIVE, CircuitStatusChoices.STATUS_PLANNED]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_description(self): + params = {'description': ['virtualcircuit1', 'virtualcircuit2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_tenant(self): + tenants = Tenant.objects.all()[:2] + params = {'tenant_id': [tenants[0].pk, tenants[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'tenant': [tenants[0].slug, tenants[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_tenant_group(self): + tenant_groups = TenantGroup.objects.all()[:2] + params = {'tenant_group_id': [tenant_groups[0].pk, tenant_groups[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'tenant_group': [tenant_groups[0].slug, tenant_groups[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class VirtualCircuitTerminationTestCase(TestCase, ChangeLoggedFilterSetTests): + queryset = VirtualCircuitTermination.objects.all() + filterset = VirtualCircuitTerminationFilterSet + + @classmethod + def setUpTestData(cls): + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + site = Site.objects.create(name='Site 1', slug='site-1') + + devices = ( + Device(site=site, name='Device 1', device_type=device_type, role=device_role), + Device(site=site, name='Device 2', device_type=device_type, role=device_role), + Device(site=site, name='Device 3', device_type=device_type, role=device_role), + ) + Device.objects.bulk_create(devices) + + virtual_interfaces = ( + # Device 1 + Interface( + device=devices[0], + name='eth0.1', + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[0], + name='eth0.2', + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + # Device 2 + Interface( + device=devices[1], + name='eth0.1', + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[1], + name='eth0.2', + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + # Device 3 + Interface( + device=devices[2], + name='eth0.1', + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[2], + name='eth0.2', + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + ) + Interface.objects.bulk_create(virtual_interfaces) + + providers = ( + Provider(name='Provider 1', slug='provider-1'), + Provider(name='Provider 2', slug='provider-2'), + Provider(name='Provider 3', slug='provider-3'), + ) + Provider.objects.bulk_create(providers) + provider_networks = ( + ProviderNetwork(provider=providers[0], name='Provider Network 1'), + ProviderNetwork(provider=providers[1], name='Provider Network 2'), + ProviderNetwork(provider=providers[2], name='Provider Network 3'), + ) + ProviderNetwork.objects.bulk_create(provider_networks) + provider_accounts = ( + ProviderAccount(provider=providers[0], account='Provider Account 1'), + ProviderAccount(provider=providers[1], account='Provider Account 2'), + ProviderAccount(provider=providers[2], account='Provider Account 3'), + ) + ProviderAccount.objects.bulk_create(provider_accounts) + virtual_circuit_type = VirtualCircuitType.objects.create( + name='Virtual Circuit Type 1', + slug='virtual-circuit-type-1' + ) + + virtual_circuits = ( + VirtualCircuit( + provider_network=provider_networks[0], + provider_account=provider_accounts[0], + cid='Virtual Circuit 1', + type=virtual_circuit_type + ), + VirtualCircuit( + provider_network=provider_networks[1], + provider_account=provider_accounts[1], + cid='Virtual Circuit 2', + type=virtual_circuit_type + ), + VirtualCircuit( + provider_network=provider_networks[2], + provider_account=provider_accounts[2], + cid='Virtual Circuit 3', + type=virtual_circuit_type + ), + ) + VirtualCircuit.objects.bulk_create(virtual_circuits) + + virtual_circuit_terminations = ( + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[0], + role=VirtualCircuitTerminationRoleChoices.ROLE_HUB, + interface=virtual_interfaces[0], + description='termination1' + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[0], + role=VirtualCircuitTerminationRoleChoices.ROLE_SPOKE, + interface=virtual_interfaces[3], + description='termination2' + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[1], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[1], + description='termination3' + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[1], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[4], + description='termination4' + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[2], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[2], + description='termination5' + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[2], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[5], + description='termination6' + ), + ) + VirtualCircuitTermination.objects.bulk_create(virtual_circuit_terminations) + + def test_q(self): + params = {'q': 'termination1'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_description(self): + params = {'description': ['termination1', 'termination2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_virtual_circuit_id(self): + virtual_circuits = VirtualCircuit.objects.filter()[:2] + params = {'virtual_circuit_id': [virtual_circuits[0].pk, virtual_circuits[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_provider(self): + providers = Provider.objects.all()[:2] + params = {'provider_id': [providers[0].pk, providers[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'provider': [providers[0].slug, providers[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_provider_network(self): + provider_networks = ProviderNetwork.objects.all()[:2] + params = {'provider_network_id': [provider_networks[0].pk, provider_networks[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_provider_account(self): + provider_accounts = ProviderAccount.objects.all()[:2] + params = {'provider_account_id': [provider_accounts[0].pk, provider_accounts[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'provider_account': [provider_accounts[0].account, provider_accounts[1].account]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_interface(self): + interfaces = Interface.objects.all()[:2] + params = {'interface_id': [interfaces[0].pk, interfaces[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) diff --git a/netbox/circuits/tests/test_views.py b/netbox/circuits/tests/test_views.py index b06ade30b..6ced9a958 100644 --- a/netbox/circuits/tests/test_views.py +++ b/netbox/circuits/tests/test_views.py @@ -1,12 +1,14 @@ import datetime +from django.contrib.contenttypes.models import ContentType from django.test import override_settings from django.urls import reverse from circuits.choices import * from circuits.models import * from core.models import ObjectType -from dcim.models import Cable, Interface, Site +from dcim.choices import InterfaceTypeChoices +from dcim.models import Cable, Device, DeviceRole, DeviceType, Interface, Manufacturer, Site from ipam.models import ASN, RIR from netbox.choices import ImportFormatChoices from users.models import ObjectPermission @@ -139,9 +141,15 @@ class CircuitTestCase(ViewTestCases.PrimaryObjectViewTestCase): CircuitType.objects.bulk_create(circuittypes) circuits = ( - Circuit(cid='Circuit 1', provider=providers[0], provider_account=provider_accounts[0], type=circuittypes[0]), - Circuit(cid='Circuit 2', provider=providers[0], provider_account=provider_accounts[0], type=circuittypes[0]), - Circuit(cid='Circuit 3', provider=providers[0], provider_account=provider_accounts[0], type=circuittypes[0]), + Circuit( + cid='Circuit 1', provider=providers[0], provider_account=provider_accounts[0], type=circuittypes[0] + ), + Circuit( + cid='Circuit 2', provider=providers[0], provider_account=provider_accounts[0], type=circuittypes[0] + ), + Circuit( + cid='Circuit 3', provider=providers[0], provider_account=provider_accounts[0], type=circuittypes[0] + ), ) Circuit.objects.bulk_create(circuits) @@ -190,27 +198,31 @@ class CircuitTestCase(ViewTestCases.PrimaryObjectViewTestCase): @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[]) def test_bulk_import_objects_with_terminations(self): - json_data = """ + site = Site.objects.first() + json_data = f""" [ - { + {{ "cid": "Circuit 7", "provider": "Provider 1", "type": "Circuit Type 1", "status": "active", "description": "Testing Import", "terminations": [ - { + {{ "term_side": "A", - "site": "Site 1" - }, - { + "termination_type": "dcim.site", + "termination_id": "{site.pk}" + }}, + {{ "term_side": "Z", - "site": "Site 1" - } + "termination_type": "dcim.site", + "termination_id": "{site.pk}" + }} ] - } + }} ] """ + initial_count = self._get_queryset().count() data = { 'data': json_data, @@ -227,10 +239,10 @@ class CircuitTestCase(ViewTestCases.PrimaryObjectViewTestCase): obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model)) # Try GET with model-level permission - self.assertHttpStatus(self.client.get(self._get_url('import')), 200) + self.assertHttpStatus(self.client.get(self._get_url('bulk_import')), 200) # Test POST with permission - self.assertHttpStatus(self.client.post(self._get_url('import'), data), 302) + self.assertHttpStatus(self.client.post(self._get_url('bulk_import'), data), 302) self.assertEqual(self._get_queryset().count(), initial_count + 1) @@ -359,24 +371,27 @@ class CircuitTerminationTestCase(ViewTestCases.PrimaryObjectViewTestCase): Circuit.objects.bulk_create(circuits) circuit_terminations = ( - CircuitTermination(circuit=circuits[0], term_side='A', site=sites[0]), - CircuitTermination(circuit=circuits[0], term_side='Z', site=sites[1]), - CircuitTermination(circuit=circuits[1], term_side='A', site=sites[0]), - CircuitTermination(circuit=circuits[1], term_side='Z', site=sites[1]), + CircuitTermination(circuit=circuits[0], term_side='A', termination=sites[0]), + CircuitTermination(circuit=circuits[0], term_side='Z', termination=sites[1]), + CircuitTermination(circuit=circuits[1], term_side='A', termination=sites[0]), + CircuitTermination(circuit=circuits[1], term_side='Z', termination=sites[1]), ) - CircuitTermination.objects.bulk_create(circuit_terminations) + for ct in circuit_terminations: + ct.save() cls.form_data = { 'circuit': circuits[2].pk, 'term_side': 'A', - 'site': sites[2].pk, + 'termination_type': ContentType.objects.get_for_model(Site).pk, + 'termination': sites[2].pk, 'description': 'New description', } + site = sites[0].pk cls.csv_data = ( - "circuit,term_side,site,description", - "Circuit 3,A,Site 1,Foo", - "Circuit 3,Z,Site 1,Bar", + "circuit,term_side,termination_type,termination_id,description", + f"Circuit 3,A,dcim.site,{site},Foo", + f"Circuit 3,Z,dcim.site,{site},Bar", ) cls.csv_update_data = ( @@ -453,6 +468,7 @@ class CircuitGroupAssignmentTestCase( ViewTestCases.DeleteObjectViewTestCase, ViewTestCases.ListObjectsViewTestCase, ViewTestCases.BulkEditObjectsViewTestCase, + ViewTestCases.BulkImportObjectsViewTestCase, ViewTestCases.BulkDeleteObjectsViewTestCase ): model = CircuitGroupAssignment @@ -482,17 +498,17 @@ class CircuitGroupAssignmentTestCase( assignments = ( CircuitGroupAssignment( group=circuit_groups[0], - circuit=circuits[0], + member=circuits[0], priority=CircuitPriorityChoices.PRIORITY_PRIMARY ), CircuitGroupAssignment( group=circuit_groups[1], - circuit=circuits[1], + member=circuits[1], priority=CircuitPriorityChoices.PRIORITY_SECONDARY ), CircuitGroupAssignment( group=circuit_groups[2], - circuit=circuits[2], + member=circuits[2], priority=CircuitPriorityChoices.PRIORITY_TERTIARY ), ) @@ -502,11 +518,420 @@ class CircuitGroupAssignmentTestCase( cls.form_data = { 'group': circuit_groups[3].pk, - 'circuit': circuits[3].pk, + 'member_type': ContentType.objects.get_for_model(Circuit).pk, + 'member': circuits[3].pk, 'priority': CircuitPriorityChoices.PRIORITY_INACTIVE, 'tags': [t.pk for t in tags], } + cls.csv_data = ( + "member_type,member_id,group,priority", + f"circuits.circuit,{circuits[0].pk},{circuit_groups[3].pk},primary", + f"circuits.circuit,{circuits[1].pk},{circuit_groups[3].pk},secondary", + f"circuits.circuit,{circuits[2].pk},{circuit_groups[3].pk},tertiary", + ) + + cls.csv_update_data = ( + "id,priority", + f"{assignments[0].pk},inactive", + f"{assignments[1].pk},inactive", + f"{assignments[2].pk},inactive", + ) + cls.bulk_edit_data = { 'priority': CircuitPriorityChoices.PRIORITY_INACTIVE, } + + +class VirtualCircuitTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase): + model = VirtualCircuitType + + @classmethod + def setUpTestData(cls): + + virtual_circuit_types = ( + VirtualCircuitType(name='Virtual Circuit Type 1', slug='circuit-type-1'), + VirtualCircuitType(name='Virtual Circuit Type 2', slug='circuit-type-2'), + VirtualCircuitType(name='Virtual Circuit Type 3', slug='circuit-type-3'), + ) + VirtualCircuitType.objects.bulk_create(virtual_circuit_types) + + tags = create_tags('Alpha', 'Bravo', 'Charlie') + + cls.form_data = { + 'name': 'Virtual Circuit Type X', + 'slug': 'virtual-circuit-type-x', + 'description': 'A new virtual circuit type', + 'tags': [t.pk for t in tags], + } + + cls.csv_data = ( + "name,slug", + "Virtual Circuit Type 4,circuit-type-4", + "Virtual Circuit Type 5,circuit-type-5", + "Virtual Circuit Type 6,circuit-type-6", + ) + + cls.csv_update_data = ( + "id,name,description", + f"{virtual_circuit_types[0].pk},Virtual Circuit Type 7,New description7", + f"{virtual_circuit_types[1].pk},Virtual Circuit Type 8,New description8", + f"{virtual_circuit_types[2].pk},Virtual Circuit Type 9,New description9", + ) + + cls.bulk_edit_data = { + 'description': 'Foo', + } + + +class VirtualCircuitTestCase(ViewTestCases.PrimaryObjectViewTestCase): + model = VirtualCircuit + + def setUp(self): + super().setUp() + + self.add_permissions( + 'circuits.add_virtualcircuittermination', + ) + + @classmethod + def setUpTestData(cls): + provider = Provider.objects.create(name='Provider 1', slug='provider-1') + provider_networks = ( + ProviderNetwork(provider=provider, name='Provider Network 1'), + ProviderNetwork(provider=provider, name='Provider Network 2'), + ) + ProviderNetwork.objects.bulk_create(provider_networks) + provider_accounts = ( + ProviderAccount(provider=provider, account='Provider Account 1'), + ProviderAccount(provider=provider, account='Provider Account 2'), + ) + ProviderAccount.objects.bulk_create(provider_accounts) + virtual_circuit_types = ( + VirtualCircuitType(name='Virtual Circuit Type 1', slug='virtual-circuit-type-1'), + VirtualCircuitType(name='Virtual Circuit Type 2', slug='virtual-circuit-type-2'), + ) + VirtualCircuitType.objects.bulk_create(virtual_circuit_types) + + virtual_circuits = ( + VirtualCircuit( + provider_network=provider_networks[0], + provider_account=provider_accounts[0], + cid='Virtual Circuit 1', + type=virtual_circuit_types[0] + ), + VirtualCircuit( + provider_network=provider_networks[0], + provider_account=provider_accounts[0], + cid='Virtual Circuit 2', + type=virtual_circuit_types[0] + ), + VirtualCircuit( + provider_network=provider_networks[0], + provider_account=provider_accounts[0], + cid='Virtual Circuit 3', + type=virtual_circuit_types[0] + ), + ) + VirtualCircuit.objects.bulk_create(virtual_circuits) + + device = create_test_device('Device 1') + interfaces = ( + Interface(device=device, name='Interface 1', type=InterfaceTypeChoices.TYPE_VIRTUAL), + Interface(device=device, name='Interface 2', type=InterfaceTypeChoices.TYPE_VIRTUAL), + Interface(device=device, name='Interface 3', type=InterfaceTypeChoices.TYPE_VIRTUAL), + ) + Interface.objects.bulk_create(interfaces) + + tags = create_tags('Alpha', 'Bravo', 'Charlie') + + cls.form_data = { + 'cid': 'Virtual Circuit X', + 'provider_network': provider_networks[1].pk, + 'provider_account': provider_accounts[1].pk, + 'type': virtual_circuit_types[1].pk, + 'status': CircuitStatusChoices.STATUS_PLANNED, + 'description': 'A new virtual circuit', + 'comments': 'Some comments', + 'tags': [t.pk for t in tags], + } + + cls.csv_data = ( + "cid,provider_network,provider_account,type,status", + ( + f"Virtual Circuit 4,Provider Network 1,Provider Account 1,{virtual_circuit_types[0].name}," + f"{CircuitStatusChoices.STATUS_PLANNED}" + ), + ( + f"Virtual Circuit 5,Provider Network 1,Provider Account 1,{virtual_circuit_types[0].name}," + f"{CircuitStatusChoices.STATUS_PLANNED}" + ), + ( + f"Virtual Circuit 6,Provider Network 1,Provider Account 1,{virtual_circuit_types[0].name}," + f"{CircuitStatusChoices.STATUS_PLANNED}" + ), + ) + + cls.csv_update_data = ( + "id,cid,description,type,status", + ( + f"{virtual_circuits[0].pk},Virtual Circuit A,New description,{virtual_circuit_types[1].name}," + f"{CircuitStatusChoices.STATUS_DECOMMISSIONED}" + ), + ( + f"{virtual_circuits[1].pk},Virtual Circuit B,New description,{virtual_circuit_types[1].name}," + f"{CircuitStatusChoices.STATUS_DECOMMISSIONED}" + ), + ( + f"{virtual_circuits[2].pk},Virtual Circuit C,New description,{virtual_circuit_types[1].name}," + f"{CircuitStatusChoices.STATUS_DECOMMISSIONED}" + ), + ) + + cls.bulk_edit_data = { + 'provider_network': provider_networks[1].pk, + 'provider_account': provider_accounts[1].pk, + 'type': virtual_circuit_types[1].pk, + 'status': CircuitStatusChoices.STATUS_DECOMMISSIONED, + 'description': 'New description', + 'comments': 'New comments', + } + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[]) + def test_bulk_import_objects_with_terminations(self): + interfaces = Interface.objects.filter(type=InterfaceTypeChoices.TYPE_VIRTUAL) + json_data = f""" + [ + {{ + "cid": "Virtual Circuit 7", + "provider_network": "Provider Network 1", + "type": "Virtual Circuit Type 1", + "status": "active", + "terminations": [ + {{ + "role": "hub", + "interface": {interfaces[0].pk} + }}, + {{ + "role": "spoke", + "interface": {interfaces[1].pk} + }}, + {{ + "role": "spoke", + "interface": {interfaces[2].pk} + }} + ] + }} + ] + """ + + initial_count = self._get_queryset().count() + data = { + 'data': json_data, + 'format': ImportFormatChoices.JSON, + } + + # Assign model-level permission + obj_perm = ObjectPermission( + name='Test permission', + actions=['add'] + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model)) + + # Try GET with model-level permission + self.assertHttpStatus(self.client.get(self._get_url('bulk_import')), 200) + + # Test POST with permission + self.assertHttpStatus(self.client.post(self._get_url('bulk_import'), data), 302) + self.assertEqual(self._get_queryset().count(), initial_count + 1) + + +class VirtualCircuitTerminationTestCase(ViewTestCases.PrimaryObjectViewTestCase): + model = VirtualCircuitTermination + + @classmethod + def setUpTestData(cls): + manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1') + device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') + site = Site.objects.create(name='Site 1', slug='site-1') + + devices = ( + Device(site=site, name='hub', device_type=device_type, role=device_role), + Device(site=site, name='spoke1', device_type=device_type, role=device_role), + Device(site=site, name='spoke2', device_type=device_type, role=device_role), + Device(site=site, name='spoke3', device_type=device_type, role=device_role), + ) + Device.objects.bulk_create(devices) + + physical_interfaces = ( + Interface(device=devices[0], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface(device=devices[1], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface(device=devices[2], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface(device=devices[3], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + ) + Interface.objects.bulk_create(physical_interfaces) + + virtual_interfaces = ( + # Point-to-point VCs + Interface( + device=devices[0], + name='eth0.1', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[0], + name='eth0.2', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[0], + name='eth0.3', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[1], + name='eth0.1', + parent=physical_interfaces[1], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[2], + name='eth0.1', + parent=physical_interfaces[2], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[3], + name='eth0.1', + parent=physical_interfaces[3], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + + # Hub and spoke VCs + Interface( + device=devices[0], + name='eth0.9', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[1], + name='eth0.9', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[2], + name='eth0.9', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + Interface( + device=devices[3], + name='eth0.9', + parent=physical_interfaces[0], + type=InterfaceTypeChoices.TYPE_VIRTUAL + ), + ) + Interface.objects.bulk_create(virtual_interfaces) + + provider = Provider.objects.create(name='Provider 1', slug='provider-1') + provider_network = ProviderNetwork.objects.create(provider=provider, name='Provider Network 1') + provider_account = ProviderAccount.objects.create(provider=provider, account='Provider Account 1') + virtual_circuit_type = VirtualCircuitType.objects.create( + name='Virtual Circuit Type 1', + slug='virtual-circuit-type-1' + ) + + virtual_circuits = ( + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + cid='Virtual Circuit 1', + type=virtual_circuit_type + ), + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + cid='Virtual Circuit 2', + type=virtual_circuit_type + ), + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + cid='Virtual Circuit 3', + type=virtual_circuit_type + ), + VirtualCircuit( + provider_network=provider_network, + provider_account=provider_account, + cid='Virtual Circuit 4', + type=virtual_circuit_type + ), + ) + VirtualCircuit.objects.bulk_create(virtual_circuits) + + virtual_circuit_terminations = ( + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[0], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[0] + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[0], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[3] + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[1], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[1] + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[1], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[4] + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[2], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[2] + ), + VirtualCircuitTermination( + virtual_circuit=virtual_circuits[2], + role=VirtualCircuitTerminationRoleChoices.ROLE_PEER, + interface=virtual_interfaces[5] + ), + ) + VirtualCircuitTermination.objects.bulk_create(virtual_circuit_terminations) + + cls.form_data = { + 'virtual_circuit': virtual_circuits[3].pk, + 'role': VirtualCircuitTerminationRoleChoices.ROLE_HUB, + 'interface': virtual_interfaces[6].pk + } + + cls.csv_data = ( + "virtual_circuit,role,interface,description", + f"Virtual Circuit 4,{VirtualCircuitTerminationRoleChoices.ROLE_HUB},{virtual_interfaces[6].pk},Hub", + f"Virtual Circuit 4,{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},{virtual_interfaces[7].pk},Spoke 1", + f"Virtual Circuit 4,{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},{virtual_interfaces[8].pk},Spoke 2", + f"Virtual Circuit 4,{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},{virtual_interfaces[9].pk},Spoke 3", + ) + + cls.csv_update_data = ( + "id,role,description", + f"{virtual_circuit_terminations[0].pk},{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},New description", + f"{virtual_circuit_terminations[1].pk},{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},New description", + f"{virtual_circuit_terminations[2].pk},{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},New description", + ) + + cls.bulk_edit_data = { + 'description': 'New description', + } diff --git a/netbox/circuits/urls.py b/netbox/circuits/urls.py index 2171d49be..90e9e511f 100644 --- a/netbox/circuits/urls.py +++ b/netbox/circuits/urls.py @@ -5,69 +5,71 @@ from . import views app_name = 'circuits' urlpatterns = [ - - # Providers - path('providers/', views.ProviderListView.as_view(), name='provider_list'), - path('providers/add/', views.ProviderEditView.as_view(), name='provider_add'), - path('providers/import/', views.ProviderBulkImportView.as_view(), name='provider_import'), - path('providers/edit/', views.ProviderBulkEditView.as_view(), name='provider_bulk_edit'), - path('providers/delete/', views.ProviderBulkDeleteView.as_view(), name='provider_bulk_delete'), + path('providers/', include(get_model_urls('circuits', 'provider', detail=False))), path('providers//', include(get_model_urls('circuits', 'provider'))), - # Provider accounts - path('provider-accounts/', views.ProviderAccountListView.as_view(), name='provideraccount_list'), - path('provider-accounts/add/', views.ProviderAccountEditView.as_view(), name='provideraccount_add'), - path('provider-accounts/import/', views.ProviderAccountBulkImportView.as_view(), name='provideraccount_import'), - path('provider-accounts/edit/', views.ProviderAccountBulkEditView.as_view(), name='provideraccount_bulk_edit'), - path('provider-accounts/delete/', views.ProviderAccountBulkDeleteView.as_view(), name='provideraccount_bulk_delete'), + path('provider-accounts/', include(get_model_urls('circuits', 'provideraccount', detail=False))), path('provider-accounts//', include(get_model_urls('circuits', 'provideraccount'))), - # Provider networks - path('provider-networks/', views.ProviderNetworkListView.as_view(), name='providernetwork_list'), - path('provider-networks/add/', views.ProviderNetworkEditView.as_view(), name='providernetwork_add'), - path('provider-networks/import/', views.ProviderNetworkBulkImportView.as_view(), name='providernetwork_import'), - path('provider-networks/edit/', views.ProviderNetworkBulkEditView.as_view(), name='providernetwork_bulk_edit'), - path('provider-networks/delete/', views.ProviderNetworkBulkDeleteView.as_view(), name='providernetwork_bulk_delete'), + path('provider-networks/', include(get_model_urls('circuits', 'providernetwork', detail=False))), path('provider-networks//', include(get_model_urls('circuits', 'providernetwork'))), - # Circuit types - path('circuit-types/', views.CircuitTypeListView.as_view(), name='circuittype_list'), - path('circuit-types/add/', views.CircuitTypeEditView.as_view(), name='circuittype_add'), - path('circuit-types/import/', views.CircuitTypeBulkImportView.as_view(), name='circuittype_import'), - path('circuit-types/edit/', views.CircuitTypeBulkEditView.as_view(), name='circuittype_bulk_edit'), - path('circuit-types/delete/', views.CircuitTypeBulkDeleteView.as_view(), name='circuittype_bulk_delete'), + path('circuit-types/', include(get_model_urls('circuits', 'circuittype', detail=False))), path('circuit-types//', include(get_model_urls('circuits', 'circuittype'))), - # Circuits - path('circuits/', views.CircuitListView.as_view(), name='circuit_list'), - path('circuits/add/', views.CircuitEditView.as_view(), name='circuit_add'), - path('circuits/import/', views.CircuitBulkImportView.as_view(), name='circuit_import'), - path('circuits/edit/', views.CircuitBulkEditView.as_view(), name='circuit_bulk_edit'), - path('circuits/delete/', views.CircuitBulkDeleteView.as_view(), name='circuit_bulk_delete'), - path('circuits//terminations/swap/', views.CircuitSwapTerminations.as_view(), name='circuit_terminations_swap'), + path('circuits/', include(get_model_urls('circuits', 'circuit', detail=False))), + path( + 'circuits//terminations/swap/', + views.CircuitSwapTerminations.as_view(), + name='circuit_terminations_swap' + ), path('circuits//', include(get_model_urls('circuits', 'circuit'))), - # Circuit terminations - path('circuit-terminations/', views.CircuitTerminationListView.as_view(), name='circuittermination_list'), - path('circuit-terminations/add/', views.CircuitTerminationEditView.as_view(), name='circuittermination_add'), - path('circuit-terminations/import/', views.CircuitTerminationBulkImportView.as_view(), name='circuittermination_import'), - path('circuit-terminations/edit/', views.CircuitTerminationBulkEditView.as_view(), name='circuittermination_bulk_edit'), - path('circuit-terminations/delete/', views.CircuitTerminationBulkDeleteView.as_view(), name='circuittermination_bulk_delete'), + path('circuit-terminations/', include(get_model_urls('circuits', 'circuittermination', detail=False))), path('circuit-terminations//', include(get_model_urls('circuits', 'circuittermination'))), - # Circuit Groups - path('circuit-groups/', views.CircuitGroupListView.as_view(), name='circuitgroup_list'), - path('circuit-groups/add/', views.CircuitGroupEditView.as_view(), name='circuitgroup_add'), - path('circuit-groups/import/', views.CircuitGroupBulkImportView.as_view(), name='circuitgroup_import'), - path('circuit-groups/edit/', views.CircuitGroupBulkEditView.as_view(), name='circuitgroup_bulk_edit'), - path('circuit-groups/delete/', views.CircuitGroupBulkDeleteView.as_view(), name='circuitgroup_bulk_delete'), + path('circuit-groups/', include(get_model_urls('circuits', 'circuitgroup', detail=False))), path('circuit-groups//', include(get_model_urls('circuits', 'circuitgroup'))), - # Circuit Group Assignments - path('circuit-group-assignments/', views.CircuitGroupAssignmentListView.as_view(), name='circuitgroupassignment_list'), - path('circuit-group-assignments/add/', views.CircuitGroupAssignmentEditView.as_view(), name='circuitgroupassignment_add'), - path('circuit-group-assignments/import/', views.CircuitGroupAssignmentBulkImportView.as_view(), name='circuitgroupassignment_import'), - path('circuit-group-assignments/edit/', views.CircuitGroupAssignmentBulkEditView.as_view(), name='circuitgroupassignment_bulk_edit'), - path('circuit-group-assignments/delete/', views.CircuitGroupAssignmentBulkDeleteView.as_view(), name='circuitgroupassignment_bulk_delete'), + path('circuit-group-assignments/', include(get_model_urls('circuits', 'circuitgroupassignment', detail=False))), path('circuit-group-assignments//', include(get_model_urls('circuits', 'circuitgroupassignment'))), + + # Virtual circuits + path('virtual-circuits/', views.VirtualCircuitListView.as_view(), name='virtualcircuit_list'), + path('virtual-circuits/add/', views.VirtualCircuitEditView.as_view(), name='virtualcircuit_add'), + path('virtual-circuits/import/', views.VirtualCircuitBulkImportView.as_view(), name='virtualcircuit_bulk_import'), + path('virtual-circuits/edit/', views.VirtualCircuitBulkEditView.as_view(), name='virtualcircuit_bulk_edit'), + path('virtual-circuits/delete/', views.VirtualCircuitBulkDeleteView.as_view(), name='virtualcircuit_bulk_delete'), + path('virtual-circuits//', include(get_model_urls('circuits', 'virtualcircuit'))), + + path('virtual-circuit-types/', include(get_model_urls('circuits', 'virtualcircuittype', detail=False))), + path('virtual-circuit-types//', include(get_model_urls('circuits', 'virtualcircuittype'))), + + # Virtual circuit terminations + path( + 'virtual-circuit-terminations/', + views.VirtualCircuitTerminationListView.as_view(), + name='virtualcircuittermination_list', + ), + path( + 'virtual-circuit-terminations/add/', + views.VirtualCircuitTerminationEditView.as_view(), + name='virtualcircuittermination_add', + ), + path( + 'virtual-circuit-terminations/import/', + views.VirtualCircuitTerminationBulkImportView.as_view(), + name='virtualcircuittermination_bulk_import', + ), + path( + 'virtual-circuit-terminations/edit/', + views.VirtualCircuitTerminationBulkEditView.as_view(), + name='virtualcircuittermination_bulk_edit', + ), + path( + 'virtual-circuit-terminations/delete/', + views.VirtualCircuitTerminationBulkDeleteView.as_view(), + name='virtualcircuittermination_bulk_delete', + ), + path('virtual-circuit-terminations//', include(get_model_urls('circuits', 'virtualcircuittermination'))), ] diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py index 8218960c9..3bd81c33a 100644 --- a/netbox/circuits/views.py +++ b/netbox/circuits/views.py @@ -17,6 +17,7 @@ from .models import * # Providers # +@register_model_view(Provider, 'list', path='', detail=False) class ProviderListView(generic.ObjectListView): queryset = Provider.objects.annotate( count_circuits=count_related(Circuit, 'provider') @@ -36,6 +37,7 @@ class ProviderView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(Provider, 'add', detail=False) @register_model_view(Provider, 'edit') class ProviderEditView(generic.ObjectEditView): queryset = Provider.objects.all() @@ -47,11 +49,13 @@ class ProviderDeleteView(generic.ObjectDeleteView): queryset = Provider.objects.all() +@register_model_view(Provider, 'bulk_import', detail=False) class ProviderBulkImportView(generic.BulkImportView): queryset = Provider.objects.all() model_form = forms.ProviderImportForm +@register_model_view(Provider, 'bulk_edit', path='edit', detail=False) class ProviderBulkEditView(generic.BulkEditView): queryset = Provider.objects.annotate( count_circuits=count_related(Circuit, 'provider') @@ -61,6 +65,7 @@ class ProviderBulkEditView(generic.BulkEditView): form = forms.ProviderBulkEditForm +@register_model_view(Provider, 'bulk_delete', path='delete', detail=False) class ProviderBulkDeleteView(generic.BulkDeleteView): queryset = Provider.objects.annotate( count_circuits=count_related(Circuit, 'provider') @@ -78,6 +83,7 @@ class ProviderContactsView(ObjectContactsView): # ProviderAccounts # +@register_model_view(ProviderAccount, 'list', path='', detail=False) class ProviderAccountListView(generic.ObjectListView): queryset = ProviderAccount.objects.annotate( count_circuits=count_related(Circuit, 'provider_account') @@ -97,6 +103,7 @@ class ProviderAccountView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(ProviderAccount, 'add', detail=False) @register_model_view(ProviderAccount, 'edit') class ProviderAccountEditView(generic.ObjectEditView): queryset = ProviderAccount.objects.all() @@ -108,12 +115,14 @@ class ProviderAccountDeleteView(generic.ObjectDeleteView): queryset = ProviderAccount.objects.all() +@register_model_view(ProviderAccount, 'bulk_import', detail=False) class ProviderAccountBulkImportView(generic.BulkImportView): queryset = ProviderAccount.objects.all() model_form = forms.ProviderAccountImportForm table = tables.ProviderAccountTable +@register_model_view(ProviderAccount, 'bulk_edit', path='edit', detail=False) class ProviderAccountBulkEditView(generic.BulkEditView): queryset = ProviderAccount.objects.annotate( count_circuits=count_related(Circuit, 'provider_account') @@ -123,6 +132,7 @@ class ProviderAccountBulkEditView(generic.BulkEditView): form = forms.ProviderAccountBulkEditForm +@register_model_view(ProviderAccount, 'bulk_delete', path='delete', detail=False) class ProviderAccountBulkDeleteView(generic.BulkDeleteView): queryset = ProviderAccount.objects.annotate( count_circuits=count_related(Circuit, 'provider_account') @@ -140,6 +150,7 @@ class ProviderAccountContactsView(ObjectContactsView): # Provider networks # +@register_model_view(ProviderNetwork, 'list', path='', detail=False) class ProviderNetworkListView(generic.ObjectListView): queryset = ProviderNetwork.objects.all() filterset = filtersets.ProviderNetworkFilterSet @@ -158,7 +169,7 @@ class ProviderNetworkView(GetRelatedModelsMixin, generic.ObjectView): instance, extra=( ( - Circuit.objects.restrict(request.user, 'view').filter(terminations__provider_network=instance), + Circuit.objects.restrict(request.user, 'view').filter(terminations___provider_network=instance), 'provider_network_id', ), ), @@ -166,6 +177,7 @@ class ProviderNetworkView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(ProviderNetwork, 'add', detail=False) @register_model_view(ProviderNetwork, 'edit') class ProviderNetworkEditView(generic.ObjectEditView): queryset = ProviderNetwork.objects.all() @@ -177,11 +189,13 @@ class ProviderNetworkDeleteView(generic.ObjectDeleteView): queryset = ProviderNetwork.objects.all() +@register_model_view(ProviderNetwork, 'bulk_import', detail=False) class ProviderNetworkBulkImportView(generic.BulkImportView): queryset = ProviderNetwork.objects.all() model_form = forms.ProviderNetworkImportForm +@register_model_view(ProviderNetwork, 'bulk_edit', path='edit', detail=False) class ProviderNetworkBulkEditView(generic.BulkEditView): queryset = ProviderNetwork.objects.all() filterset = filtersets.ProviderNetworkFilterSet @@ -189,6 +203,7 @@ class ProviderNetworkBulkEditView(generic.BulkEditView): form = forms.ProviderNetworkBulkEditForm +@register_model_view(ProviderNetwork, 'bulk_delete', path='delete', detail=False) class ProviderNetworkBulkDeleteView(generic.BulkDeleteView): queryset = ProviderNetwork.objects.all() filterset = filtersets.ProviderNetworkFilterSet @@ -199,6 +214,7 @@ class ProviderNetworkBulkDeleteView(generic.BulkDeleteView): # Circuit Types # +@register_model_view(CircuitType, 'list', path='', detail=False) class CircuitTypeListView(generic.ObjectListView): queryset = CircuitType.objects.annotate( circuit_count=count_related(Circuit, 'type') @@ -218,6 +234,7 @@ class CircuitTypeView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(CircuitType, 'add', detail=False) @register_model_view(CircuitType, 'edit') class CircuitTypeEditView(generic.ObjectEditView): queryset = CircuitType.objects.all() @@ -229,11 +246,13 @@ class CircuitTypeDeleteView(generic.ObjectDeleteView): queryset = CircuitType.objects.all() +@register_model_view(CircuitType, 'bulk_import', detail=False) class CircuitTypeBulkImportView(generic.BulkImportView): queryset = CircuitType.objects.all() model_form = forms.CircuitTypeImportForm +@register_model_view(CircuitType, 'bulk_edit', path='edit', detail=False) class CircuitTypeBulkEditView(generic.BulkEditView): queryset = CircuitType.objects.annotate( circuit_count=count_related(Circuit, 'type') @@ -243,6 +262,7 @@ class CircuitTypeBulkEditView(generic.BulkEditView): form = forms.CircuitTypeBulkEditForm +@register_model_view(CircuitType, 'bulk_delete', path='delete', detail=False) class CircuitTypeBulkDeleteView(generic.BulkDeleteView): queryset = CircuitType.objects.annotate( circuit_count=count_related(Circuit, 'type') @@ -255,10 +275,10 @@ class CircuitTypeBulkDeleteView(generic.BulkDeleteView): # Circuits # +@register_model_view(Circuit, 'list', path='', detail=False) class CircuitListView(generic.ObjectListView): queryset = Circuit.objects.prefetch_related( - 'tenant__group', 'termination_a__site', 'termination_z__site', - 'termination_a__provider_network', 'termination_z__provider_network', + 'tenant__group', 'termination_a__termination', 'termination_z__termination', ) filterset = filtersets.CircuitFilterSet filterset_form = forms.CircuitFilterForm @@ -270,6 +290,7 @@ class CircuitView(generic.ObjectView): queryset = Circuit.objects.all() +@register_model_view(Circuit, 'add', detail=False) @register_model_view(Circuit, 'edit') class CircuitEditView(generic.ObjectEditView): queryset = Circuit.objects.all() @@ -281,6 +302,7 @@ class CircuitDeleteView(generic.ObjectDeleteView): queryset = Circuit.objects.all() +@register_model_view(Circuit, 'bulk_import', detail=False) class CircuitBulkImportView(generic.BulkImportView): queryset = Circuit.objects.all() model_form = forms.CircuitImportForm @@ -296,20 +318,20 @@ class CircuitBulkImportView(generic.BulkImportView): return data +@register_model_view(Circuit, 'bulk_edit', path='edit', detail=False) class CircuitBulkEditView(generic.BulkEditView): queryset = Circuit.objects.prefetch_related( - 'termination_a__site', 'termination_z__site', - 'termination_a__provider_network', 'termination_z__provider_network', + 'tenant__group', 'termination_a__termination', 'termination_z__termination', ) filterset = filtersets.CircuitFilterSet table = tables.CircuitTable form = forms.CircuitBulkEditForm +@register_model_view(Circuit, 'bulk_delete', path='delete', detail=False) class CircuitBulkDeleteView(generic.BulkDeleteView): queryset = Circuit.objects.prefetch_related( - 'termination_a__site', 'termination_z__site', - 'termination_a__provider_network', 'termination_z__provider_network', + 'tenant__group', 'termination_a__termination', 'termination_z__termination', ) filterset = filtersets.CircuitFilterSet table = tables.CircuitTable @@ -400,6 +422,7 @@ class CircuitContactsView(ObjectContactsView): # Circuit terminations # +@register_model_view(CircuitTermination, 'list', path='', detail=False) class CircuitTerminationListView(generic.ObjectListView): queryset = CircuitTermination.objects.all() filterset = filtersets.CircuitTerminationFilterSet @@ -412,6 +435,7 @@ class CircuitTerminationView(generic.ObjectView): queryset = CircuitTermination.objects.all() +@register_model_view(CircuitTermination, 'add', detail=False) @register_model_view(CircuitTermination, 'edit') class CircuitTerminationEditView(generic.ObjectEditView): queryset = CircuitTermination.objects.all() @@ -423,11 +447,13 @@ class CircuitTerminationDeleteView(generic.ObjectDeleteView): queryset = CircuitTermination.objects.all() +@register_model_view(CircuitTermination, 'bulk_import', detail=False) class CircuitTerminationBulkImportView(generic.BulkImportView): queryset = CircuitTermination.objects.all() model_form = forms.CircuitTerminationImportForm +@register_model_view(CircuitTermination, 'bulk_edit', path='edit', detail=False) class CircuitTerminationBulkEditView(generic.BulkEditView): queryset = CircuitTermination.objects.all() filterset = filtersets.CircuitTerminationFilterSet @@ -435,6 +461,7 @@ class CircuitTerminationBulkEditView(generic.BulkEditView): form = forms.CircuitTerminationBulkEditForm +@register_model_view(CircuitTermination, 'bulk_delete', path='delete', detail=False) class CircuitTerminationBulkDeleteView(generic.BulkDeleteView): queryset = CircuitTermination.objects.all() filterset = filtersets.CircuitTerminationFilterSet @@ -449,6 +476,7 @@ register_model_view(CircuitTermination, 'trace', kwargs={'model': CircuitTermina # Circuit Groups # +@register_model_view(CircuitGroup, 'list', path='', detail=False) class CircuitGroupListView(generic.ObjectListView): queryset = CircuitGroup.objects.annotate( circuit_group_assignment_count=count_related(CircuitGroupAssignment, 'group') @@ -468,6 +496,7 @@ class CircuitGroupView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(CircuitGroup, 'add', detail=False) @register_model_view(CircuitGroup, 'edit') class CircuitGroupEditView(generic.ObjectEditView): queryset = CircuitGroup.objects.all() @@ -479,11 +508,13 @@ class CircuitGroupDeleteView(generic.ObjectDeleteView): queryset = CircuitGroup.objects.all() +@register_model_view(CircuitGroup, 'bulk_import', detail=False) class CircuitGroupBulkImportView(generic.BulkImportView): queryset = CircuitGroup.objects.all() model_form = forms.CircuitGroupImportForm +@register_model_view(CircuitGroup, 'bulk_edit', path='edit', detail=False) class CircuitGroupBulkEditView(generic.BulkEditView): queryset = CircuitGroup.objects.all() filterset = filtersets.CircuitGroupFilterSet @@ -491,6 +522,7 @@ class CircuitGroupBulkEditView(generic.BulkEditView): form = forms.CircuitGroupBulkEditForm +@register_model_view(CircuitGroup, 'bulk_delete', path='delete', detail=False) class CircuitGroupBulkDeleteView(generic.BulkDeleteView): queryset = CircuitGroup.objects.all() filterset = filtersets.CircuitGroupFilterSet @@ -501,6 +533,7 @@ class CircuitGroupBulkDeleteView(generic.BulkDeleteView): # Circuit Groups # +@register_model_view(CircuitGroupAssignment, 'list', path='', detail=False) class CircuitGroupAssignmentListView(generic.ObjectListView): queryset = CircuitGroupAssignment.objects.all() filterset = filtersets.CircuitGroupAssignmentFilterSet @@ -513,6 +546,7 @@ class CircuitGroupAssignmentView(generic.ObjectView): queryset = CircuitGroupAssignment.objects.all() +@register_model_view(CircuitGroupAssignment, 'add', detail=False) @register_model_view(CircuitGroupAssignment, 'edit') class CircuitGroupAssignmentEditView(generic.ObjectEditView): queryset = CircuitGroupAssignment.objects.all() @@ -524,11 +558,13 @@ class CircuitGroupAssignmentDeleteView(generic.ObjectDeleteView): queryset = CircuitGroupAssignment.objects.all() +@register_model_view(CircuitGroupAssignment, 'bulk_import', detail=False) class CircuitGroupAssignmentBulkImportView(generic.BulkImportView): queryset = CircuitGroupAssignment.objects.all() model_form = forms.CircuitGroupAssignmentImportForm +@register_model_view(CircuitGroupAssignment, 'bulk_edit', path='edit', detail=False) class CircuitGroupAssignmentBulkEditView(generic.BulkEditView): queryset = CircuitGroupAssignment.objects.all() filterset = filtersets.CircuitGroupAssignmentFilterSet @@ -536,7 +572,175 @@ class CircuitGroupAssignmentBulkEditView(generic.BulkEditView): form = forms.CircuitGroupAssignmentBulkEditForm +@register_model_view(CircuitGroupAssignment, 'bulk_delete', path='delete', detail=False) class CircuitGroupAssignmentBulkDeleteView(generic.BulkDeleteView): queryset = CircuitGroupAssignment.objects.all() filterset = filtersets.CircuitGroupAssignmentFilterSet table = tables.CircuitGroupAssignmentTable + + +# +# Virtual circuit Types +# + +@register_model_view(VirtualCircuitType, 'list', path='', detail=False) +class VirtualCircuitTypeListView(generic.ObjectListView): + queryset = VirtualCircuitType.objects.annotate( + virtual_circuit_count=count_related(VirtualCircuit, 'type') + ) + filterset = filtersets.VirtualCircuitTypeFilterSet + filterset_form = forms.VirtualCircuitTypeFilterForm + table = tables.VirtualCircuitTypeTable + + +@register_model_view(VirtualCircuitType) +class VirtualCircuitTypeView(GetRelatedModelsMixin, generic.ObjectView): + queryset = VirtualCircuitType.objects.all() + + def get_extra_context(self, request, instance): + return { + 'related_models': self.get_related_models(request, instance), + } + + +@register_model_view(VirtualCircuitType, 'add', detail=False) +@register_model_view(VirtualCircuitType, 'edit') +class VirtualCircuitTypeEditView(generic.ObjectEditView): + queryset = VirtualCircuitType.objects.all() + form = forms.VirtualCircuitTypeForm + + +@register_model_view(VirtualCircuitType, 'delete') +class VirtualCircuitTypeDeleteView(generic.ObjectDeleteView): + queryset = VirtualCircuitType.objects.all() + + +@register_model_view(VirtualCircuitType, 'bulk_import', detail=False) +class VirtualCircuitTypeBulkImportView(generic.BulkImportView): + queryset = VirtualCircuitType.objects.all() + model_form = forms.VirtualCircuitTypeImportForm + + +@register_model_view(VirtualCircuitType, 'bulk_edit', path='edit', detail=False) +class VirtualCircuitTypeBulkEditView(generic.BulkEditView): + queryset = VirtualCircuitType.objects.annotate( + circuit_count=count_related(Circuit, 'type') + ) + filterset = filtersets.VirtualCircuitTypeFilterSet + table = tables.VirtualCircuitTypeTable + form = forms.VirtualCircuitTypeBulkEditForm + + +@register_model_view(VirtualCircuitType, 'bulk_delete', path='delete', detail=False) +class VirtualCircuitTypeBulkDeleteView(generic.BulkDeleteView): + queryset = VirtualCircuitType.objects.annotate( + circuit_count=count_related(Circuit, 'type') + ) + filterset = filtersets.VirtualCircuitTypeFilterSet + table = tables.VirtualCircuitTypeTable + + +# +# Virtual circuits +# + +class VirtualCircuitListView(generic.ObjectListView): + queryset = VirtualCircuit.objects.annotate( + termination_count=count_related(VirtualCircuitTermination, 'virtual_circuit') + ) + filterset = filtersets.VirtualCircuitFilterSet + filterset_form = forms.VirtualCircuitFilterForm + table = tables.VirtualCircuitTable + + +@register_model_view(VirtualCircuit) +class VirtualCircuitView(generic.ObjectView): + queryset = VirtualCircuit.objects.all() + + +@register_model_view(VirtualCircuit, 'edit') +class VirtualCircuitEditView(generic.ObjectEditView): + queryset = VirtualCircuit.objects.all() + form = forms.VirtualCircuitForm + + +@register_model_view(VirtualCircuit, 'delete') +class VirtualCircuitDeleteView(generic.ObjectDeleteView): + queryset = VirtualCircuit.objects.all() + + +class VirtualCircuitBulkImportView(generic.BulkImportView): + queryset = VirtualCircuit.objects.all() + model_form = forms.VirtualCircuitImportForm + additional_permissions = [ + 'circuits.add_virtualcircuittermination', + ] + related_object_forms = { + 'terminations': forms.VirtualCircuitTerminationImportRelatedForm, + } + + def prep_related_object_data(self, parent, data): + data.update({'virtual_circuit': parent}) + return data + + +class VirtualCircuitBulkEditView(generic.BulkEditView): + queryset = VirtualCircuit.objects.annotate( + termination_count=count_related(VirtualCircuitTermination, 'virtual_circuit') + ) + filterset = filtersets.VirtualCircuitFilterSet + table = tables.VirtualCircuitTable + form = forms.VirtualCircuitBulkEditForm + + +class VirtualCircuitBulkDeleteView(generic.BulkDeleteView): + queryset = VirtualCircuit.objects.annotate( + termination_count=count_related(VirtualCircuitTermination, 'virtual_circuit') + ) + filterset = filtersets.VirtualCircuitFilterSet + table = tables.VirtualCircuitTable + + +# +# Virtual circuit terminations +# + +class VirtualCircuitTerminationListView(generic.ObjectListView): + queryset = VirtualCircuitTermination.objects.all() + filterset = filtersets.VirtualCircuitTerminationFilterSet + filterset_form = forms.VirtualCircuitTerminationFilterForm + table = tables.VirtualCircuitTerminationTable + + +@register_model_view(VirtualCircuitTermination) +class VirtualCircuitTerminationView(generic.ObjectView): + queryset = VirtualCircuitTermination.objects.all() + + +@register_model_view(VirtualCircuitTermination, 'edit') +class VirtualCircuitTerminationEditView(generic.ObjectEditView): + queryset = VirtualCircuitTermination.objects.all() + form = forms.VirtualCircuitTerminationForm + + +@register_model_view(VirtualCircuitTermination, 'delete') +class VirtualCircuitTerminationDeleteView(generic.ObjectDeleteView): + queryset = VirtualCircuitTermination.objects.all() + + +class VirtualCircuitTerminationBulkImportView(generic.BulkImportView): + queryset = VirtualCircuitTermination.objects.all() + model_form = forms.VirtualCircuitTerminationImportForm + + +class VirtualCircuitTerminationBulkEditView(generic.BulkEditView): + queryset = VirtualCircuitTermination.objects.all() + filterset = filtersets.VirtualCircuitTerminationFilterSet + table = tables.VirtualCircuitTerminationTable + form = forms.VirtualCircuitTerminationBulkEditForm + + +class VirtualCircuitTerminationBulkDeleteView(generic.BulkDeleteView): + queryset = VirtualCircuitTermination.objects.all() + filterset = filtersets.VirtualCircuitTerminationFilterSet + table = tables.VirtualCircuitTerminationTable diff --git a/netbox/core/api/nested_serializers.py b/netbox/core/api/nested_serializers.py deleted file mode 100644 index df7b41ca7..000000000 --- a/netbox/core/api/nested_serializers.py +++ /dev/null @@ -1,47 +0,0 @@ -import warnings - -from rest_framework import serializers - -from core.choices import JobStatusChoices -from core.models import * -from netbox.api.fields import ChoiceField -from netbox.api.serializers import WritableNestedSerializer -from users.api.serializers import UserSerializer - -__all__ = ( - 'NestedDataFileSerializer', - 'NestedDataSourceSerializer', - 'NestedJobSerializer', -) - -# TODO: Remove in v4.2 -warnings.warn( - "Dedicated nested serializers will be removed in NetBox v4.2. Use Serializer(nested=True) instead.", - DeprecationWarning -) - - -class NestedDataSourceSerializer(WritableNestedSerializer): - - class Meta: - model = DataSource - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedDataFileSerializer(WritableNestedSerializer): - - class Meta: - model = DataFile - fields = ['id', 'url', 'display_url', 'display', 'path'] - - -class NestedJobSerializer(serializers.ModelSerializer): - status = ChoiceField(choices=JobStatusChoices) - user = UserSerializer( - nested=True, - read_only=True - ) - - class Meta: - model = Job - fields = ['url', 'display_url', 'created', 'completed', 'user', 'status'] diff --git a/netbox/core/api/schema.py b/netbox/core/api/schema.py index 1ac822b8c..663ee2899 100644 --- a/netbox/core/api/schema.py +++ b/netbox/core/api/schema.py @@ -35,7 +35,10 @@ class ChoiceFieldFix(OpenApiSerializerFieldExtension): elif direction == "response": value = build_cf - label = {**build_basic_type(OpenApiTypes.STR), "enum": list(OrderedDict.fromkeys(self.target.choices.values()))} + label = { + **build_basic_type(OpenApiTypes.STR), + "enum": list(OrderedDict.fromkeys(self.target.choices.values())) + } return build_object_type( properties={ @@ -155,6 +158,9 @@ class NetBoxAutoSchema(AutoSchema): fields = {} if hasattr(serializer, 'child') else serializer.fields remove_fields = [] + # If you get a failure here for "AttributeError: 'cached_property' object has no attribute 'items'" + # it is probably because you are using a viewsets.ViewSet for the API View and are defining a + # serializer_class. You will also need to define a get_serializer() method like for GenericAPIView. for child_name, child in fields.items(): # read_only fields don't need to be in writable (write only) serializers if 'read_only' in dir(child) and child.read_only: diff --git a/netbox/core/api/serializers.py b/netbox/core/api/serializers.py index 2dde6be9f..9a6d4d726 100644 --- a/netbox/core/api/serializers.py +++ b/netbox/core/api/serializers.py @@ -1,3 +1,4 @@ from .serializers_.change_logging import * from .serializers_.data import * from .serializers_.jobs import * +from .serializers_.tasks import * diff --git a/netbox/core/api/serializers_/jobs.py b/netbox/core/api/serializers_/jobs.py index 544dddb56..306287e88 100644 --- a/netbox/core/api/serializers_/jobs.py +++ b/netbox/core/api/serializers_/jobs.py @@ -22,7 +22,7 @@ class JobSerializer(BaseModelSerializer): class Meta: model = Job fields = [ - 'id', 'url', 'display_url', 'display', 'object_type', 'object_id', 'name', 'status', 'created', 'scheduled', 'interval', - 'started', 'completed', 'user', 'data', 'error', 'job_id', + 'id', 'url', 'display_url', 'display', 'object_type', 'object_id', 'name', 'status', 'created', 'scheduled', + 'interval', 'started', 'completed', 'user', 'data', 'error', 'job_id', ] brief_fields = ('url', 'created', 'completed', 'user', 'status') diff --git a/netbox/core/api/serializers_/tasks.py b/netbox/core/api/serializers_/tasks.py new file mode 100644 index 000000000..53f2b5126 --- /dev/null +++ b/netbox/core/api/serializers_/tasks.py @@ -0,0 +1,87 @@ +from rest_framework import serializers +from rest_framework.reverse import reverse + +__all__ = ( + 'BackgroundTaskSerializer', + 'BackgroundQueueSerializer', + 'BackgroundWorkerSerializer', +) + + +class BackgroundTaskSerializer(serializers.Serializer): + id = serializers.CharField() + url = serializers.HyperlinkedIdentityField( + view_name='core-api:rqtask-detail', + lookup_field='id', + lookup_url_kwarg='pk' + ) + description = serializers.CharField() + origin = serializers.CharField() + func_name = serializers.CharField() + args = serializers.ListField(child=serializers.CharField()) + kwargs = serializers.DictField() + result = serializers.CharField() + timeout = serializers.IntegerField() + result_ttl = serializers.IntegerField() + created_at = serializers.DateTimeField() + enqueued_at = serializers.DateTimeField() + started_at = serializers.DateTimeField() + ended_at = serializers.DateTimeField() + worker_name = serializers.CharField() + position = serializers.SerializerMethodField() + status = serializers.SerializerMethodField() + meta = serializers.DictField() + last_heartbeat = serializers.CharField() + + is_finished = serializers.BooleanField() + is_queued = serializers.BooleanField() + is_failed = serializers.BooleanField() + is_started = serializers.BooleanField() + is_deferred = serializers.BooleanField() + is_canceled = serializers.BooleanField() + is_scheduled = serializers.BooleanField() + is_stopped = serializers.BooleanField() + + def get_position(self, obj) -> int: + return obj.get_position() + + def get_status(self, obj) -> str: + return obj.get_status() + + +class BackgroundQueueSerializer(serializers.Serializer): + name = serializers.CharField() + url = serializers.SerializerMethodField() + jobs = serializers.IntegerField() + oldest_job_timestamp = serializers.CharField() + index = serializers.IntegerField() + scheduler_pid = serializers.CharField() + workers = serializers.IntegerField() + finished_jobs = serializers.IntegerField() + started_jobs = serializers.IntegerField() + deferred_jobs = serializers.IntegerField() + failed_jobs = serializers.IntegerField() + scheduled_jobs = serializers.IntegerField() + + def get_url(self, obj): + return reverse('core-api:rqqueue-detail', args=[obj['name']], request=self.context.get("request")) + + +class BackgroundWorkerSerializer(serializers.Serializer): + name = serializers.CharField() + url = serializers.HyperlinkedIdentityField( + view_name='core-api:rqworker-detail', + lookup_field='name' + ) + state = serializers.SerializerMethodField() + birth_date = serializers.DateTimeField() + queue_names = serializers.ListField( + child=serializers.CharField() + ) + pid = serializers.CharField() + successful_job_count = serializers.IntegerField() + failed_job_count = serializers.IntegerField() + total_working_time = serializers.IntegerField() + + def get_state(self, obj): + return obj.get_state() diff --git a/netbox/core/api/urls.py b/netbox/core/api/urls.py index 95ee1896e..3c22f1cf4 100644 --- a/netbox/core/api/urls.py +++ b/netbox/core/api/urls.py @@ -1,6 +1,7 @@ from netbox.api.routers import NetBoxRouter from . import views +app_name = 'core-api' router = NetBoxRouter() router.APIRootView = views.CoreRootView @@ -9,6 +10,8 @@ router.register('data-sources', views.DataSourceViewSet) router.register('data-files', views.DataFileViewSet) router.register('jobs', views.JobViewSet) router.register('object-changes', views.ObjectChangeViewSet) +router.register('background-queues', views.BackgroundQueueViewSet, basename='rqqueue') +router.register('background-workers', views.BackgroundWorkerViewSet, basename='rqworker') +router.register('background-tasks', views.BackgroundTaskViewSet, basename='rqtask') -app_name = 'core-api' urlpatterns = router.urls diff --git a/netbox/core/api/views.py b/netbox/core/api/views.py index b3a024c02..4e5b148fc 100644 --- a/netbox/core/api/views.py +++ b/netbox/core/api/views.py @@ -1,5 +1,8 @@ +from django.http import Http404, HttpResponse from django.shortcuts import get_object_or_404 from django.utils.translation import gettext_lazy as _ +from drf_spectacular.types import OpenApiTypes +from drf_spectacular.utils import extend_schema from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied from rest_framework.response import Response @@ -10,8 +13,17 @@ from core import filtersets from core.choices import DataSourceStatusChoices from core.jobs import SyncDataSourceJob from core.models import * +from core.utils import delete_rq_job, enqueue_rq_job, get_rq_jobs, requeue_rq_job, stop_rq_job +from django_rq.queues import get_redis_connection +from django_rq.utils import get_statistics +from django_rq.settings import QUEUES_LIST from netbox.api.metadata import ContentTypeMetadata +from netbox.api.pagination import LimitOffsetListPagination from netbox.api.viewsets import NetBoxModelViewSet, NetBoxReadOnlyModelViewSet +from rest_framework import viewsets +from rest_framework.permissions import IsAdminUser +from rq.job import Job as RQ_Job +from rq.worker import Worker from . import serializers @@ -71,3 +83,152 @@ class ObjectChangeViewSet(ReadOnlyModelViewSet): queryset = ObjectChange.objects.valid_models() serializer_class = serializers.ObjectChangeSerializer filterset_class = filtersets.ObjectChangeFilterSet + + +class BaseRQViewSet(viewsets.ViewSet): + """ + Base class for RQ view sets. Provides a list() method. Subclasses must implement get_data(). + """ + permission_classes = [IsAdminUser] + serializer_class = None + + def get_data(self): + raise NotImplementedError() + + @extend_schema(responses={200: OpenApiTypes.OBJECT}) + def list(self, request): + data = self.get_data() + paginator = LimitOffsetListPagination() + data = paginator.paginate_list(data, request) + + serializer = self.serializer_class(data, many=True, context={'request': request}) + return paginator.get_paginated_response(serializer.data) + + def get_serializer(self, *args, **kwargs): + """ + Return the serializer instance that should be used for validating and + deserializing input, and for serializing output. + """ + serializer_class = self.get_serializer_class() + kwargs['context'] = self.get_serializer_context() + return serializer_class(*args, **kwargs) + + +class BackgroundQueueViewSet(BaseRQViewSet): + """ + Retrieve a list of RQ Queues. + Note: Queue names are not URL safe so not returning a detail view. + """ + serializer_class = serializers.BackgroundQueueSerializer + lookup_field = 'name' + lookup_value_regex = r'[\w.@+-]+' + + def get_view_name(self): + return "Background Queues" + + def get_data(self): + return get_statistics(run_maintenance_tasks=True)["queues"] + + @extend_schema(responses={200: OpenApiTypes.OBJECT}) + def retrieve(self, request, name): + data = self.get_data() + if not data: + raise Http404 + + for queue in data: + if queue['name'] == name: + serializer = self.serializer_class(queue, context={'request': request}) + return Response(serializer.data) + + raise Http404 + + +class BackgroundWorkerViewSet(BaseRQViewSet): + """ + Retrieve a list of RQ Workers. + """ + serializer_class = serializers.BackgroundWorkerSerializer + lookup_field = 'name' + + def get_view_name(self): + return "Background Workers" + + def get_data(self): + config = QUEUES_LIST[0] + return Worker.all(get_redis_connection(config['connection_config'])) + + def retrieve(self, request, name): + # all the RQ queues should use the same connection + config = QUEUES_LIST[0] + workers = Worker.all(get_redis_connection(config['connection_config'])) + worker = next((item for item in workers if item.name == name), None) + if not worker: + raise Http404 + + serializer = serializers.BackgroundWorkerSerializer(worker, context={'request': request}) + return Response(serializer.data) + + +class BackgroundTaskViewSet(BaseRQViewSet): + """ + Retrieve a list of RQ Tasks. + """ + serializer_class = serializers.BackgroundTaskSerializer + + def get_view_name(self): + return "Background Tasks" + + def get_data(self): + return get_rq_jobs() + + def get_task_from_id(self, task_id): + config = QUEUES_LIST[0] + task = RQ_Job.fetch(task_id, connection=get_redis_connection(config['connection_config'])) + if not task: + raise Http404 + + return task + + @extend_schema(responses={200: OpenApiTypes.OBJECT}) + def retrieve(self, request, pk): + """ + Retrieve the details of the specified RQ Task. + """ + task = self.get_task_from_id(pk) + serializer = self.serializer_class(task, context={'request': request}) + return Response(serializer.data) + + @action(methods=["POST"], detail=True) + def delete(self, request, pk): + """ + Delete the specified RQ Task. + """ + delete_rq_job(pk) + return HttpResponse(status=200) + + @action(methods=["POST"], detail=True) + def requeue(self, request, pk): + """ + Requeues the specified RQ Task. + """ + requeue_rq_job(pk) + return HttpResponse(status=200) + + @action(methods=["POST"], detail=True) + def enqueue(self, request, pk): + """ + Enqueues the specified RQ Task. + """ + enqueue_rq_job(pk) + return HttpResponse(status=200) + + @action(methods=["POST"], detail=True) + def stop(self, request, pk): + """ + Stops the specified RQ Task. + """ + stopped_jobs = stop_rq_job(pk) + if len(stopped_jobs) == 1: + return HttpResponse(status=200) + else: + return HttpResponse(status=204) diff --git a/netbox/core/apps.py b/netbox/core/apps.py index 1dfc7a65e..9674860b9 100644 --- a/netbox/core/apps.py +++ b/netbox/core/apps.py @@ -1,4 +1,6 @@ from django.apps import AppConfig +from django.conf import settings +from django.core.cache import cache from django.db import models from django.db.migrations.operations import AlterModelOptions @@ -19,6 +21,11 @@ class CoreConfig(AppConfig): from core.api import schema # noqa: F401 from netbox.models.features import register_models from . import data_backends, events, search # noqa: F401 + from netbox import context_managers # noqa: F401 # Register models register_models(*self.get_models()) + + # Clear Redis cache on startup in development mode + if settings.DEBUG: + cache.clear() diff --git a/netbox/core/choices.py b/netbox/core/choices.py index 01a072ce1..442acc26b 100644 --- a/netbox/core/choices.py +++ b/netbox/core/choices.py @@ -72,6 +72,20 @@ class JobStatusChoices(ChoiceSet): ) +class JobIntervalChoices(ChoiceSet): + INTERVAL_MINUTELY = 1 + INTERVAL_HOURLY = 60 + INTERVAL_DAILY = 60 * 24 + INTERVAL_WEEKLY = 60 * 24 * 7 + + CHOICES = ( + (INTERVAL_MINUTELY, _('Minutely')), + (INTERVAL_HOURLY, _('Hourly')), + (INTERVAL_DAILY, _('Daily')), + (INTERVAL_WEEKLY, _('Weekly')), + ) + + # # ObjectChanges # diff --git a/netbox/core/management/commands/rqworker.py b/netbox/core/management/commands/rqworker.py index e1fb6fd11..b2879c3d8 100644 --- a/netbox/core/management/commands/rqworker.py +++ b/netbox/core/management/commands/rqworker.py @@ -2,6 +2,8 @@ import logging from django_rq.management.commands.rqworker import Command as _Command +from netbox.registry import registry + DEFAULT_QUEUES = ('high', 'default', 'low') @@ -14,6 +16,15 @@ class Command(_Command): of only the 'default' queue). """ def handle(self, *args, **options): + # Setup system jobs. + for job, kwargs in registry['system_jobs'].items(): + try: + interval = kwargs['interval'] + except KeyError: + raise TypeError("System job must specify an interval (in minutes).") + logger.debug(f"Scheduling system job {job.name} (interval={interval})") + job.enqueue_once(**kwargs) + # Run the worker with scheduler functionality options['with_scheduler'] = True diff --git a/netbox/core/migrations/0001_squashed_0005.py b/netbox/core/migrations/0001_squashed_0005.py index 971370bf2..b89fa3b25 100644 --- a/netbox/core/migrations/0001_squashed_0005.py +++ b/netbox/core/migrations/0001_squashed_0005.py @@ -8,13 +8,12 @@ import utilities.json class Migration(migrations.Migration): - replaces = [ ('core', '0001_initial'), ('core', '0002_managedfile'), ('core', '0003_job'), ('core', '0004_replicate_jobresults'), - ('core', '0005_job_created_auto_now') + ('core', '0005_job_created_auto_now'), ] dependencies = [ @@ -30,7 +29,10 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('description', models.CharField(blank=True, max_length=200)), ('comments', models.TextField(blank=True)), ('name', models.CharField(max_length=100, unique=True)), @@ -55,9 +57,28 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(editable=False)), ('path', models.CharField(editable=False, max_length=1000)), ('size', models.PositiveIntegerField(editable=False)), - ('hash', models.CharField(editable=False, max_length=64, validators=[django.core.validators.RegexValidator(message='Length must be 64 hexadecimal characters.', regex='^[0-9a-f]{64}$')])), + ( + 'hash', + models.CharField( + editable=False, + max_length=64, + validators=[ + django.core.validators.RegexValidator( + message='Length must be 64 hexadecimal characters.', regex='^[0-9a-f]{64}$' + ) + ], + ), + ), ('data', models.BinaryField()), - ('source', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='datafiles', to='core.datasource')), + ( + 'source', + models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.CASCADE, + related_name='datafiles', + to='core.datasource', + ), + ), ], options={ 'ordering': ('source', 'path'), @@ -76,8 +97,18 @@ class Migration(migrations.Migration): fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('object_id', models.PositiveBigIntegerField()), - ('datafile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='core.datafile')), - ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')), + ( + 'datafile', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='+', to='core.datafile' + ), + ), + ( + 'object_type', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype' + ), + ), ], options={ 'indexes': [models.Index(fields=['object_type', 'object_id'], name='core_autosy_object__c17bac_idx')], @@ -97,8 +128,26 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(blank=True, editable=False, null=True)), ('file_root', models.CharField(max_length=1000)), ('file_path', models.FilePathField(editable=False)), - ('data_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.datafile')), - ('data_source', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='core.datasource')), + ( + 'data_file', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='core.datafile', + ), + ), + ( + 'data_source', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='core.datasource', + ), + ), ('auto_sync_enabled', models.BooleanField(default=False)), ], options={ @@ -108,7 +157,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='managedfile', - constraint=models.UniqueConstraint(fields=('file_root', 'file_path'), name='core_managedfile_unique_root_path'), + constraint=models.UniqueConstraint( + fields=('file_root', 'file_path'), name='core_managedfile_unique_root_path' + ), ), migrations.CreateModel( name='Job', @@ -118,14 +169,33 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=200)), ('created', models.DateTimeField()), ('scheduled', models.DateTimeField(blank=True, null=True)), - ('interval', models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)])), + ( + 'interval', + models.PositiveIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), + ), ('started', models.DateTimeField(blank=True, null=True)), ('completed', models.DateTimeField(blank=True, null=True)), ('status', models.CharField(default='pending', max_length=30)), ('data', models.JSONField(blank=True, null=True)), ('job_id', models.UUIDField(unique=True)), - ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='jobs', to='contenttypes.contenttype')), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ( + 'object_type', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='jobs', to='contenttypes.contenttype' + ), + ), + ( + 'user', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ 'ordering': ['-created'], diff --git a/netbox/core/migrations/0006_datasource_type_remove_choices.py b/netbox/core/migrations/0006_datasource_type_remove_choices.py index 0ad8d8854..7c9914298 100644 --- a/netbox/core/migrations/0006_datasource_type_remove_choices.py +++ b/netbox/core/migrations/0006_datasource_type_remove_choices.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0005_job_created_auto_now'), ] diff --git a/netbox/core/migrations/0007_job_add_error_field.py b/netbox/core/migrations/0007_job_add_error_field.py index e2e173bfd..3b0e02b56 100644 --- a/netbox/core/migrations/0007_job_add_error_field.py +++ b/netbox/core/migrations/0007_job_add_error_field.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0006_datasource_type_remove_choices'), ] diff --git a/netbox/core/migrations/0008_contenttype_proxy.py b/netbox/core/migrations/0008_contenttype_proxy.py index dee82a969..9acaf3ad7 100644 --- a/netbox/core/migrations/0008_contenttype_proxy.py +++ b/netbox/core/migrations/0008_contenttype_proxy.py @@ -3,7 +3,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('contenttypes', '0002_remove_content_type_name'), ('core', '0007_job_add_error_field'), @@ -12,8 +11,7 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( name='ObjectType', - fields=[ - ], + fields=[], options={ 'proxy': True, 'indexes': [], diff --git a/netbox/core/migrations/0009_configrevision.py b/netbox/core/migrations/0009_configrevision.py index e7f817a16..6acd4531d 100644 --- a/netbox/core/migrations/0009_configrevision.py +++ b/netbox/core/migrations/0009_configrevision.py @@ -2,7 +2,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0008_contenttype_proxy'), ] diff --git a/netbox/core/migrations/0010_gfk_indexes.py b/netbox/core/migrations/0010_gfk_indexes.py index d51bc67ad..1e593a0c7 100644 --- a/netbox/core/migrations/0010_gfk_indexes.py +++ b/netbox/core/migrations/0010_gfk_indexes.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0009_configrevision'), ] diff --git a/netbox/core/migrations/0011_move_objectchange.py b/netbox/core/migrations/0011_move_objectchange.py index 2b41133ec..673763ce4 100644 --- a/netbox/core/migrations/0011_move_objectchange.py +++ b/netbox/core/migrations/0011_move_objectchange.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('contenttypes', '0002_remove_content_type_name'), ('core', '0010_gfk_indexes'), @@ -27,15 +26,49 @@ class Migration(migrations.Migration): ('object_repr', models.CharField(editable=False, max_length=200)), ('prechange_data', models.JSONField(blank=True, editable=False, null=True)), ('postchange_data', models.JSONField(blank=True, editable=False, null=True)), - ('changed_object_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')), - ('related_object_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='changes', to=settings.AUTH_USER_MODEL)), + ( + 'changed_object_type', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), + ), + ( + 'related_object_type', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), + ), + ( + 'user', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='changes', + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ 'verbose_name': 'object change', 'verbose_name_plural': 'object changes', 'ordering': ['-time'], - 'indexes': [models.Index(fields=['changed_object_type', 'changed_object_id'], name='core_object_changed_c227ce_idx'), models.Index(fields=['related_object_type', 'related_object_id'], name='core_object_related_3375d6_idx')], + 'indexes': [ + models.Index( + fields=['changed_object_type', 'changed_object_id'], + name='core_object_changed_c227ce_idx', + ), + models.Index( + fields=['related_object_type', 'related_object_id'], + name='core_object_related_3375d6_idx', + ), + ], }, ), ], diff --git a/netbox/core/migrations/0012_job_object_type_optional.py b/netbox/core/migrations/0012_job_object_type_optional.py index 3c6664afc..3798b1285 100644 --- a/netbox/core/migrations/0012_job_object_type_optional.py +++ b/netbox/core/migrations/0012_job_object_type_optional.py @@ -3,7 +3,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('contenttypes', '0002_remove_content_type_name'), ('core', '0011_move_objectchange'), @@ -18,7 +17,7 @@ class Migration(migrations.Migration): null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jobs', - to='contenttypes.contenttype' + to='contenttypes.contenttype', ), ), ] diff --git a/netbox/core/models/files.py b/netbox/core/models/files.py index 7b626a441..cc446bac7 100644 --- a/netbox/core/models/files.py +++ b/netbox/core/models/files.py @@ -93,9 +93,14 @@ class ManagedFile(SyncedDataMixin, models.Model): self.file_path = os.path.basename(self.data_path) # Ensure that the file root and path make a unique pair - if self._meta.model.objects.filter(file_root=self.file_root, file_path=self.file_path).exclude(pk=self.pk).exists(): + if self._meta.model.objects.filter( + file_root=self.file_root, file_path=self.file_path + ).exclude(pk=self.pk).exists(): raise ValidationError( - f"A {self._meta.verbose_name.lower()} with this file path already exists ({self.file_root}/{self.file_path}).") + _("A {model} with this file path already exists ({path}).").format( + model=self._meta.verbose_name.lower(), + path=f"{self.file_root}/{self.file_path}" + )) def delete(self, *args, **kwargs): # Delete file from disk diff --git a/netbox/core/models/jobs.py b/netbox/core/models/jobs.py index e1b5715dd..5caa9cc2d 100644 --- a/netbox/core/models/jobs.py +++ b/netbox/core/models/jobs.py @@ -9,6 +9,7 @@ from django.db import models from django.urls import reverse from django.utils import timezone from django.utils.translation import gettext as _ +from rq.exceptions import InvalidJobOperation from core.choices import JobStatusChoices from core.models import ObjectType @@ -130,7 +131,7 @@ class Job(models.Model): super().clean() # Validate the assigned object type - if self.object_type not in ObjectType.objects.with_feature('jobs'): + if self.object_type and self.object_type not in ObjectType.objects.with_feature('jobs'): raise ValidationError( _("Jobs cannot be assigned to this object type ({type}).").format(type=self.object_type) ) @@ -158,7 +159,11 @@ class Job(models.Model): job = queue.fetch_job(str(self.job_id)) if job: - job.cancel() + try: + job.cancel() + except InvalidJobOperation: + # Job may raise this exception from get_status() if missing from Redis + pass def start(self): """ @@ -198,7 +203,17 @@ class Job(models.Model): job_end.send(self) @classmethod - def enqueue(cls, func, instance=None, name='', user=None, schedule_at=None, interval=None, immediate=False, **kwargs): + def enqueue( + cls, + func, + instance=None, + name='', + user=None, + schedule_at=None, + interval=None, + immediate=False, + **kwargs + ): """ Create a Job instance and enqueue a job using the given callable @@ -223,7 +238,7 @@ class Job(models.Model): rq_queue_name = get_queue_for_model(object_type.model if object_type else None) queue = django_rq.get_queue(rq_queue_name) status = JobStatusChoices.STATUS_SCHEDULED if schedule_at else JobStatusChoices.STATUS_PENDING - job = Job.objects.create( + job = Job( object_type=object_type, object_id=object_id, name=name, @@ -233,6 +248,8 @@ class Job(models.Model): user=user, job_id=uuid.uuid4() ) + job.full_clean() + job.save() # Run the job immediately, rather than enqueuing it as a background task. Note that this is a synchronous # (blocking) operation, and execution will pause until the job completes. diff --git a/netbox/core/tests/test_api.py b/netbox/core/tests/test_api.py index eeb3bd9c4..d8fb8fd83 100644 --- a/netbox/core/tests/test_api.py +++ b/netbox/core/tests/test_api.py @@ -1,7 +1,14 @@ +import uuid + +from django_rq import get_queue +from django_rq.workers import get_worker from django.urls import reverse from django.utils import timezone +from rq.job import Job as RQ_Job, JobStatus +from rq.registry import FailedJobRegistry, StartedJobRegistry -from utilities.testing import APITestCase, APIViewTestCases +from users.models import Token, User +from utilities.testing import APITestCase, APIViewTestCases, TestCase from ..models import * @@ -91,3 +98,164 @@ class DataFileTest( ), ) DataFile.objects.bulk_create(data_files) + + +class BackgroundTaskTestCase(TestCase): + user_permissions = () + + @staticmethod + def dummy_job_default(): + return "Job finished" + + @staticmethod + def dummy_job_failing(): + raise Exception("Job failed") + + def setUp(self): + """ + Create a user and token for API calls. + """ + # Create the test user and assign permissions + self.user = User.objects.create_user(username='testuser') + self.user.is_staff = True + self.user.is_active = True + self.user.save() + self.token = Token.objects.create(user=self.user) + self.header = {'HTTP_AUTHORIZATION': f'Token {self.token.key}'} + + # Clear all queues prior to running each test + get_queue('default').connection.flushall() + get_queue('high').connection.flushall() + get_queue('low').connection.flushall() + + def test_background_queue_list(self): + url = reverse('core-api:rqqueue-list') + + # Attempt to load view without permission + self.user.is_staff = False + self.user.save() + response = self.client.get(url, **self.header) + self.assertEqual(response.status_code, 403) + + # Load view with permission + self.user.is_staff = True + self.user.save() + response = self.client.get(url, **self.header) + self.assertEqual(response.status_code, 200) + self.assertIn('default', str(response.content)) + self.assertIn('high', str(response.content)) + self.assertIn('low', str(response.content)) + + def test_background_queue(self): + response = self.client.get(reverse('core-api:rqqueue-detail', args=['default']), **self.header) + self.assertEqual(response.status_code, 200) + self.assertIn('default', str(response.content)) + self.assertIn('oldest_job_timestamp', str(response.content)) + self.assertIn('scheduled_jobs', str(response.content)) + + def test_background_task_list(self): + queue = get_queue('default') + queue.enqueue(self.dummy_job_default) + + response = self.client.get(reverse('core-api:rqtask-list'), **self.header) + self.assertEqual(response.status_code, 200) + self.assertIn('origin', str(response.content)) + self.assertIn('core.tests.test_api.BackgroundTaskTestCase.dummy_job_default()', str(response.content)) + + def test_background_task(self): + queue = get_queue('default') + job = queue.enqueue(self.dummy_job_default) + + response = self.client.get(reverse('core-api:rqtask-detail', args=[job.id]), **self.header) + self.assertEqual(response.status_code, 200) + self.assertIn(str(job.id), str(response.content)) + self.assertIn('origin', str(response.content)) + self.assertIn('meta', str(response.content)) + self.assertIn('kwargs', str(response.content)) + + def test_background_task_delete(self): + queue = get_queue('default') + job = queue.enqueue(self.dummy_job_default) + + response = self.client.post(reverse('core-api:rqtask-delete', args=[job.id]), **self.header) + self.assertEqual(response.status_code, 200) + self.assertFalse(RQ_Job.exists(job.id, connection=queue.connection)) + queue = get_queue('default') + self.assertNotIn(job.id, queue.job_ids) + + def test_background_task_requeue(self): + queue = get_queue('default') + + # Enqueue & run a job that will fail + job = queue.enqueue(self.dummy_job_failing) + worker = get_worker('default') + worker.work(burst=True) + self.assertTrue(job.is_failed) + + # Re-enqueue the failed job and check that its status has been reset + response = self.client.post(reverse('core-api:rqtask-requeue', args=[job.id]), **self.header) + self.assertEqual(response.status_code, 200) + job = RQ_Job.fetch(job.id, queue.connection) + self.assertFalse(job.is_failed) + + def test_background_task_enqueue(self): + queue = get_queue('default') + + # Enqueue some jobs that each depends on its predecessor + job = previous_job = None + for _ in range(0, 3): + job = queue.enqueue(self.dummy_job_default, depends_on=previous_job) + previous_job = job + + # Check that the last job to be enqueued has a status of deferred + self.assertIsNotNone(job) + self.assertEqual(job.get_status(), JobStatus.DEFERRED) + self.assertIsNone(job.enqueued_at) + + # Force-enqueue the deferred job + response = self.client.post(reverse('core-api:rqtask-enqueue', args=[job.id]), **self.header) + self.assertEqual(response.status_code, 200) + + # Check that job's status is updated correctly + job = queue.fetch_job(job.id) + self.assertEqual(job.get_status(), JobStatus.QUEUED) + self.assertIsNotNone(job.enqueued_at) + + def test_background_task_stop(self): + queue = get_queue('default') + + worker = get_worker('default') + job = queue.enqueue(self.dummy_job_default) + worker.prepare_job_execution(job) + + self.assertEqual(job.get_status(), JobStatus.STARTED) + response = self.client.post(reverse('core-api:rqtask-stop', args=[job.id]), **self.header) + self.assertEqual(response.status_code, 200) + worker.monitor_work_horse(job, queue) # Sets the job as Failed and removes from Started + started_job_registry = StartedJobRegistry(queue.name, connection=queue.connection) + self.assertEqual(len(started_job_registry), 0) + + canceled_job_registry = FailedJobRegistry(queue.name, connection=queue.connection) + self.assertEqual(len(canceled_job_registry), 1) + self.assertIn(job.id, canceled_job_registry) + + def test_worker_list(self): + worker1 = get_worker('default', name=uuid.uuid4().hex) + worker1.register_birth() + + worker2 = get_worker('high') + worker2.register_birth() + + response = self.client.get(reverse('core-api:rqworker-list'), **self.header) + self.assertEqual(response.status_code, 200) + self.assertIn(str(worker1.name), str(response.content)) + + def test_worker(self): + worker1 = get_worker('default', name=uuid.uuid4().hex) + worker1.register_birth() + + response = self.client.get(reverse('core-api:rqworker-detail', args=[worker1.name]), **self.header) + self.assertEqual(response.status_code, 200) + self.assertIn(str(worker1.name), str(response.content)) + self.assertIn('birth_date', str(response.content)) + self.assertIn('total_working_time', str(response.content)) diff --git a/netbox/core/tests/test_changelog.py b/netbox/core/tests/test_changelog.py index c58968ee8..4914dbaf3 100644 --- a/netbox/core/tests/test_changelog.py +++ b/netbox/core/tests/test_changelog.py @@ -76,10 +76,6 @@ class ChangeLogViewTest(ModelViewTestCase): self.assertEqual(oc.postchange_data['custom_fields']['cf2'], form_data['cf_cf2']) self.assertEqual(oc.postchange_data['tags'], ['Tag 1', 'Tag 2']) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.postchange_data) - self.assertNotIn('_name', oc.postchange_data_clean) - def test_update_object(self): site = Site(name='Site 1', slug='site-1') site.save() @@ -117,12 +113,6 @@ class ChangeLogViewTest(ModelViewTestCase): self.assertEqual(oc.postchange_data['custom_fields']['cf2'], form_data['cf_cf2']) self.assertEqual(oc.postchange_data['tags'], ['Tag 3']) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.prechange_data) - self.assertNotIn('_name', oc.prechange_data_clean) - self.assertIn('_name', oc.postchange_data) - self.assertNotIn('_name', oc.postchange_data_clean) - def test_delete_object(self): site = Site( name='Site 1', @@ -153,10 +143,6 @@ class ChangeLogViewTest(ModelViewTestCase): self.assertEqual(oc.prechange_data['tags'], ['Tag 1', 'Tag 2']) self.assertEqual(oc.postchange_data, None) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.prechange_data) - self.assertNotIn('_name', oc.prechange_data_clean) - def test_bulk_update_objects(self): sites = ( Site(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE), @@ -353,10 +339,6 @@ class ChangeLogAPITest(APITestCase): self.assertEqual(oc.postchange_data['custom_fields'], data['custom_fields']) self.assertEqual(oc.postchange_data['tags'], ['Tag 1', 'Tag 2']) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.postchange_data) - self.assertNotIn('_name', oc.postchange_data_clean) - def test_update_object(self): site = Site(name='Site 1', slug='site-1') site.save() @@ -389,12 +371,6 @@ class ChangeLogAPITest(APITestCase): self.assertEqual(oc.postchange_data['custom_fields'], data['custom_fields']) self.assertEqual(oc.postchange_data['tags'], ['Tag 3']) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.prechange_data) - self.assertNotIn('_name', oc.prechange_data_clean) - self.assertIn('_name', oc.postchange_data) - self.assertNotIn('_name', oc.postchange_data_clean) - def test_delete_object(self): site = Site( name='Site 1', @@ -423,10 +399,6 @@ class ChangeLogAPITest(APITestCase): self.assertEqual(oc.prechange_data['tags'], ['Tag 1', 'Tag 2']) self.assertEqual(oc.postchange_data, None) - # Check that private attributes were included in raw data but not display data - self.assertIn('_name', oc.prechange_data) - self.assertNotIn('_name', oc.prechange_data_clean) - def test_bulk_create_objects(self): data = ( { diff --git a/netbox/core/tests/test_views.py b/netbox/core/tests/test_views.py index 3c847e4ef..047b51ef6 100644 --- a/netbox/core/tests/test_views.py +++ b/netbox/core/tests/test_views.py @@ -308,6 +308,7 @@ class BackgroundTaskTestCase(TestCase): worker = get_worker('default') job = queue.enqueue(self.dummy_job_default) worker.prepare_job_execution(job) + worker.prepare_execution(job) self.assertEqual(job.get_status(), JobStatus.STARTED) @@ -345,3 +346,32 @@ class BackgroundTaskTestCase(TestCase): self.assertIn(str(worker1.name), str(response.content)) self.assertIn('Birth', str(response.content)) self.assertIn('Total working time', str(response.content)) + + +class SystemTestCase(TestCase): + + def setUp(self): + super().setUp() + + self.user.is_staff = True + self.user.save() + + def test_system_view_default(self): + # Test UI render + response = self.client.get(reverse('core:system')) + self.assertEqual(response.status_code, 200) + + # Test export + response = self.client.get(f"{reverse('core:system')}?export=true") + self.assertEqual(response.status_code, 200) + + def test_system_view_with_config_revision(self): + ConfigRevision.objects.create() + + # Test UI render + response = self.client.get(reverse('core:system')) + self.assertEqual(response.status_code, 200) + + # Test export + response = self.client.get(f"{reverse('core:system')}?export=true") + self.assertEqual(response.status_code, 200) diff --git a/netbox/core/urls.py b/netbox/core/urls.py index fd6ec8996..b922c8bed 100644 --- a/netbox/core/urls.py +++ b/netbox/core/urls.py @@ -6,51 +6,50 @@ from . import views app_name = 'core' urlpatterns = ( - # Data sources - path('data-sources/', views.DataSourceListView.as_view(), name='datasource_list'), - path('data-sources/add/', views.DataSourceEditView.as_view(), name='datasource_add'), - path('data-sources/import/', views.DataSourceBulkImportView.as_view(), name='datasource_import'), - path('data-sources/edit/', views.DataSourceBulkEditView.as_view(), name='datasource_bulk_edit'), - path('data-sources/delete/', views.DataSourceBulkDeleteView.as_view(), name='datasource_bulk_delete'), + path('data-sources/', include(get_model_urls('core', 'datasource', detail=False))), path('data-sources//', include(get_model_urls('core', 'datasource'))), - # Data files - path('data-files/', views.DataFileListView.as_view(), name='datafile_list'), - path('data-files/delete/', views.DataFileBulkDeleteView.as_view(), name='datafile_bulk_delete'), + path('data-files/', include(get_model_urls('core', 'datafile', detail=False))), path('data-files//', include(get_model_urls('core', 'datafile'))), - # Job results - path('jobs/', views.JobListView.as_view(), name='job_list'), - path('jobs/delete/', views.JobBulkDeleteView.as_view(), name='job_bulk_delete'), - path('jobs//', views.JobView.as_view(), name='job'), - path('jobs//delete/', views.JobDeleteView.as_view(), name='job_delete'), + path('jobs/', include(get_model_urls('core', 'job', detail=False))), + path('jobs//', include(get_model_urls('core', 'job'))), - # Change logging - path('changelog/', views.ObjectChangeListView.as_view(), name='objectchange_list'), + path('changelog/', include(get_model_urls('core', 'objectchange', detail=False))), path('changelog//', include(get_model_urls('core', 'objectchange'))), # Background Tasks path('background-queues/', views.BackgroundQueueListView.as_view(), name='background_queue_list'), - path('background-queues///', views.BackgroundTaskListView.as_view(), name='background_task_list'), + path( + 'background-queues///', + views.BackgroundTaskListView.as_view(), + name='background_task_list' + ), path('background-tasks//', views.BackgroundTaskView.as_view(), name='background_task'), - path('background-tasks//delete/', views.BackgroundTaskDeleteView.as_view(), name='background_task_delete'), - path('background-tasks//requeue/', views.BackgroundTaskRequeueView.as_view(), name='background_task_requeue'), - path('background-tasks//enqueue/', views.BackgroundTaskEnqueueView.as_view(), name='background_task_enqueue'), + path( + 'background-tasks//delete/', + views.BackgroundTaskDeleteView.as_view(), + name='background_task_delete' + ), + path( + 'background-tasks//requeue/', + views.BackgroundTaskRequeueView.as_view(), + name='background_task_requeue' + ), + path( + 'background-tasks//enqueue/', + views.BackgroundTaskEnqueueView.as_view(), + name='background_task_enqueue' + ), path('background-tasks//stop/', views.BackgroundTaskStopView.as_view(), name='background_task_stop'), path('background-workers//', views.WorkerListView.as_view(), name='worker_list'), path('background-workers//', views.WorkerView.as_view(), name='worker'), - # Config revisions - path('config-revisions/', views.ConfigRevisionListView.as_view(), name='configrevision_list'), - path('config-revisions/add/', views.ConfigRevisionEditView.as_view(), name='configrevision_add'), - path('config-revisions/delete/', views.ConfigRevisionBulkDeleteView.as_view(), name='configrevision_bulk_delete'), - path('config-revisions//restore/', views.ConfigRevisionRestoreView.as_view(), name='configrevision_restore'), + path('config-revisions/', include(get_model_urls('core', 'configrevision', detail=False))), path('config-revisions//', include(get_model_urls('core', 'configrevision'))), - # System path('system/', views.SystemView.as_view(), name='system'), - # Plugins path('plugins/', views.PluginListView.as_view(), name='plugin_list'), path('plugins//', views.PluginView.as_view(), name='plugin'), ) diff --git a/netbox/core/utils.py b/netbox/core/utils.py new file mode 100644 index 000000000..26adfdfa2 --- /dev/null +++ b/netbox/core/utils.py @@ -0,0 +1,155 @@ +from django.http import Http404 +from django.utils.translation import gettext_lazy as _ +from django_rq.queues import get_queue, get_queue_by_index, get_redis_connection +from django_rq.settings import QUEUES_MAP, QUEUES_LIST +from django_rq.utils import get_jobs, stop_jobs +from rq import requeue_job +from rq.exceptions import NoSuchJobError +from rq.job import Job as RQ_Job, JobStatus as RQJobStatus +from rq.registry import ( + DeferredJobRegistry, + FailedJobRegistry, + FinishedJobRegistry, + ScheduledJobRegistry, + StartedJobRegistry, +) + +__all__ = ( + 'delete_rq_job', + 'enqueue_rq_job', + 'get_rq_jobs', + 'get_rq_jobs_from_status', + 'requeue_rq_job', + 'stop_rq_job', +) + + +def get_rq_jobs(): + """ + Return a list of all RQ jobs. + """ + jobs = set() + + for queue in QUEUES_LIST: + queue = get_queue(queue['name']) + jobs.update(queue.get_jobs()) + + return list(jobs) + + +def get_rq_jobs_from_status(queue, status): + """ + Return the RQ jobs with the given status. + """ + jobs = [] + + try: + registry_cls = { + RQJobStatus.STARTED: StartedJobRegistry, + RQJobStatus.DEFERRED: DeferredJobRegistry, + RQJobStatus.FINISHED: FinishedJobRegistry, + RQJobStatus.FAILED: FailedJobRegistry, + RQJobStatus.SCHEDULED: ScheduledJobRegistry, + }[status] + except KeyError: + raise Http404 + registry = registry_cls(queue.name, queue.connection) + + job_ids = registry.get_job_ids() + if status != RQJobStatus.DEFERRED: + jobs = get_jobs(queue, job_ids, registry) + else: + # Deferred jobs require special handling + for job_id in job_ids: + try: + jobs.append(RQ_Job.fetch(job_id, connection=queue.connection, serializer=queue.serializer)) + except NoSuchJobError: + pass + + if jobs and status == RQJobStatus.SCHEDULED: + for job in jobs: + job.scheduled_at = registry.get_scheduled_time(job) + + return jobs + + +def delete_rq_job(job_id): + """ + Delete the specified RQ job. + """ + config = QUEUES_LIST[0] + try: + job = RQ_Job.fetch(job_id, connection=get_redis_connection(config['connection_config']),) + except NoSuchJobError: + raise Http404(_("Job {job_id} not found").format(job_id=job_id)) + + queue_index = QUEUES_MAP[job.origin] + queue = get_queue_by_index(queue_index) + + # Remove job id from queue and delete the actual job + queue.connection.lrem(queue.key, 0, job.id) + job.delete() + + +def requeue_rq_job(job_id): + """ + Requeue the specified RQ job. + """ + config = QUEUES_LIST[0] + try: + job = RQ_Job.fetch(job_id, connection=get_redis_connection(config['connection_config']),) + except NoSuchJobError: + raise Http404(_("Job {id} not found.").format(id=job_id)) + + queue_index = QUEUES_MAP[job.origin] + queue = get_queue_by_index(queue_index) + + requeue_job(job_id, connection=queue.connection, serializer=queue.serializer) + + +def enqueue_rq_job(job_id): + """ + Enqueue the specified RQ job. + """ + config = QUEUES_LIST[0] + try: + job = RQ_Job.fetch(job_id, connection=get_redis_connection(config['connection_config']),) + except NoSuchJobError: + raise Http404(_("Job {id} not found.").format(id=job_id)) + + queue_index = QUEUES_MAP[job.origin] + queue = get_queue_by_index(queue_index) + + try: + # _enqueue_job is new in RQ 1.14, this is used to enqueue + # job regardless of its dependencies + queue._enqueue_job(job) + except AttributeError: + queue.enqueue_job(job) + + # Remove job from correct registry if needed + if job.get_status() == RQJobStatus.DEFERRED: + registry = DeferredJobRegistry(queue.name, queue.connection) + registry.remove(job) + elif job.get_status() == RQJobStatus.FINISHED: + registry = FinishedJobRegistry(queue.name, queue.connection) + registry.remove(job) + elif job.get_status() == RQJobStatus.SCHEDULED: + registry = ScheduledJobRegistry(queue.name, queue.connection) + registry.remove(job) + + +def stop_rq_job(job_id): + """ + Stop the specified RQ job. + """ + config = QUEUES_LIST[0] + try: + job = RQ_Job.fetch(job_id, connection=get_redis_connection(config['connection_config']),) + except NoSuchJobError: + raise Http404(_("Job {job_id} not found").format(job_id=job_id)) + + queue_index = QUEUES_MAP[job.origin] + queue = get_queue_by_index(queue_index) + + return stop_jobs(queue, job_id)[0] diff --git a/netbox/core/views.py b/netbox/core/views.py index 3c5319626..713807a82 100644 --- a/netbox/core/views.py +++ b/netbox/core/views.py @@ -14,16 +14,13 @@ from django.utils.translation import gettext_lazy as _ from django.views.generic import View from django_rq.queues import get_connection, get_queue_by_index, get_redis_connection from django_rq.settings import QUEUES_MAP, QUEUES_LIST -from django_rq.utils import get_jobs, get_statistics, stop_jobs -from rq import requeue_job +from django_rq.utils import get_statistics from rq.exceptions import NoSuchJobError from rq.job import Job as RQ_Job, JobStatus as RQJobStatus -from rq.registry import ( - DeferredJobRegistry, FailedJobRegistry, FinishedJobRegistry, ScheduledJobRegistry, StartedJobRegistry, -) from rq.worker import Worker from rq.worker_registration import clean_worker_registry +from core.utils import delete_rq_job, enqueue_rq_job, get_rq_jobs_from_status, requeue_rq_job, stop_rq_job from netbox.config import get_config, PARAMS from netbox.views import generic from netbox.views.generic.base import BaseObjectView @@ -46,6 +43,7 @@ from .tables import CatalogPluginTable, PluginVersionTable # Data sources # +@register_model_view(DataSource, 'list', path='', detail=False) class DataSourceListView(generic.ObjectListView): queryset = DataSource.objects.annotate( file_count=count_related(DataFile, 'source') @@ -92,6 +90,7 @@ class DataSourceSyncView(BaseObjectView): return redirect(datasource.get_absolute_url()) +@register_model_view(DataSource, 'add', detail=False) @register_model_view(DataSource, 'edit') class DataSourceEditView(generic.ObjectEditView): queryset = DataSource.objects.all() @@ -103,11 +102,13 @@ class DataSourceDeleteView(generic.ObjectDeleteView): queryset = DataSource.objects.all() +@register_model_view(DataSource, 'bulk_import', detail=False) class DataSourceBulkImportView(generic.BulkImportView): queryset = DataSource.objects.all() model_form = forms.DataSourceImportForm +@register_model_view(DataSource, 'bulk_edit', path='edit', detail=False) class DataSourceBulkEditView(generic.BulkEditView): queryset = DataSource.objects.annotate( count_files=count_related(DataFile, 'source') @@ -117,6 +118,7 @@ class DataSourceBulkEditView(generic.BulkEditView): form = forms.DataSourceBulkEditForm +@register_model_view(DataSource, 'bulk_delete', path='delete', detail=False) class DataSourceBulkDeleteView(generic.BulkDeleteView): queryset = DataSource.objects.annotate( count_files=count_related(DataFile, 'source') @@ -129,6 +131,7 @@ class DataSourceBulkDeleteView(generic.BulkDeleteView): # Data files # +@register_model_view(DataFile, 'list', path='', detail=False) class DataFileListView(generic.ObjectListView): queryset = DataFile.objects.defer('data') filterset = filtersets.DataFileFilterSet @@ -149,6 +152,7 @@ class DataFileDeleteView(generic.ObjectDeleteView): queryset = DataFile.objects.all() +@register_model_view(DataFile, 'bulk_delete', path='delete', detail=False) class DataFileBulkDeleteView(generic.BulkDeleteView): queryset = DataFile.objects.defer('data') filterset = filtersets.DataFileFilterSet @@ -159,6 +163,7 @@ class DataFileBulkDeleteView(generic.BulkDeleteView): # Jobs # +@register_model_view(Job, 'list', path='', detail=False) class JobListView(generic.ObjectListView): queryset = Job.objects.all() filterset = filtersets.JobFilterSet @@ -170,14 +175,17 @@ class JobListView(generic.ObjectListView): } +@register_model_view(Job) class JobView(generic.ObjectView): queryset = Job.objects.all() +@register_model_view(Job, 'delete') class JobDeleteView(generic.ObjectDeleteView): queryset = Job.objects.all() +@register_model_view(Job, 'bulk_delete', path='delete', detail=False) class JobBulkDeleteView(generic.BulkDeleteView): queryset = Job.objects.all() filterset = filtersets.JobFilterSet @@ -188,6 +196,7 @@ class JobBulkDeleteView(generic.BulkDeleteView): # Change logging # +@register_model_view(ObjectChange, 'list', path='', detail=False) class ObjectChangeListView(generic.ObjectListView): queryset = ObjectChange.objects.valid_models() filterset = filtersets.ObjectChangeFilterSet @@ -257,6 +266,7 @@ class ObjectChangeView(generic.ObjectView): # Config Revisions # +@register_model_view(ConfigRevision, 'list', path='', detail=False) class ConfigRevisionListView(generic.ObjectListView): queryset = ConfigRevision.objects.all() filterset = filtersets.ConfigRevisionFilterSet @@ -269,6 +279,7 @@ class ConfigRevisionView(generic.ObjectView): queryset = ConfigRevision.objects.all() +@register_model_view(ConfigRevision, 'add', detail=False) class ConfigRevisionEditView(generic.ObjectEditView): queryset = ConfigRevision.objects.all() form = forms.ConfigRevisionForm @@ -279,12 +290,14 @@ class ConfigRevisionDeleteView(generic.ObjectDeleteView): queryset = ConfigRevision.objects.all() +@register_model_view(ConfigRevision, 'bulk_delete', path='delete', detail=False) class ConfigRevisionBulkDeleteView(generic.BulkDeleteView): queryset = ConfigRevision.objects.all() filterset = filtersets.ConfigRevisionFilterSet table = tables.ConfigRevisionTable +@register_model_view(ConfigRevision, 'restore') class ConfigRevisionRestoreView(ContentTypePermissionRequiredMixin, View): def get_required_permission(self): @@ -347,41 +360,12 @@ class BackgroundTaskListView(TableMixin, BaseRQView): table = tables.BackgroundTaskTable def get_table_data(self, request, queue, status): - jobs = [] # Call get_jobs() to returned queued tasks if status == RQJobStatus.QUEUED: return queue.get_jobs() - # For other statuses, determine the registry to list (or raise a 404 for invalid statuses) - try: - registry_cls = { - RQJobStatus.STARTED: StartedJobRegistry, - RQJobStatus.DEFERRED: DeferredJobRegistry, - RQJobStatus.FINISHED: FinishedJobRegistry, - RQJobStatus.FAILED: FailedJobRegistry, - RQJobStatus.SCHEDULED: ScheduledJobRegistry, - }[status] - except KeyError: - raise Http404 - registry = registry_cls(queue.name, queue.connection) - - job_ids = registry.get_job_ids() - if status != RQJobStatus.DEFERRED: - jobs = get_jobs(queue, job_ids, registry) - else: - # Deferred jobs require special handling - for job_id in job_ids: - try: - jobs.append(RQ_Job.fetch(job_id, connection=queue.connection, serializer=queue.serializer)) - except NoSuchJobError: - pass - - if jobs and status == RQJobStatus.SCHEDULED: - for job in jobs: - job.scheduled_at = registry.get_scheduled_time(job) - - return jobs + return get_rq_jobs_from_status(queue, status) def get(self, request, queue_index, status): queue = get_queue_by_index(queue_index) @@ -447,19 +431,7 @@ class BackgroundTaskDeleteView(BaseRQView): form = ConfirmationForm(request.POST) if form.is_valid(): - # all the RQ queues should use the same connection - config = QUEUES_LIST[0] - try: - job = RQ_Job.fetch(job_id, connection=get_redis_connection(config['connection_config']),) - except NoSuchJobError: - raise Http404(_("Job {job_id} not found").format(job_id=job_id)) - - queue_index = QUEUES_MAP[job.origin] - queue = get_queue_by_index(queue_index) - - # Remove job id from queue and delete the actual job - queue.connection.lrem(queue.key, 0, job.id) - job.delete() + delete_rq_job(job_id) messages.success(request, _('Job {id} has been deleted.').format(id=job_id)) else: messages.error(request, _('Error deleting job {id}: {error}').format(id=job_id, error=form.errors[0])) @@ -470,17 +442,7 @@ class BackgroundTaskDeleteView(BaseRQView): class BackgroundTaskRequeueView(BaseRQView): def get(self, request, job_id): - # all the RQ queues should use the same connection - config = QUEUES_LIST[0] - try: - job = RQ_Job.fetch(job_id, connection=get_redis_connection(config['connection_config']),) - except NoSuchJobError: - raise Http404(_("Job {id} not found.").format(id=job_id)) - - queue_index = QUEUES_MAP[job.origin] - queue = get_queue_by_index(queue_index) - - requeue_job(job_id, connection=queue.connection, serializer=queue.serializer) + requeue_rq_job(job_id) messages.success(request, _('Job {id} has been re-enqueued.').format(id=job_id)) return redirect(reverse('core:background_task', args=[job_id])) @@ -489,33 +451,7 @@ class BackgroundTaskEnqueueView(BaseRQView): def get(self, request, job_id): # all the RQ queues should use the same connection - config = QUEUES_LIST[0] - try: - job = RQ_Job.fetch(job_id, connection=get_redis_connection(config['connection_config']),) - except NoSuchJobError: - raise Http404(_("Job {id} not found.").format(id=job_id)) - - queue_index = QUEUES_MAP[job.origin] - queue = get_queue_by_index(queue_index) - - try: - # _enqueue_job is new in RQ 1.14, this is used to enqueue - # job regardless of its dependencies - queue._enqueue_job(job) - except AttributeError: - queue.enqueue_job(job) - - # Remove job from correct registry if needed - if job.get_status() == RQJobStatus.DEFERRED: - registry = DeferredJobRegistry(queue.name, queue.connection) - registry.remove(job) - elif job.get_status() == RQJobStatus.FINISHED: - registry = FinishedJobRegistry(queue.name, queue.connection) - registry.remove(job) - elif job.get_status() == RQJobStatus.SCHEDULED: - registry = ScheduledJobRegistry(queue.name, queue.connection) - registry.remove(job) - + enqueue_rq_job(job_id) messages.success(request, _('Job {id} has been enqueued.').format(id=job_id)) return redirect(reverse('core:background_task', args=[job_id])) @@ -523,17 +459,7 @@ class BackgroundTaskEnqueueView(BaseRQView): class BackgroundTaskStopView(BaseRQView): def get(self, request, job_id): - # all the RQ queues should use the same connection - config = QUEUES_LIST[0] - try: - job = RQ_Job.fetch(job_id, connection=get_redis_connection(config['connection_config']),) - except NoSuchJobError: - raise Http404(_("Job {job_id} not found").format(job_id=job_id)) - - queue_index = QUEUES_MAP[job.origin] - queue = get_queue_by_index(queue_index) - - stopped_jobs = stop_jobs(queue, job_id)[0] + stopped_jobs = stop_rq_job(job_id) if len(stopped_jobs) == 1: messages.success(request, _('Job {id} has been stopped.').format(id=job_id)) else: @@ -626,11 +552,7 @@ class SystemView(UserPassesTestMixin, View): } # Configuration - try: - config = ConfigRevision.objects.get(pk=cache.get('config_version')) - except ConfigRevision.DoesNotExist: - # Fall back to using the active config data if no record is found - config = get_config() + config = get_config() # Raw data export if 'export' in request.GET: diff --git a/netbox/dcim/api/nested_serializers.py b/netbox/dcim/api/nested_serializers.py deleted file mode 100644 index 4b8f0db4a..000000000 --- a/netbox/dcim/api/nested_serializers.py +++ /dev/null @@ -1,389 +0,0 @@ -import warnings - -from drf_spectacular.utils import extend_schema_serializer -from rest_framework import serializers - -from dcim import models -from netbox.api.fields import RelatedObjectCountField -from netbox.api.serializers import WritableNestedSerializer -from .serializers_.nested import ( - NestedDeviceBaySerializer, NestedDeviceSerializer, NestedInterfaceSerializer, NestedInterfaceTemplateSerializer, - NestedLocationSerializer, NestedModuleBaySerializer, NestedRegionSerializer, NestedSiteGroupSerializer, -) - -__all__ = [ - 'NestedCableSerializer', - 'NestedConsolePortSerializer', - 'NestedConsolePortTemplateSerializer', - 'NestedConsoleServerPortSerializer', - 'NestedConsoleServerPortTemplateSerializer', - 'NestedDeviceBaySerializer', - 'NestedDeviceBayTemplateSerializer', - 'NestedDeviceRoleSerializer', - 'NestedDeviceSerializer', - 'NestedDeviceTypeSerializer', - 'NestedFrontPortSerializer', - 'NestedFrontPortTemplateSerializer', - 'NestedInterfaceSerializer', - 'NestedInterfaceTemplateSerializer', - 'NestedInventoryItemSerializer', - 'NestedInventoryItemRoleSerializer', - 'NestedInventoryItemTemplateSerializer', - 'NestedManufacturerSerializer', - 'NestedModuleBaySerializer', - 'NestedModuleBayTemplateSerializer', - 'NestedModuleSerializer', - 'NestedModuleTypeSerializer', - 'NestedPlatformSerializer', - 'NestedPowerFeedSerializer', - 'NestedPowerOutletSerializer', - 'NestedPowerOutletTemplateSerializer', - 'NestedPowerPanelSerializer', - 'NestedPowerPortSerializer', - 'NestedPowerPortTemplateSerializer', - 'NestedLocationSerializer', - 'NestedRackReservationSerializer', - 'NestedRackRoleSerializer', - 'NestedRackSerializer', - 'NestedRearPortSerializer', - 'NestedRearPortTemplateSerializer', - 'NestedRegionSerializer', - 'NestedSiteSerializer', - 'NestedSiteGroupSerializer', - 'NestedVirtualChassisSerializer', - 'NestedVirtualDeviceContextSerializer', -] - -# TODO: Remove in v4.2 -warnings.warn( - "Dedicated nested serializers will be removed in NetBox v4.2. Use Serializer(nested=True) instead.", - DeprecationWarning -) - - -# -# Regions/sites -# - -class NestedSiteSerializer(WritableNestedSerializer): - - class Meta: - model = models.Site - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug'] - - -# -# Racks -# - -@extend_schema_serializer( - exclude_fields=('rack_count',), -) -class NestedRackRoleSerializer(WritableNestedSerializer): - rack_count = RelatedObjectCountField('racks') - - class Meta: - model = models.RackRole - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'rack_count'] - - -@extend_schema_serializer( - exclude_fields=('device_count',), -) -class NestedRackSerializer(WritableNestedSerializer): - device_count = RelatedObjectCountField('devices') - - class Meta: - model = models.Rack - fields = ['id', 'url', 'display_url', 'display', 'name', 'device_count'] - - -class NestedRackReservationSerializer(WritableNestedSerializer): - user = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = models.RackReservation - fields = ['id', 'url', 'display_url', 'display', 'user', 'units'] - - def get_user(self, obj): - return obj.user.username - - -# -# Device/module types -# - -@extend_schema_serializer( - exclude_fields=('devicetype_count',), -) -class NestedManufacturerSerializer(WritableNestedSerializer): - devicetype_count = RelatedObjectCountField('device_types') - - class Meta: - model = models.Manufacturer - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'devicetype_count'] - - -@extend_schema_serializer( - exclude_fields=('device_count',), -) -class NestedDeviceTypeSerializer(WritableNestedSerializer): - manufacturer = NestedManufacturerSerializer(read_only=True) - device_count = RelatedObjectCountField('instances') - - class Meta: - model = models.DeviceType - fields = ['id', 'url', 'display_url', 'display', 'manufacturer', 'model', 'slug', 'device_count'] - - -class NestedModuleTypeSerializer(WritableNestedSerializer): - manufacturer = NestedManufacturerSerializer(read_only=True) - - class Meta: - model = models.ModuleType - fields = ['id', 'url', 'display_url', 'display', 'manufacturer', 'model'] - - -# -# Component templates -# - -class NestedConsolePortTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.ConsolePortTemplate - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedConsoleServerPortTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.ConsoleServerPortTemplate - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedPowerPortTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.PowerPortTemplate - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedPowerOutletTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.PowerOutletTemplate - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedRearPortTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.RearPortTemplate - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedFrontPortTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.FrontPortTemplate - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedModuleBayTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.ModuleBayTemplate - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedDeviceBayTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.DeviceBayTemplate - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedInventoryItemTemplateSerializer(WritableNestedSerializer): - _depth = serializers.IntegerField(source='level', read_only=True) - - class Meta: - model = models.InventoryItemTemplate - fields = ['id', 'url', 'display_url', 'display', 'name', '_depth'] - - -# -# Devices -# - -@extend_schema_serializer( - exclude_fields=('device_count', 'virtualmachine_count'), -) -class NestedDeviceRoleSerializer(WritableNestedSerializer): - device_count = RelatedObjectCountField('devices') - virtualmachine_count = RelatedObjectCountField('virtual_machines') - - class Meta: - model = models.DeviceRole - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'device_count', 'virtualmachine_count'] - - -@extend_schema_serializer( - exclude_fields=('device_count', 'virtualmachine_count'), -) -class NestedPlatformSerializer(WritableNestedSerializer): - device_count = RelatedObjectCountField('devices') - virtualmachine_count = RelatedObjectCountField('virtual_machines') - - class Meta: - model = models.Platform - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'device_count', 'virtualmachine_count'] - - -class ModuleNestedModuleBaySerializer(WritableNestedSerializer): - - class Meta: - model = models.ModuleBay - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedModuleSerializer(WritableNestedSerializer): - device = NestedDeviceSerializer(read_only=True) - module_bay = ModuleNestedModuleBaySerializer(read_only=True) - module_type = NestedModuleTypeSerializer(read_only=True) - - class Meta: - model = models.Module - fields = ['id', 'url', 'display_url', 'display', 'device', 'module_bay', 'module_type'] - - -class NestedConsoleServerPortSerializer(WritableNestedSerializer): - device = NestedDeviceSerializer(read_only=True) - _occupied = serializers.BooleanField(required=False, read_only=True) - - class Meta: - model = models.ConsoleServerPort - fields = ['id', 'url', 'display_url', 'display', 'device', 'name', 'cable', '_occupied'] - - -class NestedConsolePortSerializer(WritableNestedSerializer): - device = NestedDeviceSerializer(read_only=True) - _occupied = serializers.BooleanField(required=False, read_only=True) - - class Meta: - model = models.ConsolePort - fields = ['id', 'url', 'display_url', 'display', 'device', 'name', 'cable', '_occupied'] - - -class NestedPowerOutletSerializer(WritableNestedSerializer): - device = NestedDeviceSerializer(read_only=True) - _occupied = serializers.BooleanField(required=False, read_only=True) - - class Meta: - model = models.PowerOutlet - fields = ['id', 'url', 'display_url', 'display', 'device', 'name', 'cable', '_occupied'] - - -class NestedPowerPortSerializer(WritableNestedSerializer): - device = NestedDeviceSerializer(read_only=True) - _occupied = serializers.BooleanField(required=False, read_only=True) - - class Meta: - model = models.PowerPort - fields = ['id', 'url', 'display_url', 'display', 'device', 'name', 'cable', '_occupied'] - - -class NestedRearPortSerializer(WritableNestedSerializer): - device = NestedDeviceSerializer(read_only=True) - _occupied = serializers.BooleanField(required=False, read_only=True) - - class Meta: - model = models.RearPort - fields = ['id', 'url', 'display_url', 'display', 'device', 'name', 'cable', '_occupied'] - - -class NestedFrontPortSerializer(WritableNestedSerializer): - device = NestedDeviceSerializer(read_only=True) - _occupied = serializers.BooleanField(required=False, read_only=True) - - class Meta: - model = models.FrontPort - fields = ['id', 'url', 'display_url', 'display', 'device', 'name', 'cable', '_occupied'] - - -class NestedInventoryItemSerializer(WritableNestedSerializer): - device = NestedDeviceSerializer(read_only=True) - _depth = serializers.IntegerField(source='level', read_only=True) - - class Meta: - model = models.InventoryItem - fields = ['id', 'url', 'display_url', 'display', 'device', 'name', '_depth'] - - -@extend_schema_serializer( - exclude_fields=('inventoryitem_count',), -) -class NestedInventoryItemRoleSerializer(WritableNestedSerializer): - inventoryitem_count = RelatedObjectCountField('inventory_items') - - class Meta: - model = models.InventoryItemRole - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'inventoryitem_count'] - - -# -# Cables -# - -class NestedCableSerializer(WritableNestedSerializer): - - class Meta: - model = models.Cable - fields = ['id', 'url', 'display_url', 'display', 'label'] - - -# -# Virtual chassis -# - -@extend_schema_serializer( - exclude_fields=('member_count',), -) -class NestedVirtualChassisSerializer(WritableNestedSerializer): - master = NestedDeviceSerializer() - member_count = serializers.IntegerField(read_only=True) - - class Meta: - model = models.VirtualChassis - fields = ['id', 'url', 'display_url', 'display', 'name', 'master', 'member_count'] - - -# -# Power panels/feeds -# - -@extend_schema_serializer( - exclude_fields=('powerfeed_count',), -) -class NestedPowerPanelSerializer(WritableNestedSerializer): - powerfeed_count = RelatedObjectCountField('powerfeeds') - - class Meta: - model = models.PowerPanel - fields = ['id', 'url', 'display_url', 'display', 'name', 'powerfeed_count'] - - -class NestedPowerFeedSerializer(WritableNestedSerializer): - _occupied = serializers.BooleanField(required=False, read_only=True) - - class Meta: - model = models.PowerFeed - fields = ['id', 'url', 'display_url', 'display', 'name', 'cable', '_occupied'] - - -class NestedVirtualDeviceContextSerializer(WritableNestedSerializer): - device = NestedDeviceSerializer() - - class Meta: - model = models.VirtualDeviceContext - fields = ['id', 'url', 'display_url', 'display', 'name', 'identifier', 'device'] diff --git a/netbox/dcim/api/serializers_/device_components.py b/netbox/dcim/api/serializers_/device_components.py index e285ce349..a6767bb6f 100644 --- a/netbox/dcim/api/serializers_/device_components.py +++ b/netbox/dcim/api/serializers_/device_components.py @@ -8,7 +8,7 @@ from dcim.models import ( ConsolePort, ConsoleServerPort, DeviceBay, FrontPort, Interface, InventoryItem, ModuleBay, PowerOutlet, PowerPort, RearPort, VirtualDeviceContext, ) -from ipam.api.serializers_.vlans import VLANSerializer +from ipam.api.serializers_.vlans import VLANSerializer, VLANTranslationPolicySerializer from ipam.api.serializers_.vrfs import VRFSerializer from ipam.models import VLAN from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField @@ -21,7 +21,7 @@ from wireless.choices import * from wireless.models import WirelessLAN from .base import ConnectedEndpointsSerializer from .cables import CabledObjectSerializer -from .devices import DeviceSerializer, ModuleSerializer, VirtualDeviceContextSerializer +from .devices import DeviceSerializer, MACAddressSerializer, ModuleSerializer, VirtualDeviceContextSerializer from .manufacturers import ManufacturerSerializer from .nested import NestedInterfaceSerializer from .roles import InventoryItemRoleSerializer @@ -196,6 +196,8 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect required=False, many=True ) + qinq_svlan = VLANSerializer(nested=True, required=False, allow_null=True) + vlan_translation_policy = VLANTranslationPolicySerializer(nested=True, required=False, allow_null=True) vrf = VRFSerializer(nested=True, required=False, allow_null=True) l2vpn_termination = L2VPNTerminationSerializer(nested=True, read_only=True, allow_null=True) wireless_link = NestedWirelessLinkSerializer(read_only=True, allow_null=True) @@ -208,22 +210,21 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect ) count_ipaddresses = serializers.IntegerField(read_only=True) count_fhrp_groups = serializers.IntegerField(read_only=True) - mac_address = serializers.CharField( - required=False, - default=None, - allow_blank=True, - allow_null=True - ) + # Maintains backward compatibility with NetBox [ge,xe]-0/0/[0-9]). The token {module}, if present, will be " + "automatically replaced with the position value when creating a new module." + ) + class ConsolePortTemplateForm(ModularComponentTemplateForm): fieldsets = ( @@ -991,7 +1010,8 @@ class InterfaceTemplateForm(ModularComponentTemplateForm): class Meta: model = InterfaceTemplate fields = [ - 'device_type', 'module_type', 'name', 'label', 'type', 'mgmt_only', 'enabled', 'description', 'poe_mode', 'poe_type', 'bridge', 'rf_role', + 'device_type', 'module_type', 'name', 'label', 'type', 'mgmt_only', 'enabled', 'description', 'poe_mode', + 'poe_type', 'bridge', 'rf_role', ] @@ -1173,7 +1193,10 @@ class InventoryItemTemplateForm(ComponentTemplateForm): break elif component_type and component_id: # When adding the InventoryItem from a component page - if content_type := ContentType.objects.filter(MODULAR_COMPONENT_TEMPLATE_MODELS).filter(pk=component_type).first(): + content_type = ContentType.objects.filter( + MODULAR_COMPONENT_TEMPLATE_MODELS + ).filter(pk=component_type).first() + if content_type: if component := content_type.model_class().objects.filter(pk=component_id).first(): initial[content_type.model] = component @@ -1285,16 +1308,16 @@ class PowerOutletForm(ModularDeviceComponentForm): fieldsets = ( FieldSet( - 'device', 'module', 'name', 'label', 'type', 'color', 'power_port', 'feed_leg', 'mark_connected', 'description', - 'tags', + 'device', 'module', 'name', 'label', 'type', 'color', 'power_port', 'feed_leg', 'mark_connected', + 'description', 'tags', ), ) class Meta: model = PowerOutlet fields = [ - 'device', 'module', 'name', 'label', 'type', 'color', 'power_port', 'feed_leg', 'mark_connected', 'description', - 'tags', + 'device', 'module', 'name', 'label', 'type', 'color', 'power_port', 'feed_leg', 'mark_connected', + 'description', 'tags', ] @@ -1372,26 +1395,51 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm): 'available_on_device': '$device', } ) + qinq_svlan = DynamicModelChoiceField( + queryset=VLAN.objects.all(), + required=False, + label=_('Q-in-Q Service VLAN'), + query_params={ + 'group_id': '$vlan_group', + 'available_on_device': '$device', + 'qinq_role': VLANQinQRoleChoices.ROLE_SERVICE, + } + ) vrf = DynamicModelChoiceField( queryset=VRF.objects.all(), required=False, label=_('VRF') ) + primary_mac_address = DynamicModelChoiceField( + queryset=MACAddress.objects.all(), + label=_('Primary MAC address'), + required=False, + quick_add=True, + quick_add_params={'interface': '$pk'} + ) wwn = forms.CharField( empty_value=None, required=False, label=_('WWN') ) + vlan_translation_policy = DynamicModelChoiceField( + queryset=VLANTranslationPolicy.objects.all(), + required=False, + label=_('VLAN Translation Policy') + ) fieldsets = ( FieldSet( 'device', 'module', 'name', 'label', 'type', 'speed', 'duplex', 'description', 'tags', name=_('Interface') ), - FieldSet('vrf', 'mac_address', 'wwn', name=_('Addressing')), + FieldSet('vrf', 'primary_mac_address', 'wwn', name=_('Addressing')), FieldSet('vdcs', 'mtu', 'tx_power', 'enabled', 'mgmt_only', 'mark_connected', name=_('Operation')), FieldSet('parent', 'bridge', 'lag', name=_('Related Interfaces')), FieldSet('poe_mode', 'poe_type', name=_('PoE')), - FieldSet('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans', name=_('802.1Q Switching')), + FieldSet( + 'mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans', 'qinq_svlan', 'vlan_translation_policy', + name=_('802.1Q Switching') + ), FieldSet( 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'wireless_lan_group', 'wireless_lans', name=_('Wireless') @@ -1401,10 +1449,11 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm): class Meta: model = Interface fields = [ - 'device', 'module', 'vdcs', 'name', 'label', 'type', 'speed', 'duplex', 'enabled', 'parent', 'bridge', 'lag', - 'mac_address', 'wwn', 'mtu', 'mgmt_only', 'mark_connected', 'description', 'poe_mode', 'poe_type', 'mode', + 'device', 'module', 'vdcs', 'name', 'label', 'type', 'speed', 'duplex', 'enabled', 'parent', 'bridge', + 'lag', 'wwn', 'mtu', 'mgmt_only', 'mark_connected', 'description', 'poe_mode', 'poe_type', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'wireless_lans', - 'untagged_vlan', 'tagged_vlans', 'vrf', 'tags', + 'untagged_vlan', 'tagged_vlans', 'qinq_svlan', 'vlan_translation_policy', 'vrf', 'primary_mac_address', + 'tags', ] widgets = { 'speed': NumberWithOptions( @@ -1576,7 +1625,10 @@ class InventoryItemForm(DeviceComponentForm): ) fieldsets = ( - FieldSet('device', 'parent', 'name', 'label', 'status', 'role', 'description', 'tags', name=_('Inventory Item')), + FieldSet( + 'device', 'parent', 'name', 'label', 'status', 'role', 'description', 'tags', + name=_('Inventory Item') + ), FieldSet('manufacturer', 'part_id', 'serial', 'asset_tag', name=_('Hardware')), FieldSet( TabbedGroups( @@ -1698,3 +1750,78 @@ class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm): 'device', 'name', 'status', 'identifier', 'primary_ip4', 'primary_ip6', 'tenant_group', 'tenant', 'comments', 'tags' ] + + +# +# Addressing +# + +class MACAddressForm(NetBoxModelForm): + mac_address = forms.CharField( + required=True, + label=_('MAC address') + ) + interface = DynamicModelChoiceField( + label=_('Interface'), + queryset=Interface.objects.all(), + required=False, + context={ + 'parent': 'device', + }, + ) + vminterface = DynamicModelChoiceField( + label=_('VM Interface'), + queryset=VMInterface.objects.all(), + required=False, + context={ + 'parent': 'virtual_machine', + }, + ) + + fieldsets = ( + FieldSet( + 'mac_address', 'description', 'tags', + ), + FieldSet( + TabbedGroups( + FieldSet('interface', name=_('Device')), + FieldSet('vminterface', name=_('Virtual Machine')), + ), + ), + ) + + class Meta: + model = MACAddress + fields = [ + 'mac_address', 'interface', 'vminterface', 'description', 'tags', + ] + + def __init__(self, *args, **kwargs): + + # Initialize helper selectors + instance = kwargs.get('instance') + initial = kwargs.get('initial', {}).copy() + if instance: + if type(instance.assigned_object) is Interface: + initial['interface'] = instance.assigned_object + elif type(instance.assigned_object) is VMInterface: + initial['vminterface'] = instance.assigned_object + kwargs['initial'] = initial + + super().__init__(*args, **kwargs) + + def clean(self): + super().clean() + + # Handle object assignment + selected_objects = [ + field for field in ('interface', 'vminterface') if self.cleaned_data[field] + ] + if len(selected_objects) > 1: + raise forms.ValidationError({ + selected_objects[1]: _("A MAC address can only be assigned to a single object.") + }) + elif selected_objects: + self.instance.assigned_object = self.cleaned_data[selected_objects[0]] + else: + self.instance.assigned_object = None diff --git a/netbox/dcim/forms/object_create.py b/netbox/dcim/forms/object_create.py index d18c7ed14..6f6cd8f7c 100644 --- a/netbox/dcim/forms/object_create.py +++ b/netbox/dcim/forms/object_create.py @@ -243,14 +243,6 @@ class InterfaceCreateForm(ComponentCreateForm, model_forms.InterfaceForm): class Meta(model_forms.InterfaceForm.Meta): exclude = ('name', 'label') - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - if 'module' in self.fields: - self.fields['name'].help_text += _( - "The string {module} will be replaced with the position of the assigned module, if any." - ) - class FrontPortCreateForm(ComponentCreateForm, model_forms.FrontPortForm): device = DynamicModelChoiceField( @@ -424,7 +416,8 @@ class VirtualChassisCreateForm(NetBoxModelForm): class Meta: model = VirtualChassis fields = [ - 'name', 'domain', 'description', 'region', 'site_group', 'site', 'rack', 'members', 'initial_position', 'tags', + 'name', 'domain', 'description', 'region', 'site_group', 'site', 'rack', 'members', 'initial_position', + 'tags', ] def clean(self): diff --git a/netbox/dcim/forms/object_import.py b/netbox/dcim/forms/object_import.py index d46ef83ad..821f91402 100644 --- a/netbox/dcim/forms/object_import.py +++ b/netbox/dcim/forms/object_import.py @@ -136,7 +136,8 @@ class FrontPortTemplateImportForm(forms.ModelForm): class Meta: model = FrontPortTemplate fields = [ - 'device_type', 'module_type', 'name', 'type', 'color', 'rear_port', 'rear_port_position', 'label', 'description', + 'device_type', 'module_type', 'name', 'type', 'color', 'rear_port', 'rear_port_position', 'label', + 'description', ] diff --git a/netbox/dcim/graphql/filters.py b/netbox/dcim/graphql/filters.py index 8c256aecb..94f2c6d38 100644 --- a/netbox/dcim/graphql/filters.py +++ b/netbox/dcim/graphql/filters.py @@ -23,6 +23,7 @@ __all__ = ( 'InventoryItemFilter', 'InventoryItemRoleFilter', 'LocationFilter', + 'MACAddressFilter', 'ManufacturerFilter', 'ModuleFilter', 'ModuleBayFilter', @@ -133,6 +134,12 @@ class FrontPortTemplateFilter(BaseFilterMixin): pass +@strawberry_django.filter(models.MACAddress, lookups=True) +@autotype_decorator(filtersets.MACAddressFilterSet) +class MACAddressFilter(BaseFilterMixin): + pass + + @strawberry_django.filter(models.Interface, lookups=True) @autotype_decorator(filtersets.InterfaceFilterSet) class InterfaceFilter(BaseFilterMixin): diff --git a/netbox/dcim/graphql/schema.py b/netbox/dcim/graphql/schema.py index 65818fb20..011a2b58b 100644 --- a/netbox/dcim/graphql/schema.py +++ b/netbox/dcim/graphql/schema.py @@ -44,6 +44,9 @@ class DCIMQuery: front_port_template: FrontPortTemplateType = strawberry_django.field() front_port_template_list: List[FrontPortTemplateType] = strawberry_django.field() + mac_address: MACAddressType = strawberry_django.field() + mac_address_list: List[MACAddressType] = strawberry_django.field() + interface: InterfaceType = strawberry_django.field() interface_list: List[InterfaceType] = strawberry_django.field() diff --git a/netbox/dcim/graphql/types.py b/netbox/dcim/graphql/types.py index b951aead0..8d992176a 100644 --- a/netbox/dcim/graphql/types.py +++ b/netbox/dcim/graphql/types.py @@ -34,6 +34,7 @@ __all__ = ( 'InventoryItemRoleType', 'InventoryItemTemplateType', 'LocationType', + 'MACAddressType', 'ManufacturerType', 'ModularComponentType', 'ModuleType', @@ -76,7 +77,6 @@ class ComponentType( """ Base type for device/VM components """ - _name: str device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] @@ -93,7 +93,6 @@ class ComponentTemplateType( """ Base type for device/VM components """ - _name: str device_type: Annotated["DeviceTypeType", strawberry.lazy('dcim.graphql.types')] @@ -112,11 +111,11 @@ class ModularComponentTemplateType(ComponentTemplateType): @strawberry_django.type( models.CableTermination, - exclude=('termination_type', 'termination_id'), + exclude=('termination_type', 'termination_id', '_device', '_rack', '_location', '_site'), filters=CableTerminationFilter ) class CableTerminationType(NetBoxObjectType): - + cable: Annotated["CableType", strawberry.lazy('dcim.graphql.types')] | None termination: Annotated[Union[ Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')], Annotated["ConsolePortType", strawberry.lazy('dcim.graphql.types')], @@ -181,7 +180,7 @@ class ConsolePortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin filters=ConsolePortTemplateFilter ) class ConsolePortTemplateType(ModularComponentTemplateType): - _name: str + pass @strawberry_django.type( @@ -199,7 +198,7 @@ class ConsoleServerPortType(ModularComponentType, CabledObjectMixin, PathEndpoin filters=ConsoleServerPortTemplateFilter ) class ConsoleServerPortTemplateType(ModularComponentTemplateType): - _name: str + pass @strawberry_django.type( @@ -208,7 +207,6 @@ class ConsoleServerPortTemplateType(ModularComponentTemplateType): filters=DeviceFilter ) class DeviceType(ConfigContextMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType): - _name: str console_port_count: BigInt console_server_port_count: BigInt power_port_count: BigInt @@ -243,6 +241,7 @@ class DeviceType(ConfigContextMixin, ImageAttachmentsMixin, ContactsMixin, NetBo consoleserverports: List[Annotated["ConsoleServerPortType", strawberry.lazy('dcim.graphql.types')]] poweroutlets: List[Annotated["PowerOutletType", strawberry.lazy('dcim.graphql.types')]] frontports: List[Annotated["FrontPortType", strawberry.lazy('dcim.graphql.types')]] + devicebays: List[Annotated["DeviceBayType", strawberry.lazy('dcim.graphql.types')]] modulebays: List[Annotated["ModuleBayType", strawberry.lazy('dcim.graphql.types')]] services: List[Annotated["ServiceType", strawberry.lazy('ipam.graphql.types')]] inventoryitems: List[Annotated["InventoryItemType", strawberry.lazy('dcim.graphql.types')]] @@ -272,7 +271,7 @@ class DeviceBayType(ComponentType): filters=DeviceBayTemplateFilter ) class DeviceBayTemplateType(ComponentTemplateType): - _name: str + pass @strawberry_django.type( @@ -281,7 +280,6 @@ class DeviceBayTemplateType(ComponentTemplateType): filters=InventoryItemTemplateFilter ) class InventoryItemTemplateType(ComponentTemplateType): - _name: str role: Annotated["InventoryItemRoleType", strawberry.lazy('dcim.graphql.types')] | None manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')] @@ -365,18 +363,33 @@ class FrontPortType(ModularComponentType, CabledObjectMixin): filters=FrontPortTemplateFilter ) class FrontPortTemplateType(ModularComponentTemplateType): - _name: str color: str rear_port: Annotated["RearPortTemplateType", strawberry.lazy('dcim.graphql.types')] +@strawberry_django.type( + models.MACAddress, + exclude=('assigned_object_type', 'assigned_object_id'), + filters=MACAddressFilter +) +class MACAddressType(NetBoxObjectType): + mac_address: str + + @strawberry_django.field + def assigned_object(self) -> Annotated[Union[ + Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')], + Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')], + ], strawberry.union("MACAddressAssignmentType")] | None: + return self.assigned_object + + @strawberry_django.type( models.Interface, exclude=('_path',), filters=InterfaceFilter ) class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, PathEndpointMixin): - mac_address: str | None + _name: str wwn: str | None parent: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')] | None bridge: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')] | None @@ -384,6 +397,9 @@ class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, P wireless_link: Annotated["WirelessLinkType", strawberry.lazy('wireless.graphql.types')] | None untagged_vlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None + primary_mac_address: Annotated["MACAddressType", strawberry.lazy('dcim.graphql.types')] | None + qinq_svlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None + vlan_translation_policy: Annotated["VLANTranslationPolicyType", strawberry.lazy('ipam.graphql.types')] | None vdcs: List[Annotated["VirtualDeviceContextType", strawberry.lazy('dcim.graphql.types')]] tagged_vlans: List[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]] @@ -391,6 +407,7 @@ class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, P wireless_lans: List[Annotated["WirelessLANType", strawberry.lazy('wireless.graphql.types')]] member_interfaces: List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]] child_interfaces: List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]] + mac_addresses: List[Annotated["MACAddressType", strawberry.lazy('dcim.graphql.types')]] @strawberry_django.type( @@ -460,6 +477,16 @@ class LocationType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, Organi devices: List[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]] children: List[Annotated["LocationType", strawberry.lazy('dcim.graphql.types')]] + @strawberry_django.field + def clusters(self) -> List[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: + return self.cluster_set.all() + + @strawberry_django.field + def circuit_terminations(self) -> List[ + Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] + ]: + return self.circuit_terminations.all() + @strawberry_django.type( models.Manufacturer, @@ -516,7 +543,7 @@ class ModuleBayType(ModularComponentType): filters=ModuleBayTemplateFilter ) class ModuleBayTemplateType(ModularComponentTemplateType): - _name: str + pass @strawberry_django.type( @@ -577,7 +604,6 @@ class PowerOutletType(ModularComponentType, CabledObjectMixin, PathEndpointMixin filters=PowerOutletTemplateFilter ) class PowerOutletTemplateType(ModularComponentTemplateType): - _name: str power_port: Annotated["PowerPortTemplateType", strawberry.lazy('dcim.graphql.types')] | None @@ -609,8 +635,6 @@ class PowerPortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin): filters=PowerPortTemplateFilter ) class PowerPortTemplateType(ModularComponentTemplateType): - _name: str - poweroutlet_templates: List[Annotated["PowerOutletTemplateType", strawberry.lazy('dcim.graphql.types')]] @@ -629,7 +653,6 @@ class RackTypeType(NetBoxObjectType): filters=RackFilter ) class RackType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType): - _name: str site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] location: Annotated["LocationType", strawberry.lazy('dcim.graphql.types')] | None tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None @@ -682,7 +705,6 @@ class RearPortType(ModularComponentType, CabledObjectMixin): filters=RearPortTemplateFilter ) class RearPortTemplateType(ModularComponentTemplateType): - _name: str color: str frontport_templates: List[Annotated["FrontPortTemplateType", strawberry.lazy('dcim.graphql.types')]] @@ -703,6 +725,16 @@ class RegionType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType): def parent(self) -> Annotated["RegionType", strawberry.lazy('dcim.graphql.types')] | None: return self.parent + @strawberry_django.field + def clusters(self) -> List[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: + return self.cluster_set.all() + + @strawberry_django.field + def circuit_terminations(self) -> List[ + Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] + ]: + return self.circuit_terminations.all() + @strawberry_django.type( models.Site, @@ -710,7 +742,6 @@ class RegionType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType): filters=SiteFilter ) class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType): - _name: str time_zone: str | None region: Annotated["RegionType", strawberry.lazy('dcim.graphql.types')] | None group: Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')] | None @@ -728,6 +759,16 @@ class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObje clusters: List[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]] vlans: List[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]] + @strawberry_django.field + def clusters(self) -> List[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: + return self.cluster_set.all() + + @strawberry_django.field + def circuit_terminations(self) -> List[ + Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] + ]: + return self.circuit_terminations.all() + @strawberry_django.type( models.SiteGroup, @@ -744,6 +785,16 @@ class SiteGroupType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType): def parent(self) -> Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')] | None: return self.parent + @strawberry_django.field + def clusters(self) -> List[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]: + return self.cluster_set.all() + + @strawberry_django.field + def circuit_terminations(self) -> List[ + Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')] + ]: + return self.circuit_terminations.all() + @strawberry_django.type( models.VirtualChassis, diff --git a/netbox/dcim/management/commands/buildschema.py b/netbox/dcim/management/commands/buildschema.py index 44a0e95f2..529a2462c 100644 --- a/netbox/dcim/management/commands/buildschema.py +++ b/netbox/dcim/management/commands/buildschema.py @@ -6,6 +6,7 @@ from django.core.management.base import BaseCommand from jinja2 import FileSystemLoader, Environment from dcim.choices import * +from netbox.choices import WeightUnitChoices TEMPLATE_FILENAME = 'devicetype_schema.jinja2' OUTPUT_FILENAME = 'contrib/generated_schema.json' diff --git a/netbox/dcim/migrations/0001_squashed.py b/netbox/dcim/migrations/0001_squashed.py index cf0ef4816..f08fe1d70 100644 --- a/netbox/dcim/migrations/0001_squashed.py +++ b/netbox/dcim/migrations/0001_squashed.py @@ -13,11 +13,9 @@ import utilities.validators class Migration(migrations.Migration): - initial = True - dependencies = [ - ] + dependencies = [] replaces = [ ('dcim', '0001_initial'), @@ -64,7 +62,12 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('_cable_peer_id', models.PositiveIntegerField(blank=True, null=True)), @@ -83,7 +86,12 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('type', models.CharField(blank=True, max_length=50)), @@ -100,7 +108,12 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('_cable_peer_id', models.PositiveIntegerField(blank=True, null=True)), @@ -119,7 +132,12 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('type', models.CharField(blank=True, max_length=50)), @@ -137,14 +155,34 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(primary_key=True, serialize=False)), ('local_context_data', models.JSONField(blank=True, null=True)), ('name', models.CharField(blank=True, max_length=64, null=True)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize, null=True)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize, null=True + ), + ), ('serial', models.CharField(blank=True, max_length=50)), ('asset_tag', models.CharField(blank=True, max_length=50, null=True, unique=True)), - ('position', models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)])), + ( + 'position', + models.PositiveSmallIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), + ), ('face', models.CharField(blank=True, max_length=50)), ('status', models.CharField(default='active', max_length=50)), - ('vc_position', models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(255)])), - ('vc_priority', models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(255)])), + ( + 'vc_position', + models.PositiveSmallIntegerField( + blank=True, null=True, validators=[django.core.validators.MaxValueValidator(255)] + ), + ), + ( + 'vc_priority', + models.PositiveSmallIntegerField( + blank=True, null=True, validators=[django.core.validators.MaxValueValidator(255)] + ), + ), ('comments', models.TextField(blank=True)), ], options={ @@ -159,7 +197,12 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ], @@ -174,7 +217,12 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ], @@ -228,13 +276,27 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('_cable_peer_id', models.PositiveIntegerField(blank=True, null=True)), ('mark_connected', models.BooleanField(default=False)), ('type', models.CharField(max_length=50)), - ('rear_port_position', models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(1024)])), + ( + 'rear_port_position', + models.PositiveSmallIntegerField( + default=1, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(1024), + ], + ), + ), ], options={ 'ordering': ('device', '_name'), @@ -247,11 +309,25 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('type', models.CharField(max_length=50)), - ('rear_port_position', models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(1024)])), + ( + 'rear_port_position', + models.PositiveSmallIntegerField( + default=1, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(1024), + ], + ), + ), ], options={ 'ordering': ('device_type', '_name'), @@ -271,9 +347,24 @@ class Migration(migrations.Migration): ('mark_connected', models.BooleanField(default=False)), ('enabled', models.BooleanField(default=True)), ('mac_address', dcim.fields.MACAddressField(blank=True, null=True)), - ('mtu', models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65536)])), + ( + 'mtu', + models.PositiveIntegerField( + blank=True, + null=True, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(65536), + ], + ), + ), ('mode', models.CharField(blank=True, max_length=50)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize_interface)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize_interface + ), + ), ('type', models.CharField(max_length=50)), ('mgmt_only', models.BooleanField(default=False)), ], @@ -290,7 +381,12 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=64)), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize_interface)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize_interface + ), + ), ('type', models.CharField(max_length=50)), ('mgmt_only', models.BooleanField(default=False)), ], @@ -306,7 +402,12 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('part_id', models.CharField(blank=True, max_length=50)), @@ -388,8 +489,19 @@ class Migration(migrations.Migration): ('supply', models.CharField(default='ac', max_length=50)), ('phase', models.CharField(default='single-phase', max_length=50)), ('voltage', models.SmallIntegerField(validators=[utilities.validators.ExclusionValidator([0])])), - ('amperage', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(1)])), - ('max_utilization', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)])), + ( + 'amperage', + models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(1)]), + ), + ( + 'max_utilization', + models.PositiveSmallIntegerField( + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(100), + ] + ), + ), ('available_power', models.PositiveIntegerField(default=0, editable=False)), ('comments', models.TextField(blank=True)), ], @@ -405,7 +517,12 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('_cable_peer_id', models.PositiveIntegerField(blank=True, null=True)), @@ -424,7 +541,12 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('type', models.CharField(blank=True, max_length=50)), @@ -455,14 +577,29 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('_cable_peer_id', models.PositiveIntegerField(blank=True, null=True)), ('mark_connected', models.BooleanField(default=False)), ('type', models.CharField(blank=True, max_length=50)), - ('maximum_draw', models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)])), - ('allocated_draw', models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)])), + ( + 'maximum_draw', + models.PositiveSmallIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), + ), + ( + 'allocated_draw', + models.PositiveSmallIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), + ), ], options={ 'ordering': ('device', '_name'), @@ -475,12 +612,27 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('type', models.CharField(blank=True, max_length=50)), - ('maximum_draw', models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)])), - ('allocated_draw', models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)])), + ( + 'maximum_draw', + models.PositiveSmallIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), + ), + ( + 'allocated_draw', + models.PositiveSmallIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), + ), ], options={ 'ordering': ('device_type', '_name'), @@ -494,14 +646,28 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=100)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('facility_id', models.CharField(blank=True, max_length=50, null=True)), ('status', models.CharField(default='active', max_length=50)), ('serial', models.CharField(blank=True, max_length=50)), ('asset_tag', models.CharField(blank=True, max_length=50, null=True, unique=True)), ('type', models.CharField(blank=True, max_length=50)), ('width', models.PositiveSmallIntegerField(default=19)), - ('u_height', models.PositiveSmallIntegerField(default=42, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)])), + ( + 'u_height', + models.PositiveSmallIntegerField( + default=42, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(100), + ], + ), + ), ('desc_units', models.BooleanField(default=False)), ('outer_width', models.PositiveSmallIntegerField(blank=True, null=True)), ('outer_depth', models.PositiveSmallIntegerField(blank=True, null=True)), @@ -519,7 +685,10 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), - ('units', django.contrib.postgres.fields.ArrayField(base_field=models.PositiveSmallIntegerField(), size=None)), + ( + 'units', + django.contrib.postgres.fields.ArrayField(base_field=models.PositiveSmallIntegerField(), size=None), + ), ('description', models.CharField(max_length=200)), ], options={ @@ -550,13 +719,27 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('_cable_peer_id', models.PositiveIntegerField(blank=True, null=True)), ('mark_connected', models.BooleanField(default=False)), ('type', models.CharField(max_length=50)), - ('positions', models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(1024)])), + ( + 'positions', + models.PositiveSmallIntegerField( + default=1, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(1024), + ], + ), + ), ], options={ 'ordering': ('device', '_name'), @@ -569,11 +752,25 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('type', models.CharField(max_length=50)), - ('positions', models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(1024)])), + ( + 'positions', + models.PositiveSmallIntegerField( + default=1, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(1024), + ], + ), + ), ], options={ 'ordering': ('device_type', '_name'), @@ -606,7 +803,12 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=100, unique=True)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('slug', models.SlugField(max_length=100, unique=True)), ('status', models.CharField(default='active', max_length=50)), ('facility', models.CharField(blank=True, max_length=50)), @@ -654,7 +856,16 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), ('domain', models.CharField(blank=True, max_length=30)), - ('master', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vc_master_for', to='dcim.device')), + ( + 'master', + models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='vc_master_for', + to='dcim.device', + ), + ), ], options={ 'verbose_name_plural': 'virtual chassis', diff --git a/netbox/dcim/migrations/0002_squashed.py b/netbox/dcim/migrations/0002_squashed.py index 786167680..2e830560f 100644 --- a/netbox/dcim/migrations/0002_squashed.py +++ b/netbox/dcim/migrations/0002_squashed.py @@ -6,7 +6,6 @@ import taggit.managers class Migration(migrations.Migration): - dependencies = [ ('dcim', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), @@ -28,17 +27,35 @@ class Migration(migrations.Migration): migrations.AddField( model_name='sitegroup', name='parent', - field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='dcim.sitegroup'), + field=mptt.fields.TreeForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='children', + to='dcim.sitegroup', + ), ), migrations.AddField( model_name='site', name='group', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sites', to='dcim.sitegroup'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='sites', + to='dcim.sitegroup', + ), ), migrations.AddField( model_name='site', name='region', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sites', to='dcim.region'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='sites', + to='dcim.region', + ), ), migrations.AddField( model_name='site', @@ -48,32 +65,56 @@ class Migration(migrations.Migration): migrations.AddField( model_name='site', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='sites', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='sites', + to='tenancy.tenant', + ), ), migrations.AddField( model_name='region', name='parent', - field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='dcim.region'), + field=mptt.fields.TreeForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='children', + to='dcim.region', + ), ), migrations.AddField( model_name='rearporttemplate', name='device_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype' + ), ), migrations.AddField( model_name='rearport', name='_cable_peer_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='rearport', name='cable', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable' + ), ), migrations.AddField( model_name='rearport', name='device', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device' + ), ), migrations.AddField( model_name='rearport', @@ -83,7 +124,9 @@ class Migration(migrations.Migration): migrations.AddField( model_name='rackreservation', name='rack', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reservations', to='dcim.rack'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='reservations', to='dcim.rack' + ), ), migrations.AddField( model_name='rackreservation', @@ -93,7 +136,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='rackreservation', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='rackreservations', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='rackreservations', + to='tenancy.tenant', + ), ), migrations.AddField( model_name='rackreservation', @@ -103,12 +152,24 @@ class Migration(migrations.Migration): migrations.AddField( model_name='rack', name='location', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='racks', to='dcim.location'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='racks', + to='dcim.location', + ), ), migrations.AddField( model_name='rack', name='role', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='racks', to='dcim.rackrole'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='racks', + to='dcim.rackrole', + ), ), migrations.AddField( model_name='rack', @@ -123,32 +184,52 @@ class Migration(migrations.Migration): migrations.AddField( model_name='rack', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='racks', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='racks', + to='tenancy.tenant', + ), ), migrations.AddField( model_name='powerporttemplate', name='device_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype' + ), ), migrations.AddField( model_name='powerport', name='_cable_peer_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='powerport', name='_path', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath' + ), ), migrations.AddField( model_name='powerport', name='cable', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable' + ), ), migrations.AddField( model_name='powerport', name='device', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device' + ), ), migrations.AddField( model_name='powerport', @@ -158,7 +239,9 @@ class Migration(migrations.Migration): migrations.AddField( model_name='powerpanel', name='location', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='dcim.location'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='dcim.location' + ), ), migrations.AddField( model_name='powerpanel', @@ -173,37 +256,63 @@ class Migration(migrations.Migration): migrations.AddField( model_name='poweroutlettemplate', name='device_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype' + ), ), migrations.AddField( model_name='poweroutlettemplate', name='power_port', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='poweroutlet_templates', to='dcim.powerporttemplate'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='poweroutlet_templates', + to='dcim.powerporttemplate', + ), ), migrations.AddField( model_name='poweroutlet', name='_cable_peer_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='poweroutlet', name='_path', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath' + ), ), migrations.AddField( model_name='poweroutlet', name='cable', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable' + ), ), migrations.AddField( model_name='poweroutlet', name='device', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device' + ), ), migrations.AddField( model_name='poweroutlet', name='power_port', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='poweroutlets', to='dcim.powerport'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='poweroutlets', + to='dcim.powerport', + ), ), migrations.AddField( model_name='poweroutlet', @@ -213,27 +322,45 @@ class Migration(migrations.Migration): migrations.AddField( model_name='powerfeed', name='_cable_peer_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='powerfeed', name='_path', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath' + ), ), migrations.AddField( model_name='powerfeed', name='cable', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable' + ), ), migrations.AddField( model_name='powerfeed', name='power_panel', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='powerfeeds', to='dcim.powerpanel'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='powerfeeds', to='dcim.powerpanel' + ), ), migrations.AddField( model_name='powerfeed', name='rack', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='powerfeeds', to='dcim.rack'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='powerfeeds', + to='dcim.rack', + ), ), migrations.AddField( model_name='powerfeed', @@ -243,32 +370,60 @@ class Migration(migrations.Migration): migrations.AddField( model_name='platform', name='manufacturer', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='platforms', to='dcim.manufacturer'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='platforms', + to='dcim.manufacturer', + ), ), migrations.AddField( model_name='location', name='parent', - field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='dcim.location'), + field=mptt.fields.TreeForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='children', + to='dcim.location', + ), ), migrations.AddField( model_name='location', name='site', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='locations', to='dcim.site'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='locations', to='dcim.site' + ), ), migrations.AddField( model_name='inventoryitem', name='device', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device' + ), ), migrations.AddField( model_name='inventoryitem', name='manufacturer', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_items', to='dcim.manufacturer'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='inventory_items', + to='dcim.manufacturer', + ), ), migrations.AddField( model_name='inventoryitem', name='parent', - field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child_items', to='dcim.inventoryitem'), + field=mptt.fields.TreeForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='child_items', + to='dcim.inventoryitem', + ), ), migrations.AddField( model_name='inventoryitem', @@ -278,36 +433,62 @@ class Migration(migrations.Migration): migrations.AddField( model_name='interfacetemplate', name='device_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype' + ), ), migrations.AddField( model_name='interface', name='_cable_peer_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='interface', name='_path', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath' + ), ), migrations.AddField( model_name='interface', name='cable', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable' + ), ), migrations.AddField( model_name='interface', name='device', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device' + ), ), migrations.AddField( model_name='interface', name='lag', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='member_interfaces', to='dcim.interface'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='member_interfaces', + to='dcim.interface', + ), ), migrations.AddField( model_name='interface', name='parent', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='child_interfaces', to='dcim.interface'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='child_interfaces', + to='dcim.interface', + ), ), ] diff --git a/netbox/dcim/migrations/0003_squashed_0130.py b/netbox/dcim/migrations/0003_squashed_0130.py index 592aaf9a8..0248d9ba1 100644 --- a/netbox/dcim/migrations/0003_squashed_0130.py +++ b/netbox/dcim/migrations/0003_squashed_0130.py @@ -4,7 +4,6 @@ import taggit.managers class Migration(migrations.Migration): - dependencies = [ ('dcim', '0002_auto_20160622_1821'), ('virtualization', '0001_virtualization'), @@ -160,37 +159,61 @@ class Migration(migrations.Migration): migrations.AddField( model_name='interface', name='untagged_vlan', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='interfaces_as_untagged', to='ipam.vlan'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='interfaces_as_untagged', + to='ipam.vlan', + ), ), migrations.AddField( model_name='frontporttemplate', name='device_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype' + ), ), migrations.AddField( model_name='frontporttemplate', name='rear_port', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frontport_templates', to='dcim.rearporttemplate'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name='frontport_templates', + to='dcim.rearporttemplate', + ), ), migrations.AddField( model_name='frontport', name='_cable_peer_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='frontport', name='cable', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable' + ), ), migrations.AddField( model_name='frontport', name='device', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device' + ), ), migrations.AddField( model_name='frontport', name='rear_port', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frontports', to='dcim.rearport'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='frontports', to='dcim.rearport' + ), ), migrations.AddField( model_name='frontport', @@ -200,7 +223,9 @@ class Migration(migrations.Migration): migrations.AddField( model_name='devicetype', name='manufacturer', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='device_types', to='dcim.manufacturer'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='device_types', to='dcim.manufacturer' + ), ), migrations.AddField( model_name='devicetype', @@ -210,17 +235,27 @@ class Migration(migrations.Migration): migrations.AddField( model_name='devicebaytemplate', name='device_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype' + ), ), migrations.AddField( model_name='devicebay', name='device', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device' + ), ), migrations.AddField( model_name='devicebay', name='installed_device', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='parent_bay', to='dcim.device'), + field=models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='parent_bay', + to='dcim.device', + ), ), migrations.AddField( model_name='devicebay', @@ -230,47 +265,89 @@ class Migration(migrations.Migration): migrations.AddField( model_name='device', name='cluster', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='devices', to='virtualization.cluster'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='devices', + to='virtualization.cluster', + ), ), migrations.AddField( model_name='device', name='device_role', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='dcim.devicerole'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='dcim.devicerole' + ), ), migrations.AddField( model_name='device', name='device_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='instances', to='dcim.devicetype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='instances', to='dcim.devicetype' + ), ), migrations.AddField( model_name='device', name='location', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='dcim.location'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='devices', + to='dcim.location', + ), ), migrations.AddField( model_name='device', name='platform', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='devices', to='dcim.platform'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='devices', + to='dcim.platform', + ), ), migrations.AddField( model_name='device', name='primary_ip4', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='primary_ip4_for', to='ipam.ipaddress'), + field=models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='primary_ip4_for', + to='ipam.ipaddress', + ), ), migrations.AddField( model_name='device', name='primary_ip6', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='primary_ip6_for', to='ipam.ipaddress'), + field=models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='primary_ip6_for', + to='ipam.ipaddress', + ), ), migrations.AddField( model_name='device', name='rack', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='dcim.rack'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='devices', + to='dcim.rack', + ), ), migrations.AddField( model_name='device', name='site', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='dcim.site'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='dcim.site' + ), ), migrations.AddField( model_name='device', @@ -280,37 +357,63 @@ class Migration(migrations.Migration): migrations.AddField( model_name='device', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='devices', + to='tenancy.tenant', + ), ), migrations.AddField( model_name='device', name='virtual_chassis', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='members', to='dcim.virtualchassis'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='members', + to='dcim.virtualchassis', + ), ), migrations.AddField( model_name='consoleserverporttemplate', name='device_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype' + ), ), migrations.AddField( model_name='consoleserverport', name='_cable_peer_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='consoleserverport', name='_path', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath' + ), ), migrations.AddField( model_name='consoleserverport', name='cable', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable' + ), ), migrations.AddField( model_name='consoleserverport', name='device', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device' + ), ), migrations.AddField( model_name='consoleserverport', @@ -320,27 +423,41 @@ class Migration(migrations.Migration): migrations.AddField( model_name='consoleporttemplate', name='device_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype' + ), ), migrations.AddField( model_name='consoleport', name='_cable_peer_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='consoleport', name='_path', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath' + ), ), migrations.AddField( model_name='consoleport', name='cable', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.cable' + ), ), migrations.AddField( model_name='consoleport', name='device', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device' + ), ), migrations.AddField( model_name='consoleport', @@ -350,22 +467,34 @@ class Migration(migrations.Migration): migrations.AddField( model_name='cablepath', name='destination_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='cablepath', name='origin_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype' + ), ), migrations.AddField( model_name='cable', name='_termination_a_device', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.device'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.device' + ), ), migrations.AddField( model_name='cable', name='_termination_b_device', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.device'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.device' + ), ), migrations.AddField( model_name='cable', @@ -375,12 +504,64 @@ class Migration(migrations.Migration): migrations.AddField( model_name='cable', name='termination_a_type', - field=models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'circuits'), ('model__in', ('circuittermination',))), models.Q(('app_label', 'dcim'), ('model__in', ('consoleport', 'consoleserverport', 'frontport', 'interface', 'powerfeed', 'poweroutlet', 'powerport', 'rearport'))), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + limit_choices_to=models.Q( + models.Q( + models.Q(('app_label', 'circuits'), ('model__in', ('circuittermination',))), + models.Q( + ('app_label', 'dcim'), + ( + 'model__in', + ( + 'consoleport', + 'consoleserverport', + 'frontport', + 'interface', + 'powerfeed', + 'poweroutlet', + 'powerport', + 'rearport', + ), + ), + ), + _connector='OR', + ) + ), + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='cable', name='termination_b_type', - field=models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'circuits'), ('model__in', ('circuittermination',))), models.Q(('app_label', 'dcim'), ('model__in', ('consoleport', 'consoleserverport', 'frontport', 'interface', 'powerfeed', 'poweroutlet', 'powerport', 'rearport'))), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + limit_choices_to=models.Q( + models.Q( + models.Q(('app_label', 'circuits'), ('model__in', ('circuittermination',))), + models.Q( + ('app_label', 'dcim'), + ( + 'model__in', + ( + 'consoleport', + 'consoleserverport', + 'frontport', + 'interface', + 'powerfeed', + 'poweroutlet', + 'powerport', + 'rearport', + ), + ), + ), + _connector='OR', + ) + ), + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AlterUniqueTogether( name='rearporttemplate', @@ -456,7 +637,11 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='device', - unique_together={('rack', 'position', 'face'), ('virtual_chassis', 'vc_position'), ('site', 'tenant', 'name')}, + unique_together={ + ('rack', 'position', 'face'), + ('virtual_chassis', 'vc_position'), + ('site', 'tenant', 'name'), + }, ), migrations.AlterUniqueTogether( name='consoleserverporttemplate', diff --git a/netbox/dcim/migrations/0131_squashed_0159.py b/netbox/dcim/migrations/0131_squashed_0159.py index f7e7cfdb2..3866e8cc8 100644 --- a/netbox/dcim/migrations/0131_squashed_0159.py +++ b/netbox/dcim/migrations/0131_squashed_0159.py @@ -10,7 +10,6 @@ import utilities.ordering class Migration(migrations.Migration): - replaces = [ ('dcim', '0131_consoleport_speed'), ('dcim', '0132_cable_length'), @@ -40,7 +39,7 @@ class Migration(migrations.Migration): ('dcim', '0156_location_status'), ('dcim', '0157_new_cabling_models'), ('dcim', '0158_populate_cable_terminations'), - ('dcim', '0159_populate_cable_paths') + ('dcim', '0159_populate_cable_paths'), ] dependencies = [ @@ -96,17 +95,35 @@ class Migration(migrations.Migration): migrations.AddField( model_name='interface', name='bridge', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bridge_interfaces', to='dcim.interface'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='bridge_interfaces', + to='dcim.interface', + ), ), migrations.AddField( model_name='location', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='locations', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='locations', + to='tenancy.tenant', + ), ), migrations.AddField( model_name='cable', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='cables', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='cables', + to='tenancy.tenant', + ), ), migrations.AddField( model_name='devicetype', @@ -148,7 +165,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='location', - constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('site', 'name'), name='dcim_location_name'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent', None)), fields=('site', 'name'), name='dcim_location_name' + ), ), migrations.AddConstraint( model_name='location', @@ -156,7 +175,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='location', - constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('site', 'slug'), name='dcim_location_slug'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent', None)), fields=('site', 'slug'), name='dcim_location_slug' + ), ), migrations.AddConstraint( model_name='region', @@ -164,7 +185,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='region', - constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('name',), name='dcim_region_name'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent', None)), fields=('name',), name='dcim_region_name' + ), ), migrations.AddConstraint( model_name='region', @@ -172,7 +195,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='region', - constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('slug',), name='dcim_region_slug'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent', None)), fields=('slug',), name='dcim_region_slug' + ), ), migrations.AddConstraint( model_name='sitegroup', @@ -180,7 +205,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='sitegroup', - constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('name',), name='dcim_sitegroup_name'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent', None)), fields=('name',), name='dcim_sitegroup_name' + ), ), migrations.AddConstraint( model_name='sitegroup', @@ -188,7 +215,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='sitegroup', - constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('slug',), name='dcim_sitegroup_slug'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent', None)), fields=('slug',), name='dcim_sitegroup_slug' + ), ), migrations.AddField( model_name='devicerole', @@ -328,7 +357,9 @@ class Migration(migrations.Migration): migrations.AddField( model_name='interface', name='tx_power', - field=models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(127)]), + field=models.PositiveSmallIntegerField( + blank=True, null=True, validators=[django.core.validators.MaxValueValidator(127)] + ), ), migrations.AddField( model_name='interface', @@ -338,7 +369,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='interface', name='wireless_link', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wireless.wirelesslink'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='wireless.wirelesslink', + ), ), migrations.AddField( model_name='site', @@ -348,12 +385,24 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='device', name='primary_ip4', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress'), + field=models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='ipam.ipaddress', + ), ), migrations.AlterField( model_name='device', name='primary_ip6', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress'), + field=models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='ipam.ipaddress', + ), ), migrations.RemoveField( model_name='site', @@ -372,7 +421,23 @@ class Migration(migrations.Migration): name='contact_phone', ), migrations.RunSQL( - sql="\n DO $$\n DECLARE\n idx record;\n BEGIN\n FOR idx IN\n SELECT indexname AS old_name,\n replace(indexname, 'module', 'inventoryitem') AS new_name\n FROM pg_indexes\n WHERE schemaname = 'public' AND\n tablename = 'dcim_inventoryitem' AND\n indexname LIKE 'dcim_module_%'\n LOOP\n EXECUTE format(\n 'ALTER INDEX %I RENAME TO %I;',\n idx.old_name,\n idx.new_name\n );\n END LOOP;\n END$$;\n ", + sql="""DO $$ + DECLARE idx record; + BEGIN + FOR idx IN + SELECT indexname AS old_name, replace(indexname, 'module', 'inventoryitem') AS new_name + FROM pg_indexes + WHERE schemaname = 'public' AND + tablename = 'dcim_inventoryitem' AND + indexname LIKE 'dcim_module_%' + LOOP + EXECUTE format( + 'ALTER INDEX %I RENAME TO %I;', + idx.old_name, + idx.new_name + ); + END LOOP; + END$$;""", ), migrations.AlterModelOptions( name='consoleporttemplate', @@ -405,49 +470,99 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='consoleporttemplate', name='device_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.devicetype', + ), ), migrations.AlterField( model_name='consoleserverporttemplate', name='device_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.devicetype', + ), ), migrations.AlterField( model_name='frontporttemplate', name='device_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.devicetype', + ), ), migrations.AlterField( model_name='interfacetemplate', name='device_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.devicetype', + ), ), migrations.AlterField( model_name='poweroutlettemplate', name='device_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.devicetype', + ), ), migrations.AlterField( model_name='powerporttemplate', name='device_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.devicetype', + ), ), migrations.AlterField( model_name='rearporttemplate', name='device_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.devicetype', + ), ), migrations.CreateModel( name='ModuleType', fields=[ ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('model', models.CharField(max_length=100)), ('part_number', models.CharField(blank=True, max_length=50)), ('comments', models.TextField(blank=True)), - ('manufacturer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='module_types', to='dcim.manufacturer')), + ( + 'manufacturer', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='module_types', to='dcim.manufacturer' + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], options={ @@ -460,14 +575,27 @@ class Migration(migrations.Migration): fields=[ ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('position', models.CharField(blank=True, max_length=30)), ('description', models.CharField(blank=True, max_length=200)), - ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device')), + ( + 'device', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device' + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], options={ @@ -480,15 +608,35 @@ class Migration(migrations.Migration): fields=[ ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('local_context_data', models.JSONField(blank=True, null=True)), ('serial', models.CharField(blank=True, max_length=50)), ('asset_tag', models.CharField(blank=True, max_length=50, null=True, unique=True)), ('comments', models.TextField(blank=True)), - ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='modules', to='dcim.device')), - ('module_bay', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='installed_module', to='dcim.modulebay')), - ('module_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='instances', to='dcim.moduletype')), + ( + 'device', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='modules', to='dcim.device' + ), + ), + ( + 'module_bay', + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + related_name='installed_module', + to='dcim.modulebay', + ), + ), + ( + 'module_type', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='instances', to='dcim.moduletype' + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], options={ @@ -498,72 +646,156 @@ class Migration(migrations.Migration): migrations.AddField( model_name='consoleport', name='module', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.module', + ), ), migrations.AddField( model_name='consoleporttemplate', name='module_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.moduletype', + ), ), migrations.AddField( model_name='consoleserverport', name='module', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.module', + ), ), migrations.AddField( model_name='consoleserverporttemplate', name='module_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.moduletype', + ), ), migrations.AddField( model_name='frontport', name='module', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.module', + ), ), migrations.AddField( model_name='frontporttemplate', name='module_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.moduletype', + ), ), migrations.AddField( model_name='interface', name='module', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.module', + ), ), migrations.AddField( model_name='interfacetemplate', name='module_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.moduletype', + ), ), migrations.AddField( model_name='poweroutlet', name='module', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.module', + ), ), migrations.AddField( model_name='poweroutlettemplate', name='module_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.moduletype', + ), ), migrations.AddField( model_name='powerport', name='module', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.module', + ), ), migrations.AddField( model_name='powerporttemplate', name='module_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.moduletype', + ), ), migrations.AddField( model_name='rearport', name='module', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.module', + ), ), migrations.AddField( model_name='rearporttemplate', name='module_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.moduletype', + ), ), migrations.AlterUniqueTogether( name='consoleporttemplate', @@ -598,7 +830,10 @@ class Migration(migrations.Migration): fields=[ ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('name', models.CharField(max_length=100, unique=True)), ('slug', models.SlugField(max_length=100, unique=True)), @@ -613,7 +848,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='inventoryitem', name='role', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_items', to='dcim.inventoryitemrole'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='inventory_items', + to='dcim.inventoryitemrole', + ), ), migrations.AddField( model_name='inventoryitem', @@ -623,12 +864,39 @@ class Migration(migrations.Migration): migrations.AddField( model_name='inventoryitem', name='component_type', - field=models.ForeignKey(blank=True, limit_choices_to=models.Q(('app_label', 'dcim'), ('model__in', ('consoleport', 'consoleserverport', 'frontport', 'interface', 'poweroutlet', 'powerport', 'rearport'))), null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + limit_choices_to=models.Q( + ('app_label', 'dcim'), + ( + 'model__in', + ( + 'consoleport', + 'consoleserverport', + 'frontport', + 'interface', + 'poweroutlet', + 'powerport', + 'rearport', + ), + ), + ), + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='interface', name='vrf', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='interfaces', to='ipam.vrf'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='interfaces', + to='ipam.vrf', + ), ), migrations.AddField( model_name='interface', @@ -952,7 +1220,12 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('description', models.CharField(blank=True, max_length=200)), ('component_id', models.PositiveBigIntegerField(blank=True, null=True)), @@ -961,11 +1234,67 @@ class Migration(migrations.Migration): ('rght', models.PositiveIntegerField(editable=False)), ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), ('level', models.PositiveIntegerField(editable=False)), - ('component_type', models.ForeignKey(blank=True, limit_choices_to=models.Q(('app_label', 'dcim'), ('model__in', ('consoleporttemplate', 'consoleserverporttemplate', 'frontporttemplate', 'interfacetemplate', 'poweroutlettemplate', 'powerporttemplate', 'rearporttemplate'))), null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')), - ('device_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype')), - ('manufacturer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_item_templates', to='dcim.manufacturer')), - ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child_items', to='dcim.inventoryitemtemplate')), - ('role', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_item_templates', to='dcim.inventoryitemrole')), + ( + 'component_type', + models.ForeignKey( + blank=True, + limit_choices_to=models.Q( + ('app_label', 'dcim'), + ( + 'model__in', + ( + 'consoleporttemplate', + 'consoleserverporttemplate', + 'frontporttemplate', + 'interfacetemplate', + 'poweroutlettemplate', + 'powerporttemplate', + 'rearporttemplate', + ), + ), + ), + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), + ), + ( + 'device_type', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype' + ), + ), + ( + 'manufacturer', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='inventory_item_templates', + to='dcim.manufacturer', + ), + ), + ( + 'parent', + mptt.fields.TreeForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='child_items', + to='dcim.inventoryitemtemplate', + ), + ), + ( + 'role', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='inventory_item_templates', + to='dcim.inventoryitemrole', + ), + ), ], options={ 'ordering': ('device_type__id', 'parent__id', '_name'), @@ -989,11 +1318,21 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('name', models.CharField(max_length=64)), - ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)), + ( + '_name', + utilities.fields.NaturalOrderingField( + 'name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize + ), + ), ('label', models.CharField(blank=True, max_length=64)), ('position', models.CharField(blank=True, max_length=30)), ('description', models.CharField(blank=True, max_length=200)), - ('device_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype')), + ( + 'device_type', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype' + ), + ), ], options={ 'ordering': ('device_type', '_name'), @@ -1088,7 +1427,16 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='device', name='position', - field=models.DecimalField(blank=True, decimal_places=1, max_digits=4, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100.5)]), + field=models.DecimalField( + blank=True, + decimal_places=1, + max_digits=4, + null=True, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(100.5), + ], + ), ), migrations.AddField( model_name='interface', @@ -1121,12 +1469,66 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('cable_end', models.CharField(max_length=1)), ('termination_id', models.PositiveBigIntegerField()), - ('cable', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='terminations', to='dcim.cable')), - ('termination_type', models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'circuits'), ('model__in', ('circuittermination',))), models.Q(('app_label', 'dcim'), ('model__in', ('consoleport', 'consoleserverport', 'frontport', 'interface', 'powerfeed', 'poweroutlet', 'powerport', 'rearport'))), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')), - ('_device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.device')), - ('_rack', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.rack')), - ('_location', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.location')), - ('_site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.site')), + ( + 'cable', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='terminations', to='dcim.cable' + ), + ), + ( + 'termination_type', + models.ForeignKey( + limit_choices_to=models.Q( + models.Q( + models.Q(('app_label', 'circuits'), ('model__in', ('circuittermination',))), + models.Q( + ('app_label', 'dcim'), + ( + 'model__in', + ( + 'consoleport', + 'consoleserverport', + 'frontport', + 'interface', + 'powerfeed', + 'poweroutlet', + 'powerport', + 'rearport', + ), + ), + ), + _connector='OR', + ) + ), + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), + ), + ( + '_device', + models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.device' + ), + ), + ( + '_rack', + models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.rack' + ), + ), + ( + '_location', + models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.location' + ), + ), + ( + '_site', + models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.site' + ), + ), ], options={ 'ordering': ('cable', 'cable_end', 'pk'), @@ -1134,7 +1536,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='cabletermination', - constraint=models.UniqueConstraint(fields=('termination_type', 'termination_id'), name='dcim_cable_termination_unique_termination'), + constraint=models.UniqueConstraint( + fields=('termination_type', 'termination_id'), name='dcim_cable_termination_unique_termination' + ), ), migrations.RenameField( model_name='cablepath', diff --git a/netbox/dcim/migrations/0160_squashed_0166.py b/netbox/dcim/migrations/0160_squashed_0166.py index 440a8115e..0deb58bab 100644 --- a/netbox/dcim/migrations/0160_squashed_0166.py +++ b/netbox/dcim/migrations/0160_squashed_0166.py @@ -6,7 +6,6 @@ import utilities.json class Migration(migrations.Migration): - replaces = [ ('dcim', '0160_populate_cable_ends'), ('dcim', '0161_cabling_cleanup'), @@ -14,7 +13,7 @@ class Migration(migrations.Migration): ('dcim', '0163_weight_fields'), ('dcim', '0164_rack_mounting_depth'), ('dcim', '0165_standardize_description_comments'), - ('dcim', '0166_virtualdevicecontext') + ('dcim', '0166_virtualdevicecontext'), ] dependencies = [ @@ -275,7 +274,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='cabletermination', - constraint=models.UniqueConstraint(fields=('termination_type', 'termination_id'), name='dcim_cabletermination_unique_termination'), + constraint=models.UniqueConstraint( + fields=('termination_type', 'termination_id'), name='dcim_cabletermination_unique_termination' + ), ), migrations.AddConstraint( model_name='consoleport', @@ -283,39 +284,64 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='consoleporttemplate', - constraint=models.UniqueConstraint(fields=('device_type', 'name'), name='dcim_consoleporttemplate_unique_device_type_name'), + constraint=models.UniqueConstraint( + fields=('device_type', 'name'), name='dcim_consoleporttemplate_unique_device_type_name' + ), ), migrations.AddConstraint( model_name='consoleporttemplate', - constraint=models.UniqueConstraint(fields=('module_type', 'name'), name='dcim_consoleporttemplate_unique_module_type_name'), + constraint=models.UniqueConstraint( + fields=('module_type', 'name'), name='dcim_consoleporttemplate_unique_module_type_name' + ), ), migrations.AddConstraint( model_name='consoleserverport', - constraint=models.UniqueConstraint(fields=('device', 'name'), name='dcim_consoleserverport_unique_device_name'), + constraint=models.UniqueConstraint( + fields=('device', 'name'), name='dcim_consoleserverport_unique_device_name' + ), ), migrations.AddConstraint( model_name='consoleserverporttemplate', - constraint=models.UniqueConstraint(fields=('device_type', 'name'), name='dcim_consoleserverporttemplate_unique_device_type_name'), + constraint=models.UniqueConstraint( + fields=('device_type', 'name'), name='dcim_consoleserverporttemplate_unique_device_type_name' + ), ), migrations.AddConstraint( model_name='consoleserverporttemplate', - constraint=models.UniqueConstraint(fields=('module_type', 'name'), name='dcim_consoleserverporttemplate_unique_module_type_name'), + constraint=models.UniqueConstraint( + fields=('module_type', 'name'), name='dcim_consoleserverporttemplate_unique_module_type_name' + ), ), migrations.AddConstraint( model_name='device', - constraint=models.UniqueConstraint(django.db.models.functions.text.Lower('name'), models.F('site'), models.F('tenant'), name='dcim_device_unique_name_site_tenant'), + constraint=models.UniqueConstraint( + django.db.models.functions.text.Lower('name'), + models.F('site'), + models.F('tenant'), + name='dcim_device_unique_name_site_tenant', + ), ), migrations.AddConstraint( model_name='device', - constraint=models.UniqueConstraint(django.db.models.functions.text.Lower('name'), models.F('site'), condition=models.Q(('tenant__isnull', True)), name='dcim_device_unique_name_site', violation_error_message='Device name must be unique per site.'), + constraint=models.UniqueConstraint( + django.db.models.functions.text.Lower('name'), + models.F('site'), + condition=models.Q(('tenant__isnull', True)), + name='dcim_device_unique_name_site', + violation_error_message='Device name must be unique per site.', + ), ), migrations.AddConstraint( model_name='device', - constraint=models.UniqueConstraint(fields=('rack', 'position', 'face'), name='dcim_device_unique_rack_position_face'), + constraint=models.UniqueConstraint( + fields=('rack', 'position', 'face'), name='dcim_device_unique_rack_position_face' + ), ), migrations.AddConstraint( model_name='device', - constraint=models.UniqueConstraint(fields=('virtual_chassis', 'vc_position'), name='dcim_device_unique_virtual_chassis_vc_position'), + constraint=models.UniqueConstraint( + fields=('virtual_chassis', 'vc_position'), name='dcim_device_unique_virtual_chassis_vc_position' + ), ), migrations.AddConstraint( model_name='devicebay', @@ -323,15 +349,21 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='devicebaytemplate', - constraint=models.UniqueConstraint(fields=('device_type', 'name'), name='dcim_devicebaytemplate_unique_device_type_name'), + constraint=models.UniqueConstraint( + fields=('device_type', 'name'), name='dcim_devicebaytemplate_unique_device_type_name' + ), ), migrations.AddConstraint( model_name='devicetype', - constraint=models.UniqueConstraint(fields=('manufacturer', 'model'), name='dcim_devicetype_unique_manufacturer_model'), + constraint=models.UniqueConstraint( + fields=('manufacturer', 'model'), name='dcim_devicetype_unique_manufacturer_model' + ), ), migrations.AddConstraint( model_name='devicetype', - constraint=models.UniqueConstraint(fields=('manufacturer', 'slug'), name='dcim_devicetype_unique_manufacturer_slug'), + constraint=models.UniqueConstraint( + fields=('manufacturer', 'slug'), name='dcim_devicetype_unique_manufacturer_slug' + ), ), migrations.AddConstraint( model_name='frontport', @@ -339,19 +371,27 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='frontport', - constraint=models.UniqueConstraint(fields=('rear_port', 'rear_port_position'), name='dcim_frontport_unique_rear_port_position'), + constraint=models.UniqueConstraint( + fields=('rear_port', 'rear_port_position'), name='dcim_frontport_unique_rear_port_position' + ), ), migrations.AddConstraint( model_name='frontporttemplate', - constraint=models.UniqueConstraint(fields=('device_type', 'name'), name='dcim_frontporttemplate_unique_device_type_name'), + constraint=models.UniqueConstraint( + fields=('device_type', 'name'), name='dcim_frontporttemplate_unique_device_type_name' + ), ), migrations.AddConstraint( model_name='frontporttemplate', - constraint=models.UniqueConstraint(fields=('module_type', 'name'), name='dcim_frontporttemplate_unique_module_type_name'), + constraint=models.UniqueConstraint( + fields=('module_type', 'name'), name='dcim_frontporttemplate_unique_module_type_name' + ), ), migrations.AddConstraint( model_name='frontporttemplate', - constraint=models.UniqueConstraint(fields=('rear_port', 'rear_port_position'), name='dcim_frontporttemplate_unique_rear_port_position'), + constraint=models.UniqueConstraint( + fields=('rear_port', 'rear_port_position'), name='dcim_frontporttemplate_unique_rear_port_position' + ), ), migrations.AddConstraint( model_name='interface', @@ -359,27 +399,46 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='interfacetemplate', - constraint=models.UniqueConstraint(fields=('device_type', 'name'), name='dcim_interfacetemplate_unique_device_type_name'), + constraint=models.UniqueConstraint( + fields=('device_type', 'name'), name='dcim_interfacetemplate_unique_device_type_name' + ), ), migrations.AddConstraint( model_name='interfacetemplate', - constraint=models.UniqueConstraint(fields=('module_type', 'name'), name='dcim_interfacetemplate_unique_module_type_name'), + constraint=models.UniqueConstraint( + fields=('module_type', 'name'), name='dcim_interfacetemplate_unique_module_type_name' + ), ), migrations.AddConstraint( model_name='inventoryitem', - constraint=models.UniqueConstraint(fields=('device', 'parent', 'name'), name='dcim_inventoryitem_unique_device_parent_name'), + constraint=models.UniqueConstraint( + fields=('device', 'parent', 'name'), name='dcim_inventoryitem_unique_device_parent_name' + ), ), migrations.AddConstraint( model_name='inventoryitemtemplate', - constraint=models.UniqueConstraint(fields=('device_type', 'parent', 'name'), name='dcim_inventoryitemtemplate_unique_device_type_parent_name'), + constraint=models.UniqueConstraint( + fields=('device_type', 'parent', 'name'), + name='dcim_inventoryitemtemplate_unique_device_type_parent_name', + ), ), migrations.AddConstraint( model_name='location', - constraint=models.UniqueConstraint(condition=models.Q(('parent__isnull', True)), fields=('site', 'name'), name='dcim_location_name', violation_error_message='A location with this name already exists within the specified site.'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent__isnull', True)), + fields=('site', 'name'), + name='dcim_location_name', + violation_error_message='A location with this name already exists within the specified site.', + ), ), migrations.AddConstraint( model_name='location', - constraint=models.UniqueConstraint(condition=models.Q(('parent__isnull', True)), fields=('site', 'slug'), name='dcim_location_slug', violation_error_message='A location with this slug already exists within the specified site.'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent__isnull', True)), + fields=('site', 'slug'), + name='dcim_location_slug', + violation_error_message='A location with this slug already exists within the specified site.', + ), ), migrations.AddConstraint( model_name='modulebay', @@ -387,15 +446,21 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='modulebaytemplate', - constraint=models.UniqueConstraint(fields=('device_type', 'name'), name='dcim_modulebaytemplate_unique_device_type_name'), + constraint=models.UniqueConstraint( + fields=('device_type', 'name'), name='dcim_modulebaytemplate_unique_device_type_name' + ), ), migrations.AddConstraint( model_name='moduletype', - constraint=models.UniqueConstraint(fields=('manufacturer', 'model'), name='dcim_moduletype_unique_manufacturer_model'), + constraint=models.UniqueConstraint( + fields=('manufacturer', 'model'), name='dcim_moduletype_unique_manufacturer_model' + ), ), migrations.AddConstraint( model_name='powerfeed', - constraint=models.UniqueConstraint(fields=('power_panel', 'name'), name='dcim_powerfeed_unique_power_panel_name'), + constraint=models.UniqueConstraint( + fields=('power_panel', 'name'), name='dcim_powerfeed_unique_power_panel_name' + ), ), migrations.AddConstraint( model_name='poweroutlet', @@ -403,11 +468,15 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='poweroutlettemplate', - constraint=models.UniqueConstraint(fields=('device_type', 'name'), name='dcim_poweroutlettemplate_unique_device_type_name'), + constraint=models.UniqueConstraint( + fields=('device_type', 'name'), name='dcim_poweroutlettemplate_unique_device_type_name' + ), ), migrations.AddConstraint( model_name='poweroutlettemplate', - constraint=models.UniqueConstraint(fields=('module_type', 'name'), name='dcim_poweroutlettemplate_unique_module_type_name'), + constraint=models.UniqueConstraint( + fields=('module_type', 'name'), name='dcim_poweroutlettemplate_unique_module_type_name' + ), ), migrations.AddConstraint( model_name='powerpanel', @@ -419,11 +488,15 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='powerporttemplate', - constraint=models.UniqueConstraint(fields=('device_type', 'name'), name='dcim_powerporttemplate_unique_device_type_name'), + constraint=models.UniqueConstraint( + fields=('device_type', 'name'), name='dcim_powerporttemplate_unique_device_type_name' + ), ), migrations.AddConstraint( model_name='powerporttemplate', - constraint=models.UniqueConstraint(fields=('module_type', 'name'), name='dcim_powerporttemplate_unique_module_type_name'), + constraint=models.UniqueConstraint( + fields=('module_type', 'name'), name='dcim_powerporttemplate_unique_module_type_name' + ), ), migrations.AddConstraint( model_name='rack', @@ -431,7 +504,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='rack', - constraint=models.UniqueConstraint(fields=('location', 'facility_id'), name='dcim_rack_unique_location_facility_id'), + constraint=models.UniqueConstraint( + fields=('location', 'facility_id'), name='dcim_rack_unique_location_facility_id' + ), ), migrations.AddConstraint( model_name='rearport', @@ -439,27 +514,51 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='rearporttemplate', - constraint=models.UniqueConstraint(fields=('device_type', 'name'), name='dcim_rearporttemplate_unique_device_type_name'), + constraint=models.UniqueConstraint( + fields=('device_type', 'name'), name='dcim_rearporttemplate_unique_device_type_name' + ), ), migrations.AddConstraint( model_name='rearporttemplate', - constraint=models.UniqueConstraint(fields=('module_type', 'name'), name='dcim_rearporttemplate_unique_module_type_name'), + constraint=models.UniqueConstraint( + fields=('module_type', 'name'), name='dcim_rearporttemplate_unique_module_type_name' + ), ), migrations.AddConstraint( model_name='region', - constraint=models.UniqueConstraint(condition=models.Q(('parent__isnull', True)), fields=('name',), name='dcim_region_name', violation_error_message='A top-level region with this name already exists.'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent__isnull', True)), + fields=('name',), + name='dcim_region_name', + violation_error_message='A top-level region with this name already exists.', + ), ), migrations.AddConstraint( model_name='region', - constraint=models.UniqueConstraint(condition=models.Q(('parent__isnull', True)), fields=('slug',), name='dcim_region_slug', violation_error_message='A top-level region with this slug already exists.'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent__isnull', True)), + fields=('slug',), + name='dcim_region_slug', + violation_error_message='A top-level region with this slug already exists.', + ), ), migrations.AddConstraint( model_name='sitegroup', - constraint=models.UniqueConstraint(condition=models.Q(('parent__isnull', True)), fields=('name',), name='dcim_sitegroup_name', violation_error_message='A top-level site group with this name already exists.'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent__isnull', True)), + fields=('name',), + name='dcim_sitegroup_name', + violation_error_message='A top-level site group with this name already exists.', + ), ), migrations.AddConstraint( model_name='sitegroup', - constraint=models.UniqueConstraint(condition=models.Q(('parent__isnull', True)), fields=('slug',), name='dcim_sitegroup_slug', violation_error_message='A top-level site group with this slug already exists.'), + constraint=models.UniqueConstraint( + condition=models.Q(('parent__isnull', True)), + fields=('slug',), + name='dcim_sitegroup_slug', + violation_error_message='A top-level site group with this slug already exists.', + ), ), migrations.AddField( model_name='devicetype', @@ -592,17 +691,56 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('description', models.CharField(blank=True, max_length=200)), ('name', models.CharField(max_length=64)), ('status', models.CharField(max_length=50)), ('identifier', models.PositiveSmallIntegerField(blank=True, null=True)), ('comments', models.TextField(blank=True)), - ('device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vdcs', to='dcim.device')), - ('primary_ip4', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress')), - ('primary_ip6', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress')), + ( + 'device', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='vdcs', + to='dcim.device', + ), + ), + ( + 'primary_ip4', + models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='ipam.ipaddress', + ), + ), + ( + 'primary_ip6', + models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='ipam.ipaddress', + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), - ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vdcs', to='tenancy.tenant')), + ( + 'tenant', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='vdcs', + to='tenancy.tenant', + ), + ), ], options={ 'ordering': ['name'], @@ -615,7 +753,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='virtualdevicecontext', - constraint=models.UniqueConstraint(fields=('device', 'identifier'), name='dcim_virtualdevicecontext_device_identifier'), + constraint=models.UniqueConstraint( + fields=('device', 'identifier'), name='dcim_virtualdevicecontext_device_identifier' + ), ), migrations.AddConstraint( model_name='virtualdevicecontext', diff --git a/netbox/dcim/migrations/0167_squashed_0182.py b/netbox/dcim/migrations/0167_squashed_0182.py index 735cb3efa..d0ad5379f 100644 --- a/netbox/dcim/migrations/0167_squashed_0182.py +++ b/netbox/dcim/migrations/0167_squashed_0182.py @@ -6,7 +6,6 @@ import utilities.fields class Migration(migrations.Migration): - replaces = [ ('dcim', '0167_module_status'), ('dcim', '0168_interface_template_enabled'), @@ -24,7 +23,7 @@ class Migration(migrations.Migration): ('dcim', '0179_interfacetemplate_rf_role'), ('dcim', '0180_powerfeed_tenant'), ('dcim', '0181_rename_device_role_device_role'), - ('dcim', '0182_zero_length_cable_fix') + ('dcim', '0182_zero_length_cable_fix'), ] dependencies = [ @@ -48,27 +47,57 @@ class Migration(migrations.Migration): migrations.AddField( model_name='interfacetemplate', name='bridge', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bridge_interfaces', to='dcim.interfacetemplate'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='bridge_interfaces', + to='dcim.interfacetemplate', + ), ), migrations.AddField( model_name='devicetype', name='default_platform', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.platform'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='dcim.platform', + ), ), migrations.AddField( model_name='device', name='config_template', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='%(class)ss', to='extras.configtemplate'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='%(class)ss', + to='extras.configtemplate', + ), ), migrations.AddField( model_name='devicerole', name='config_template', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='device_roles', to='extras.configtemplate'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='device_roles', + to='extras.configtemplate', + ), ), migrations.AddField( model_name='platform', name='config_template', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='platforms', to='extras.configtemplate'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='platforms', + to='extras.configtemplate', + ), ), migrations.AddField( model_name='cabletermination', @@ -83,22 +112,30 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='powerport', name='allocated_draw', - field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]), + field=models.PositiveIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), ), migrations.AlterField( model_name='powerport', name='maximum_draw', - field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]), + field=models.PositiveIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), ), migrations.AlterField( model_name='powerporttemplate', name='allocated_draw', - field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]), + field=models.PositiveIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), ), migrations.AlterField( model_name='powerporttemplate', name='maximum_draw', - field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]), + field=models.PositiveIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), ), migrations.RemoveField( model_name='platform', @@ -126,112 +163,160 @@ class Migration(migrations.Migration): migrations.AddField( model_name='device', name='oob_ip', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress'), + field=models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='ipam.ipaddress', + ), ), migrations.AddField( model_name='device', name='console_port_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.ConsolePort'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device', to_model='dcim.ConsolePort' + ), ), migrations.AddField( model_name='device', name='console_server_port_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.ConsoleServerPort'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device', to_model='dcim.ConsoleServerPort' + ), ), migrations.AddField( model_name='device', name='power_port_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.PowerPort'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device', to_model='dcim.PowerPort' + ), ), migrations.AddField( model_name='device', name='power_outlet_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.PowerOutlet'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device', to_model='dcim.PowerOutlet' + ), ), migrations.AddField( model_name='device', name='interface_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.Interface'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device', to_model='dcim.Interface' + ), ), migrations.AddField( model_name='device', name='front_port_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.FrontPort'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device', to_model='dcim.FrontPort' + ), ), migrations.AddField( model_name='device', name='rear_port_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.RearPort'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device', to_model='dcim.RearPort' + ), ), migrations.AddField( model_name='device', name='device_bay_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.DeviceBay'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device', to_model='dcim.DeviceBay' + ), ), migrations.AddField( model_name='device', name='module_bay_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.ModuleBay'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device', to_model='dcim.ModuleBay' + ), ), migrations.AddField( model_name='device', name='inventory_item_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.InventoryItem'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device', to_model='dcim.InventoryItem' + ), ), migrations.AddField( model_name='devicetype', name='console_port_template_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.ConsolePortTemplate'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device_type', to_model='dcim.ConsolePortTemplate' + ), ), migrations.AddField( model_name='devicetype', name='console_server_port_template_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.ConsoleServerPortTemplate'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device_type', to_model='dcim.ConsoleServerPortTemplate' + ), ), migrations.AddField( model_name='devicetype', name='power_port_template_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.PowerPortTemplate'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device_type', to_model='dcim.PowerPortTemplate' + ), ), migrations.AddField( model_name='devicetype', name='power_outlet_template_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.PowerOutletTemplate'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device_type', to_model='dcim.PowerOutletTemplate' + ), ), migrations.AddField( model_name='devicetype', name='interface_template_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.InterfaceTemplate'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device_type', to_model='dcim.InterfaceTemplate' + ), ), migrations.AddField( model_name='devicetype', name='front_port_template_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.FrontPortTemplate'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device_type', to_model='dcim.FrontPortTemplate' + ), ), migrations.AddField( model_name='devicetype', name='rear_port_template_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.RearPortTemplate'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device_type', to_model='dcim.RearPortTemplate' + ), ), migrations.AddField( model_name='devicetype', name='device_bay_template_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.DeviceBayTemplate'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device_type', to_model='dcim.DeviceBayTemplate' + ), ), migrations.AddField( model_name='devicetype', name='module_bay_template_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.ModuleBayTemplate'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device_type', to_model='dcim.ModuleBayTemplate' + ), ), migrations.AddField( model_name='devicetype', name='inventory_item_template_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.InventoryItemTemplate'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='device_type', to_model='dcim.InventoryItemTemplate' + ), ), migrations.AddField( model_name='virtualchassis', name='member_count', - field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='virtual_chassis', to_model='dcim.Device'), + field=utilities.fields.CounterCacheField( + default=0, editable=False, to_field='virtual_chassis', to_model='dcim.Device' + ), ), migrations.AddField( model_name='interfacetemplate', @@ -241,7 +326,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='powerfeed', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='power_feeds', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='power_feeds', + to='tenancy.tenant', + ), ), migrations.RenameField( model_name='device', diff --git a/netbox/dcim/migrations/0184_protect_child_interfaces.py b/netbox/dcim/migrations/0184_protect_child_interfaces.py index 3459e23fc..58eca506d 100644 --- a/netbox/dcim/migrations/0184_protect_child_interfaces.py +++ b/netbox/dcim/migrations/0184_protect_child_interfaces.py @@ -5,7 +5,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ ('dcim', '0183_devicetype_exclude_from_utilization'), ] @@ -14,6 +13,12 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='interface', name='parent', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, related_name='child_interfaces', to='dcim.interface'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.RESTRICT, + related_name='child_interfaces', + to='dcim.interface', + ), ), ] diff --git a/netbox/dcim/migrations/0185_gfk_indexes.py b/netbox/dcim/migrations/0185_gfk_indexes.py index 84cdc53ff..5c099b380 100644 --- a/netbox/dcim/migrations/0185_gfk_indexes.py +++ b/netbox/dcim/migrations/0185_gfk_indexes.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('dcim', '0184_protect_child_interfaces'), ] diff --git a/netbox/dcim/migrations/0186_location_facility.py b/netbox/dcim/migrations/0186_location_facility.py index 759ee813b..3d22503b6 100644 --- a/netbox/dcim/migrations/0186_location_facility.py +++ b/netbox/dcim/migrations/0186_location_facility.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('dcim', '0185_gfk_indexes'), ] diff --git a/netbox/dcim/migrations/0187_alter_device_vc_position.py b/netbox/dcim/migrations/0187_alter_device_vc_position.py index d4a42dc20..10b636959 100644 --- a/netbox/dcim/migrations/0187_alter_device_vc_position.py +++ b/netbox/dcim/migrations/0187_alter_device_vc_position.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('dcim', '0186_location_facility'), ] diff --git a/netbox/dcim/migrations/0188_racktype.py b/netbox/dcim/migrations/0188_racktype.py index aa45246e5..a5265d030 100644 --- a/netbox/dcim/migrations/0188_racktype.py +++ b/netbox/dcim/migrations/0188_racktype.py @@ -9,7 +9,6 @@ import utilities.ordering class Migration(migrations.Migration): - dependencies = [ ('extras', '0118_customfield_uniqueness'), ('dcim', '0187_alter_device_vc_position'), @@ -22,36 +21,41 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField( - blank=True, - default=dict, - encoder=utilities.json.CustomFieldJSONEncoder - )), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('description', models.CharField(blank=True, max_length=200)), ('comments', models.TextField(blank=True)), ('weight', models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True)), ('weight_unit', models.CharField(blank=True, max_length=50)), ('_abs_weight', models.PositiveBigIntegerField(blank=True, null=True)), - ('manufacturer', models.ForeignKey( - on_delete=django.db.models.deletion.PROTECT, - related_name='rack_types', - to='dcim.manufacturer' - )), + ( + 'manufacturer', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='rack_types', to='dcim.manufacturer' + ), + ), ('model', models.CharField(max_length=100)), ('slug', models.SlugField(max_length=100, unique=True)), ('form_factor', models.CharField(max_length=50)), ('width', models.PositiveSmallIntegerField(default=19)), - ('u_height', models.PositiveSmallIntegerField( - default=42, - validators=[ - django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100), - ] - )), - ('starting_unit', models.PositiveSmallIntegerField( - default=1, - validators=[django.core.validators.MinValueValidator(1)] - )), + ( + 'u_height', + models.PositiveSmallIntegerField( + default=42, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(100), + ], + ), + ), + ( + 'starting_unit', + models.PositiveSmallIntegerField( + default=1, validators=[django.core.validators.MinValueValidator(1)] + ), + ), ('desc_units', models.BooleanField(default=False)), ('outer_width', models.PositiveSmallIntegerField(blank=True, null=True)), ('outer_depth', models.PositiveSmallIntegerField(blank=True, null=True)), diff --git a/netbox/dcim/migrations/0189_moduletype_rack_airflow.py b/netbox/dcim/migrations/0189_moduletype_rack_airflow.py index 31787b67d..c356e32f7 100644 --- a/netbox/dcim/migrations/0189_moduletype_rack_airflow.py +++ b/netbox/dcim/migrations/0189_moduletype_rack_airflow.py @@ -2,7 +2,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('dcim', '0188_racktype'), ] diff --git a/netbox/dcim/migrations/0190_nested_modules.py b/netbox/dcim/migrations/0190_nested_modules.py index 9cef40efb..239e08639 100644 --- a/netbox/dcim/migrations/0190_nested_modules.py +++ b/netbox/dcim/migrations/0190_nested_modules.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('dcim', '0189_moduletype_rack_airflow'), ('extras', '0121_customfield_related_object_filter'), @@ -34,12 +33,25 @@ class Migration(migrations.Migration): migrations.AddField( model_name='modulebay', name='module', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.module', + ), ), migrations.AddField( model_name='modulebay', name='parent', - field=mptt.fields.TreeForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='dcim.modulebay'), + field=mptt.fields.TreeForeignKey( + blank=True, + editable=False, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='children', + to='dcim.modulebay', + ), ), migrations.AddField( model_name='modulebay', @@ -56,19 +68,35 @@ class Migration(migrations.Migration): migrations.AddField( model_name='modulebaytemplate', name='module_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.moduletype', + ), ), migrations.AlterField( model_name='modulebaytemplate', name='device_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='%(class)ss', + to='dcim.devicetype', + ), ), migrations.AddConstraint( model_name='modulebay', - constraint=models.UniqueConstraint(fields=('device', 'module', 'name'), name='dcim_modulebay_unique_device_module_name'), + constraint=models.UniqueConstraint( + fields=('device', 'module', 'name'), name='dcim_modulebay_unique_device_module_name' + ), ), migrations.AddConstraint( model_name='modulebaytemplate', - constraint=models.UniqueConstraint(fields=('module_type', 'name'), name='dcim_modulebaytemplate_unique_module_type_name'), + constraint=models.UniqueConstraint( + fields=('module_type', 'name'), name='dcim_modulebaytemplate_unique_module_type_name' + ), ), ] diff --git a/netbox/dcim/migrations/0191_module_bay_rebuild.py b/netbox/dcim/migrations/0191_module_bay_rebuild.py index 260063213..4f8a461f2 100644 --- a/netbox/dcim/migrations/0191_module_bay_rebuild.py +++ b/netbox/dcim/migrations/0191_module_bay_rebuild.py @@ -13,14 +13,10 @@ def rebuild_mptt(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('dcim', '0190_nested_modules'), ] operations = [ - migrations.RunPython( - code=rebuild_mptt, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=rebuild_mptt, reverse_code=migrations.RunPython.noop), ] diff --git a/netbox/dcim/migrations/0192_inventoryitem_status.py b/netbox/dcim/migrations/0192_inventoryitem_status.py index 335ab2ca7..027f2daef 100644 --- a/netbox/dcim/migrations/0192_inventoryitem_status.py +++ b/netbox/dcim/migrations/0192_inventoryitem_status.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('dcim', '0191_module_bay_rebuild'), ] diff --git a/netbox/dcim/migrations/0193_poweroutlet_color.py b/netbox/dcim/migrations/0193_poweroutlet_color.py index 0a6c08b48..f7e3c430c 100644 --- a/netbox/dcim/migrations/0193_poweroutlet_color.py +++ b/netbox/dcim/migrations/0193_poweroutlet_color.py @@ -5,7 +5,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('dcim', '0192_inventoryitem_status'), ] diff --git a/netbox/dcim/migrations/0194_charfield_null_choices.py b/netbox/dcim/migrations/0194_charfield_null_choices.py new file mode 100644 index 000000000..e13b0e10d --- /dev/null +++ b/netbox/dcim/migrations/0194_charfield_null_choices.py @@ -0,0 +1,291 @@ +import timezone_field.fields +from django.db import migrations, models + + +def set_null_values(apps, schema_editor): + """ + Replace empty strings with null values. + """ + Cable = apps.get_model('dcim', 'Cable') + ConsolePort = apps.get_model('dcim', 'ConsolePort') + ConsolePortTemplate = apps.get_model('dcim', 'ConsolePortTemplate') + ConsoleServerPort = apps.get_model('dcim', 'ConsoleServerPort') + ConsoleServerPortTemplate = apps.get_model('dcim', 'ConsoleServerPortTemplate') + Device = apps.get_model('dcim', 'Device') + DeviceType = apps.get_model('dcim', 'DeviceType') + FrontPort = apps.get_model('dcim', 'FrontPort') + Interface = apps.get_model('dcim', 'Interface') + InterfaceTemplate = apps.get_model('dcim', 'InterfaceTemplate') + ModuleType = apps.get_model('dcim', 'ModuleType') + PowerFeed = apps.get_model('dcim', 'PowerFeed') + PowerOutlet = apps.get_model('dcim', 'PowerOutlet') + PowerOutletTemplate = apps.get_model('dcim', 'PowerOutletTemplate') + PowerPort = apps.get_model('dcim', 'PowerPort') + PowerPortTemplate = apps.get_model('dcim', 'PowerPortTemplate') + Rack = apps.get_model('dcim', 'Rack') + RackType = apps.get_model('dcim', 'RackType') + RearPort = apps.get_model('dcim', 'RearPort') + Site = apps.get_model('dcim', 'Site') + + Cable.objects.filter(length_unit='').update(length_unit=None) + Cable.objects.filter(type='').update(type=None) + ConsolePort.objects.filter(cable_end='').update(cable_end=None) + ConsolePort.objects.filter(type='').update(type=None) + ConsolePortTemplate.objects.filter(type='').update(type=None) + ConsoleServerPort.objects.filter(cable_end='').update(cable_end=None) + ConsoleServerPort.objects.filter(type='').update(type=None) + ConsoleServerPortTemplate.objects.filter(type='').update(type=None) + Device.objects.filter(airflow='').update(airflow=None) + Device.objects.filter(face='').update(face=None) + DeviceType.objects.filter(airflow='').update(airflow=None) + DeviceType.objects.filter(subdevice_role='').update(subdevice_role=None) + DeviceType.objects.filter(weight_unit='').update(weight_unit=None) + FrontPort.objects.filter(cable_end='').update(cable_end=None) + Interface.objects.filter(cable_end='').update(cable_end=None) + Interface.objects.filter(mode='').update(mode=None) + Interface.objects.filter(poe_mode='').update(poe_mode=None) + Interface.objects.filter(poe_type='').update(poe_type=None) + Interface.objects.filter(rf_channel='').update(rf_channel=None) + Interface.objects.filter(rf_role='').update(rf_role=None) + InterfaceTemplate.objects.filter(poe_mode='').update(poe_mode=None) + InterfaceTemplate.objects.filter(poe_type='').update(poe_type=None) + InterfaceTemplate.objects.filter(rf_role='').update(rf_role=None) + ModuleType.objects.filter(airflow='').update(airflow=None) + ModuleType.objects.filter(weight_unit='').update(weight_unit=None) + PowerFeed.objects.filter(cable_end='').update(cable_end=None) + PowerOutlet.objects.filter(cable_end='').update(cable_end=None) + PowerOutlet.objects.filter(feed_leg='').update(feed_leg=None) + PowerOutlet.objects.filter(type='').update(type=None) + PowerOutletTemplate.objects.filter(feed_leg='').update(feed_leg=None) + PowerOutletTemplate.objects.filter(type='').update(type=None) + PowerPort.objects.filter(cable_end='').update(cable_end=None) + PowerPort.objects.filter(type='').update(type=None) + PowerPortTemplate.objects.filter(type='').update(type=None) + Rack.objects.filter(airflow='').update(airflow=None) + Rack.objects.filter(form_factor='').update(form_factor=None) + Rack.objects.filter(outer_unit='').update(outer_unit=None) + Rack.objects.filter(weight_unit='').update(weight_unit=None) + RackType.objects.filter(outer_unit='').update(outer_unit=None) + RackType.objects.filter(weight_unit='').update(weight_unit=None) + RearPort.objects.filter(cable_end='').update(cable_end=None) + Site.objects.filter(time_zone='').update(time_zone=None) + + +class Migration(migrations.Migration): + dependencies = [ + ('dcim', '0193_poweroutlet_color'), + ] + + operations = [ + migrations.AlterField( + model_name='cable', + name='length_unit', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='cable', + name='type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='consoleport', + name='cable_end', + field=models.CharField(blank=True, max_length=1, null=True), + ), + migrations.AlterField( + model_name='consoleport', + name='type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='consoleporttemplate', + name='type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='consoleserverport', + name='cable_end', + field=models.CharField(blank=True, max_length=1, null=True), + ), + migrations.AlterField( + model_name='consoleserverport', + name='type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='consoleserverporttemplate', + name='type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='device', + name='airflow', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='device', + name='face', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='devicetype', + name='airflow', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='devicetype', + name='subdevice_role', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='devicetype', + name='weight_unit', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='frontport', + name='cable_end', + field=models.CharField(blank=True, max_length=1, null=True), + ), + migrations.AlterField( + model_name='interface', + name='cable_end', + field=models.CharField(blank=True, max_length=1, null=True), + ), + migrations.AlterField( + model_name='interface', + name='mode', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='interface', + name='poe_mode', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='interface', + name='poe_type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='interface', + name='rf_channel', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='interface', + name='rf_role', + field=models.CharField(blank=True, max_length=30, null=True), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='poe_mode', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='poe_type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='rf_role', + field=models.CharField(blank=True, max_length=30, null=True), + ), + migrations.AlterField( + model_name='moduletype', + name='airflow', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='moduletype', + name='weight_unit', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='powerfeed', + name='cable_end', + field=models.CharField(blank=True, max_length=1, null=True), + ), + migrations.AlterField( + model_name='poweroutlet', + name='cable_end', + field=models.CharField(blank=True, max_length=1, null=True), + ), + migrations.AlterField( + model_name='poweroutlet', + name='feed_leg', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='poweroutlet', + name='type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='poweroutlettemplate', + name='feed_leg', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='poweroutlettemplate', + name='type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='powerport', + name='cable_end', + field=models.CharField(blank=True, max_length=1, null=True), + ), + migrations.AlterField( + model_name='powerport', + name='type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='powerporttemplate', + name='type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='rack', + name='airflow', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='rack', + name='form_factor', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='rack', + name='outer_unit', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='rack', + name='weight_unit', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='racktype', + name='outer_unit', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='racktype', + name='weight_unit', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='rearport', + name='cable_end', + field=models.CharField(blank=True, max_length=1, null=True), + ), + migrations.AlterField( + model_name='site', + name='time_zone', + field=timezone_field.fields.TimeZoneField(blank=True, null=True), + ), + migrations.RunPython(code=set_null_values, reverse_code=migrations.RunPython.noop), + ] diff --git a/netbox/dcim/migrations/0195_interface_vlan_translation_policy.py b/netbox/dcim/migrations/0195_interface_vlan_translation_policy.py new file mode 100644 index 000000000..9ec404886 --- /dev/null +++ b/netbox/dcim/migrations/0195_interface_vlan_translation_policy.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.9 on 2024-10-11 19:45 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('dcim', '0194_charfield_null_choices'), + ('ipam', '0074_vlantranslationpolicy_vlantranslationrule'), + ] + + operations = [ + migrations.AddField( + model_name='interface', + name='vlan_translation_policy', + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='ipam.vlantranslationpolicy' + ), + ), + ] diff --git a/netbox/dcim/migrations/0196_qinq_svlan.py b/netbox/dcim/migrations/0196_qinq_svlan.py new file mode 100644 index 000000000..a03ad144a --- /dev/null +++ b/netbox/dcim/migrations/0196_qinq_svlan.py @@ -0,0 +1,39 @@ +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('dcim', '0195_interface_vlan_translation_policy'), + ('ipam', '0075_vlan_qinq'), + ] + + operations = [ + migrations.AddField( + model_name='interface', + name='qinq_svlan', + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='%(class)ss_svlan', + to='ipam.vlan', + ), + ), + migrations.AlterField( + model_name='interface', + name='tagged_vlans', + field=models.ManyToManyField(blank=True, related_name='%(class)ss_as_tagged', to='ipam.vlan'), + ), + migrations.AlterField( + model_name='interface', + name='untagged_vlan', + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='%(class)ss_as_untagged', + to='ipam.vlan', + ), + ), + ] diff --git a/netbox/dcim/migrations/0197_natural_sort_collation.py b/netbox/dcim/migrations/0197_natural_sort_collation.py new file mode 100644 index 000000000..268bda7eb --- /dev/null +++ b/netbox/dcim/migrations/0197_natural_sort_collation.py @@ -0,0 +1,16 @@ +from django.contrib.postgres.operations import CreateCollation +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ('dcim', '0196_qinq_svlan'), + ] + + operations = [ + CreateCollation( + 'natural_sort', + provider='icu', + locale='und-u-kn-true', + ), + ] diff --git a/netbox/dcim/migrations/0198_natural_ordering.py b/netbox/dcim/migrations/0198_natural_ordering.py new file mode 100644 index 000000000..cf4361a2b --- /dev/null +++ b/netbox/dcim/migrations/0198_natural_ordering.py @@ -0,0 +1,317 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('dcim', '0197_natural_sort_collation'), + ] + + operations = [ + migrations.AlterModelOptions( + name='site', + options={'ordering': ('name',)}, + ), + migrations.AlterField( + model_name='site', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterModelOptions( + name='consoleport', + options={'ordering': ('device', 'name')}, + ), + migrations.AlterModelOptions( + name='consoleporttemplate', + options={'ordering': ('device_type', 'module_type', 'name')}, + ), + migrations.AlterModelOptions( + name='consoleserverport', + options={'ordering': ('device', 'name')}, + ), + migrations.AlterModelOptions( + name='consoleserverporttemplate', + options={'ordering': ('device_type', 'module_type', 'name')}, + ), + migrations.AlterModelOptions( + name='device', + options={'ordering': ('name', 'pk')}, + ), + migrations.AlterModelOptions( + name='devicebay', + options={'ordering': ('device', 'name')}, + ), + migrations.AlterModelOptions( + name='devicebaytemplate', + options={'ordering': ('device_type', 'name')}, + ), + migrations.AlterModelOptions( + name='frontport', + options={'ordering': ('device', 'name')}, + ), + migrations.AlterModelOptions( + name='frontporttemplate', + options={'ordering': ('device_type', 'module_type', 'name')}, + ), + migrations.AlterModelOptions( + name='interfacetemplate', + options={'ordering': ('device_type', 'module_type', 'name')}, + ), + migrations.AlterModelOptions( + name='inventoryitem', + options={'ordering': ('device__id', 'parent__id', 'name')}, + ), + migrations.AlterModelOptions( + name='inventoryitemtemplate', + options={'ordering': ('device_type__id', 'parent__id', 'name')}, + ), + migrations.AlterModelOptions( + name='modulebay', + options={'ordering': ('device', 'name')}, + ), + migrations.AlterModelOptions( + name='modulebaytemplate', + options={'ordering': ('device_type', 'module_type', 'name')}, + ), + migrations.AlterModelOptions( + name='poweroutlet', + options={'ordering': ('device', 'name')}, + ), + migrations.AlterModelOptions( + name='poweroutlettemplate', + options={'ordering': ('device_type', 'module_type', 'name')}, + ), + migrations.AlterModelOptions( + name='powerport', + options={'ordering': ('device', 'name')}, + ), + migrations.AlterModelOptions( + name='powerporttemplate', + options={'ordering': ('device_type', 'module_type', 'name')}, + ), + migrations.AlterModelOptions( + name='rack', + options={'ordering': ('site', 'location', 'name', 'pk')}, + ), + migrations.AlterModelOptions( + name='rearport', + options={'ordering': ('device', 'name')}, + ), + migrations.AlterModelOptions( + name='rearporttemplate', + options={'ordering': ('device_type', 'module_type', 'name')}, + ), + migrations.RemoveField( + model_name='consoleport', + name='_name', + ), + migrations.RemoveField( + model_name='consoleporttemplate', + name='_name', + ), + migrations.RemoveField( + model_name='consoleserverport', + name='_name', + ), + migrations.RemoveField( + model_name='consoleserverporttemplate', + name='_name', + ), + migrations.RemoveField( + model_name='device', + name='_name', + ), + migrations.RemoveField( + model_name='devicebay', + name='_name', + ), + migrations.RemoveField( + model_name='devicebaytemplate', + name='_name', + ), + migrations.RemoveField( + model_name='frontport', + name='_name', + ), + migrations.RemoveField( + model_name='frontporttemplate', + name='_name', + ), + migrations.RemoveField( + model_name='inventoryitem', + name='_name', + ), + migrations.RemoveField( + model_name='inventoryitemtemplate', + name='_name', + ), + migrations.RemoveField( + model_name='modulebay', + name='_name', + ), + migrations.RemoveField( + model_name='modulebaytemplate', + name='_name', + ), + migrations.RemoveField( + model_name='poweroutlet', + name='_name', + ), + migrations.RemoveField( + model_name='poweroutlettemplate', + name='_name', + ), + migrations.RemoveField( + model_name='powerport', + name='_name', + ), + migrations.RemoveField( + model_name='powerporttemplate', + name='_name', + ), + migrations.RemoveField( + model_name='rack', + name='_name', + ), + migrations.RemoveField( + model_name='rearport', + name='_name', + ), + migrations.RemoveField( + model_name='rearporttemplate', + name='_name', + ), + migrations.RemoveField( + model_name='site', + name='_name', + ), + migrations.AlterField( + model_name='consoleport', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='consoleporttemplate', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='consoleserverport', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='consoleserverporttemplate', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='device', + name='name', + field=models.CharField(blank=True, db_collation='natural_sort', max_length=64, null=True), + ), + migrations.AlterField( + model_name='devicebay', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='devicebaytemplate', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='frontport', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='frontporttemplate', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='interface', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='inventoryitem', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='inventoryitemtemplate', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='modulebay', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='modulebaytemplate', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='poweroutlet', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='poweroutlettemplate', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='powerport', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='powerporttemplate', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='rack', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + migrations.AlterField( + model_name='rearport', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='rearporttemplate', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='powerfeed', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + migrations.AlterField( + model_name='powerpanel', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + migrations.AlterField( + model_name='virtualchassis', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + migrations.AlterField( + model_name='virtualdevicecontext', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=64), + ), + ] diff --git a/netbox/dcim/migrations/0199_macaddress.py b/netbox/dcim/migrations/0199_macaddress.py new file mode 100644 index 000000000..ae18d5f63 --- /dev/null +++ b/netbox/dcim/migrations/0199_macaddress.py @@ -0,0 +1,51 @@ +import django.db.models.deletion +import taggit.managers +from django.db import migrations, models + +import dcim.fields +import utilities.json + + +class Migration(migrations.Migration): + dependencies = [ + ('dcim', '0198_natural_ordering'), + ('extras', '0122_charfield_null_choices'), + ] + + operations = [ + migrations.CreateModel( + name='MACAddress', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), + ('description', models.CharField(blank=True, max_length=200)), + ('comments', models.TextField(blank=True)), + ('mac_address', dcim.fields.MACAddressField()), + ('assigned_object_id', models.PositiveBigIntegerField(blank=True, null=True)), + ( + 'assigned_object_type', + models.ForeignKey( + blank=True, + limit_choices_to=models.Q( + models.Q( + models.Q(('app_label', 'dcim'), ('model', 'interface')), + models.Q(('app_label', 'virtualization'), ('model', 'vminterface')), + _connector='OR', + ) + ), + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), + ), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ], + options={'abstract': False, 'ordering': ('mac_address',)}, + ), + ] diff --git a/netbox/dcim/migrations/0200_populate_mac_addresses.py b/netbox/dcim/migrations/0200_populate_mac_addresses.py new file mode 100644 index 000000000..0cd18d78e --- /dev/null +++ b/netbox/dcim/migrations/0200_populate_mac_addresses.py @@ -0,0 +1,46 @@ +import django.db.models.deletion +from django.db import migrations, models + + +def populate_mac_addresses(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + Interface = apps.get_model('dcim', 'Interface') + MACAddress = apps.get_model('dcim', 'MACAddress') + interface_ct = ContentType.objects.get_for_model(Interface) + + mac_addresses = [ + MACAddress( + mac_address=interface.mac_address, assigned_object_type=interface_ct, assigned_object_id=interface.pk + ) + for interface in Interface.objects.filter(mac_address__isnull=False) + ] + MACAddress.objects.bulk_create(mac_addresses, batch_size=100) + + # TODO: Optimize interface updates + for mac_address in mac_addresses: + Interface.objects.filter(pk=mac_address.assigned_object_id).update(primary_mac_address=mac_address) + + +class Migration(migrations.Migration): + dependencies = [ + ('dcim', '0199_macaddress'), + ] + + operations = [ + migrations.AddField( + model_name='interface', + name='primary_mac_address', + field=models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='dcim.macaddress', + ), + ), + migrations.RunPython(code=populate_mac_addresses, reverse_code=migrations.RunPython.noop), + migrations.RemoveField( + model_name='interface', + name='mac_address', + ), + ] diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py index 96861a13e..7117ea7e0 100644 --- a/netbox/dcim/models/cables.py +++ b/netbox/dcim/models/cables.py @@ -42,7 +42,8 @@ class Cable(PrimaryModel): verbose_name=_('type'), max_length=50, choices=CableTypeChoices, - blank=True + blank=True, + null=True ) status = models.CharField( verbose_name=_('status'), @@ -78,6 +79,7 @@ class Cable(PrimaryModel): max_length=50, choices=CableLengthUnitChoices, blank=True, + null=True ) # Stores the normalized length (in meters) for database ordering _abs_length = models.DecimalField( @@ -160,7 +162,7 @@ class Cable(PrimaryModel): if self.length is not None and not self.length_unit: raise ValidationError(_("Must specify a unit when setting a cable length")) - if self._state.adding and (not self.a_terminations or not self.b_terminations): + if self._state.adding and self.pk is None and (not self.a_terminations or not self.b_terminations): raise ValidationError(_("Must define A and B terminations when creating a new cable.")) if self._terminations_modified: @@ -206,7 +208,7 @@ class Cable(PrimaryModel): # Clear length_unit if no length is defined if self.length is None: - self.length_unit = '' + self.length_unit = None super().save(*args, **kwargs) @@ -342,7 +344,7 @@ class CableTermination(ChangeLoggedModel): ) # A CircuitTermination attached to a ProviderNetwork cannot have a Cable - if self.termination_type.model == 'circuittermination' and self.termination.provider_network is not None: + if self.termination_type.model == 'circuittermination' and self.termination._provider_network is not None: raise ValidationError(_("Circuit terminations attached to a provider network may not be cabled.")) def save(self, *args, **kwargs): @@ -365,7 +367,7 @@ class CableTermination(ChangeLoggedModel): termination = self.termination._meta.model.objects.get(pk=self.termination_id) termination.snapshot() termination.cable = None - termination.cable_end = '' + termination.cable_end = None termination.save() super().delete(*args, **kwargs) @@ -603,6 +605,10 @@ class CablePath(models.Model): cable_end = 'A' if lct.cable_end == 'B' else 'B' q_filter |= Q(cable=lct.cable, cable_end=cable_end) + # Make sure this filter has been populated; if not, we have probably been given invalid data + if not q_filter: + break + remote_cable_terminations = CableTermination.objects.filter(q_filter) remote_terminations = [ct.termination for ct in remote_cable_terminations] else: @@ -688,19 +694,19 @@ class CablePath(models.Model): ).first() if circuit_termination is None: break - elif circuit_termination.provider_network: + elif circuit_termination._provider_network: # Circuit terminates to a ProviderNetwork path.extend([ [object_to_path_node(circuit_termination)], - [object_to_path_node(circuit_termination.provider_network)], + [object_to_path_node(circuit_termination._provider_network)], ]) is_complete = True break - elif circuit_termination.site and not circuit_termination.cable: - # Circuit terminates to a Site + elif circuit_termination.termination and not circuit_termination.cable: + # Circuit terminates to a Region/Site/etc. path.extend([ [object_to_path_node(circuit_termination)], - [object_to_path_node(circuit_termination.site)], + [object_to_path_node(circuit_termination.termination)], ]) break diff --git a/netbox/dcim/models/device_component_templates.py b/netbox/dcim/models/device_component_templates.py index 3a71c424d..b4f057711 100644 --- a/netbox/dcim/models/device_component_templates.py +++ b/netbox/dcim/models/device_component_templates.py @@ -44,12 +44,8 @@ class ComponentTemplateModel(ChangeLoggedModel, TrackingModelMixin): max_length=64, help_text=_( "{module} is accepted as a substitution for the module bay position when attached to a module type." - ) - ) - _name = NaturalOrderingField( - target_field='name', - max_length=100, - blank=True + ), + db_collation="natural_sort" ) label = models.CharField( verbose_name=_('label'), @@ -65,7 +61,7 @@ class ComponentTemplateModel(ChangeLoggedModel, TrackingModelMixin): class Meta: abstract = True - ordering = ('device_type', '_name') + ordering = ('device_type', 'name') constraints = ( models.UniqueConstraint( fields=('device_type', 'name'), @@ -125,7 +121,7 @@ class ModularComponentTemplateModel(ComponentTemplateModel): class Meta: abstract = True - ordering = ('device_type', 'module_type', '_name') + ordering = ('device_type', 'module_type', 'name') constraints = ( models.UniqueConstraint( fields=('device_type', 'name'), @@ -203,7 +199,8 @@ class ConsolePortTemplate(ModularComponentTemplateModel): verbose_name=_('type'), max_length=50, choices=ConsolePortTypeChoices, - blank=True + blank=True, + null=True ) component_model = ConsolePort @@ -237,7 +234,8 @@ class ConsoleServerPortTemplate(ModularComponentTemplateModel): verbose_name=_('type'), max_length=50, choices=ConsolePortTypeChoices, - blank=True + blank=True, + null=True ) component_model = ConsoleServerPort @@ -272,7 +270,8 @@ class PowerPortTemplate(ModularComponentTemplateModel): verbose_name=_('type'), max_length=50, choices=PowerPortTypeChoices, - blank=True + blank=True, + null=True ) maximum_draw = models.PositiveIntegerField( verbose_name=_('maximum draw'), @@ -312,7 +311,9 @@ class PowerPortTemplate(ModularComponentTemplateModel): if self.maximum_draw is not None and self.allocated_draw is not None: if self.allocated_draw > self.maximum_draw: raise ValidationError({ - 'allocated_draw': _("Allocated draw cannot exceed the maximum draw ({maximum_draw}W).").format(maximum_draw=self.maximum_draw) + 'allocated_draw': _( + "Allocated draw cannot exceed the maximum draw ({maximum_draw}W)." + ).format(maximum_draw=self.maximum_draw) }) def to_yaml(self): @@ -334,7 +335,8 @@ class PowerOutletTemplate(ModularComponentTemplateModel): verbose_name=_('type'), max_length=50, choices=PowerOutletTypeChoices, - blank=True + blank=True, + null=True ) power_port = models.ForeignKey( to='dcim.PowerPortTemplate', @@ -348,6 +350,7 @@ class PowerOutletTemplate(ModularComponentTemplateModel): max_length=50, choices=PowerOutletFeedLegChoices, blank=True, + null=True, help_text=_('Phase (for three-phase feeds)') ) @@ -364,11 +367,15 @@ class PowerOutletTemplate(ModularComponentTemplateModel): if self.power_port: if self.device_type and self.power_port.device_type != self.device_type: raise ValidationError( - _("Parent power port ({power_port}) must belong to the same device type").format(power_port=self.power_port) + _("Parent power port ({power_port}) must belong to the same device type").format( + power_port=self.power_port + ) ) if self.module_type and self.power_port.module_type != self.module_type: raise ValidationError( - _("Parent power port ({power_port}) must belong to the same module type").format(power_port=self.power_port) + _("Parent power port ({power_port}) must belong to the same module type").format( + power_port=self.power_port + ) ) def instantiate(self, **kwargs): @@ -434,18 +441,21 @@ class InterfaceTemplate(ModularComponentTemplateModel): max_length=50, choices=InterfacePoEModeChoices, blank=True, + null=True, verbose_name=_('PoE mode') ) poe_type = models.CharField( max_length=50, choices=InterfacePoETypeChoices, blank=True, + null=True, verbose_name=_('PoE type') ) rf_role = models.CharField( max_length=30, choices=WirelessRoleChoices, blank=True, + null=True, verbose_name=_('wireless role') ) @@ -463,11 +473,15 @@ class InterfaceTemplate(ModularComponentTemplateModel): raise ValidationError({'bridge': _("An interface cannot be bridged to itself.")}) if self.device_type and self.device_type != self.bridge.device_type: raise ValidationError({ - 'bridge': _("Bridge interface ({bridge}) must belong to the same device type").format(bridge=self.bridge) + 'bridge': _( + "Bridge interface ({bridge}) must belong to the same device type" + ).format(bridge=self.bridge) }) if self.module_type and self.module_type != self.bridge.module_type: raise ValidationError({ - 'bridge': _("Bridge interface ({bridge}) must belong to the same module type").format(bridge=self.bridge) + 'bridge': _( + "Bridge interface ({bridge}) must belong to the same module type" + ).format(bridge=self.bridge) }) if self.rf_role and self.type not in WIRELESS_IFACE_TYPES: @@ -710,7 +724,9 @@ class DeviceBayTemplate(ComponentTemplateModel): def clean(self): if self.device_type and self.device_type.subdevice_role != SubdeviceRoleChoices.ROLE_PARENT: raise ValidationError( - _("Subdevice role of device type ({device_type}) must be set to \"parent\" to allow device bays.").format(device_type=self.device_type) + _( + 'Subdevice role of device type ({device_type}) must be set to "parent" to allow device bays.' + ).format(device_type=self.device_type) ) def to_yaml(self): @@ -774,7 +790,7 @@ class InventoryItemTemplate(MPTTModel, ComponentTemplateModel): component_model = InventoryItem class Meta: - ordering = ('device_type__id', 'parent__id', '_name') + ordering = ('device_type__id', 'parent__id', 'name') indexes = ( models.Index(fields=('component_type', 'component_id')), ) diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index 1a86a250c..ce9e5607f 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -10,7 +10,7 @@ from mptt.models import MPTTModel, TreeForeignKey from dcim.choices import * from dcim.constants import * -from dcim.fields import MACAddressField, WWNField +from dcim.fields import WWNField from netbox.choices import ColorChoices from netbox.models import OrganizationalModel, NetBoxModel from utilities.fields import ColorField, NaturalOrderingField @@ -50,12 +50,8 @@ class ComponentModel(NetBoxModel): ) name = models.CharField( verbose_name=_('name'), - max_length=64 - ) - _name = NaturalOrderingField( - target_field='name', - max_length=100, - blank=True + max_length=64, + db_collation="natural_sort" ) label = models.CharField( verbose_name=_('label'), @@ -71,7 +67,7 @@ class ComponentModel(NetBoxModel): class Meta: abstract = True - ordering = ('device', '_name') + ordering = ('device', 'name') constraints = ( models.UniqueConstraint( fields=('device', 'name'), @@ -142,8 +138,9 @@ class CabledObjectModel(models.Model): cable_end = models.CharField( verbose_name=_('cable end'), max_length=1, + choices=CableEndChoices, blank=True, - choices=CableEndChoices + null=True ) mark_connected = models.BooleanField( verbose_name=_('mark connected'), @@ -283,6 +280,7 @@ class ConsolePort(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki max_length=50, choices=ConsolePortTypeChoices, blank=True, + null=True, help_text=_('Physical port type') ) speed = models.PositiveIntegerField( @@ -309,6 +307,7 @@ class ConsoleServerPort(ModularComponentModel, CabledObjectModel, PathEndpoint, max_length=50, choices=ConsolePortTypeChoices, blank=True, + null=True, help_text=_('Physical port type') ) speed = models.PositiveIntegerField( @@ -339,6 +338,7 @@ class PowerPort(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracking max_length=50, choices=PowerPortTypeChoices, blank=True, + null=True, help_text=_('Physical port type') ) maximum_draw = models.PositiveIntegerField( @@ -454,6 +454,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki max_length=50, choices=PowerOutletTypeChoices, blank=True, + null=True, help_text=_('Physical port type') ) power_port = models.ForeignKey( @@ -468,6 +469,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki max_length=50, choices=PowerOutletFeedLegChoices, blank=True, + null=True, help_text=_('Phase (for three-phase feeds)') ) color = ColorField( @@ -503,11 +505,6 @@ class BaseInterface(models.Model): verbose_name=_('enabled'), default=True ) - mac_address = MACAddressField( - null=True, - blank=True, - verbose_name=_('MAC address') - ) mtu = models.PositiveIntegerField( blank=True, null=True, @@ -522,6 +519,7 @@ class BaseInterface(models.Model): max_length=50, choices=InterfaceModeChoices, blank=True, + null=True, help_text=_('IEEE 802.1Q tagging strategy') ) parent = models.ForeignKey( @@ -540,10 +538,64 @@ class BaseInterface(models.Model): blank=True, verbose_name=_('bridge interface') ) + untagged_vlan = models.ForeignKey( + to='ipam.VLAN', + on_delete=models.SET_NULL, + related_name='%(class)ss_as_untagged', + null=True, + blank=True, + verbose_name=_('untagged VLAN') + ) + tagged_vlans = models.ManyToManyField( + to='ipam.VLAN', + related_name='%(class)ss_as_tagged', + blank=True, + verbose_name=_('tagged VLANs') + ) + qinq_svlan = models.ForeignKey( + to='ipam.VLAN', + on_delete=models.SET_NULL, + related_name='%(class)ss_svlan', + null=True, + blank=True, + verbose_name=_('Q-in-Q SVLAN') + ) + vlan_translation_policy = models.ForeignKey( + to='ipam.VLANTranslationPolicy', + on_delete=models.PROTECT, + null=True, + blank=True, + verbose_name=_('VLAN Translation Policy') + ) + primary_mac_address = models.OneToOneField( + to='dcim.MACAddress', + on_delete=models.SET_NULL, + related_name='+', + blank=True, + null=True, + verbose_name=_('primary MAC address') + ) class Meta: abstract = True + def clean(self): + super().clean() + + # SVLAN can be defined only for Q-in-Q interfaces + if self.qinq_svlan and self.mode != InterfaceModeChoices.MODE_Q_IN_Q: + raise ValidationError({ + 'qinq_svlan': _("Only Q-in-Q interfaces may specify a service VLAN.") + }) + + # Check that the primary MAC address (if any) is assigned to this interface + if self.primary_mac_address and self.primary_mac_address.assigned_object != self: + raise ValidationError({ + 'primary_mac_address': _("MAC address {mac_address} is not assigned to this interface.").format( + mac_address=self.primary_mac_address + ) + }) + def save(self, *args, **kwargs): # Remove untagged VLAN assignment for non-802.1Q interfaces @@ -568,6 +620,11 @@ class BaseInterface(models.Model): def count_fhrp_groups(self): return self.fhrp_group_assignments.count() + @cached_property + def mac_address(self): + if self.primary_mac_address: + return self.primary_mac_address.mac_address + class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEndpoint, TrackingModelMixin): """ @@ -624,12 +681,14 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd max_length=30, choices=WirelessRoleChoices, blank=True, + null=True, verbose_name=_('wireless role') ) rf_channel = models.CharField( max_length=50, choices=WirelessChannelChoices, blank=True, + null=True, verbose_name=_('wireless channel') ) rf_channel_frequency = models.DecimalField( @@ -658,12 +717,14 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd max_length=50, choices=InterfacePoEModeChoices, blank=True, + null=True, verbose_name=_('PoE mode') ) poe_type = models.CharField( max_length=50, choices=InterfacePoETypeChoices, blank=True, + null=True, verbose_name=_('PoE type') ) wireless_link = models.ForeignKey( @@ -679,20 +740,6 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd blank=True, verbose_name=_('wireless LANs') ) - untagged_vlan = models.ForeignKey( - to='ipam.VLAN', - on_delete=models.SET_NULL, - related_name='interfaces_as_untagged', - null=True, - blank=True, - verbose_name=_('untagged VLAN') - ) - tagged_vlans = models.ManyToManyField( - to='ipam.VLAN', - related_name='interfaces_as_tagged', - blank=True, - verbose_name=_('tagged VLANs') - ) vrf = models.ForeignKey( to='ipam.VRF', on_delete=models.SET_NULL, @@ -707,6 +754,12 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd object_id_field='assigned_object_id', related_query_name='interface' ) + mac_addresses = GenericRelation( + to='dcim.MACAddress', + content_type_field='assigned_object_type', + object_id_field='assigned_object_id', + related_query_name='interface' + ) fhrp_group_assignments = GenericRelation( to='ipam.FHRPGroupAssignment', content_type_field='interface_type', @@ -945,6 +998,14 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd def l2vpn_termination(self): return self.l2vpn_terminations.first() + @cached_property + def connected_endpoints(self): + # If this is a virtual interface, return the remote endpoint of the connected + # virtual circuit, if any. + if self.is_virtual and hasattr(self, 'virtual_circuit_termination'): + return self.virtual_circuit_termination.peer_terminations + return super().connected_endpoints + # # Pass-through ports @@ -1266,7 +1327,7 @@ class InventoryItem(MPTTModel, ComponentModel, TrackingModelMixin): clone_fields = ('device', 'parent', 'role', 'manufacturer', 'status', 'part_id') class Meta: - ordering = ('device__id', 'parent__id', '_name') + ordering = ('device__id', 'parent__id', 'name') indexes = ( models.Index(fields=('component_type', 'component_id')), ) diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index e472303a6..dbcd91ea0 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -3,6 +3,7 @@ import yaml from functools import cached_property +from django.contrib.contenttypes.fields import GenericForeignKey from django.core.exceptions import ValidationError from django.core.files.storage import default_storage from django.core.validators import MaxValueValidator, MinValueValidator @@ -16,6 +17,7 @@ from django.utils.translation import gettext_lazy as _ from dcim.choices import * from dcim.constants import * +from dcim.fields import MACAddressField from extras.models import ConfigContextModel, CustomField from extras.querysets import ConfigContextModelQuerySet from netbox.choices import ColorChoices @@ -23,7 +25,7 @@ from netbox.config import ConfigItem from netbox.models import OrganizationalModel, PrimaryModel from netbox.models.mixins import WeightMixin from netbox.models.features import ContactsMixin, ImageAttachmentsMixin -from utilities.fields import ColorField, CounterCacheField, NaturalOrderingField +from utilities.fields import ColorField, CounterCacheField from utilities.tracking import TrackingModelMixin from .device_components import * from .mixins import RenderConfigMixin @@ -33,6 +35,7 @@ __all__ = ( 'Device', 'DeviceRole', 'DeviceType', + 'MACAddress', 'Manufacturer', 'Module', 'ModuleType', @@ -118,6 +121,7 @@ class DeviceType(ImageAttachmentsMixin, PrimaryModel, WeightMixin): max_length=50, choices=SubdeviceRoleChoices, blank=True, + null=True, verbose_name=_('parent/child status'), help_text=_('Parent devices house child devices in device bays. Leave blank ' 'if this device type is neither a parent nor a child.') @@ -126,7 +130,8 @@ class DeviceType(ImageAttachmentsMixin, PrimaryModel, WeightMixin): verbose_name=_('airflow'), max_length=50, choices=DeviceAirflowChoices, - blank=True + blank=True, + null=True ) front_image = models.ImageField( upload_to='devicetype-images', @@ -387,7 +392,8 @@ class ModuleType(ImageAttachmentsMixin, PrimaryModel, WeightMixin): verbose_name=_('airflow'), max_length=50, choices=ModuleAirflowChoices, - blank=True + blank=True, + null=True ) clone_fields = ('manufacturer', 'weight', 'weight_unit', 'airflow') @@ -526,7 +532,10 @@ def update_interface_bridges(device, interface_templates, module=None): interface = Interface.objects.get(device=device, name=interface_template.resolve_name(module=module)) if interface_template.bridge: - interface.bridge = Interface.objects.get(device=device, name=interface_template.bridge.resolve_name(module=module)) + interface.bridge = Interface.objects.get( + device=device, + name=interface_template.bridge.resolve_name(module=module) + ) interface.full_clean() interface.save() @@ -579,13 +588,8 @@ class Device( verbose_name=_('name'), max_length=64, blank=True, - null=True - ) - _name = NaturalOrderingField( - target_field='name', - max_length=100, - blank=True, - null=True + null=True, + db_collation="natural_sort" ) serial = models.CharField( max_length=50, @@ -632,6 +636,7 @@ class Device( face = models.CharField( max_length=50, blank=True, + null=True, choices=DeviceFaceChoices, verbose_name=_('rack face') ) @@ -645,7 +650,8 @@ class Device( verbose_name=_('airflow'), max_length=50, choices=DeviceAirflowChoices, - blank=True + blank=True, + null=True ) primary_ip4 = models.OneToOneField( to='ipam.IPAddress', @@ -770,7 +776,7 @@ class Device( ) class Meta: - ordering = ('_name', 'pk') # Name may be null + ordering = ('name', 'pk') # Name may be null constraints = ( models.UniqueConstraint( Lower('name'), 'site', 'tenant', @@ -906,7 +912,10 @@ class Device( }) if self.primary_ip4.assigned_object in vc_interfaces: pass - elif self.primary_ip4.nat_inside is not None and self.primary_ip4.nat_inside.assigned_object in vc_interfaces: + elif ( + self.primary_ip4.nat_inside is not None and + self.primary_ip4.nat_inside.assigned_object in vc_interfaces + ): pass else: raise ValidationError({ @@ -921,7 +930,10 @@ class Device( }) if self.primary_ip6.assigned_object in vc_interfaces: pass - elif self.primary_ip6.nat_inside is not None and self.primary_ip6.nat_inside.assigned_object in vc_interfaces: + elif ( + self.primary_ip6.nat_inside is not None and + self.primary_ip6.nat_inside.assigned_object in vc_interfaces + ): pass else: raise ValidationError({ @@ -953,10 +965,17 @@ class Device( }) # A Device can only be assigned to a Cluster in the same Site (or no Site) - if self.cluster and self.cluster.site is not None and self.cluster.site != self.site: + if self.cluster and self.cluster._site is not None and self.cluster._site != self.site: raise ValidationError({ 'cluster': _("The assigned cluster belongs to a different site ({site})").format( - site=self.cluster.site + site=self.cluster._site + ) + }) + + if self.cluster and self.cluster._location is not None and self.cluster._location != self.location: + raise ValidationError({ + 'cluster': _("The assigned cluster belongs to a different location ({location})").format( + site=self.cluster._location ) }) @@ -968,9 +987,10 @@ class Device( if hasattr(self, 'vc_master_for') and self.vc_master_for and self.vc_master_for != self.virtual_chassis: raise ValidationError({ - 'virtual_chassis': _('Device cannot be removed from virtual chassis {virtual_chassis} because it is currently designated as its master.').format( - virtual_chassis=self.vc_master_for - ) + 'virtual_chassis': _( + 'Device cannot be removed from virtual chassis {virtual_chassis} because it is currently ' + 'designated as its master.' + ).format(virtual_chassis=self.vc_master_for) }) def _instantiate_components(self, queryset, bulk_create=True): @@ -1257,6 +1277,11 @@ class Module(PrimaryModel, ConfigContextModel): if not disable_replication: create_instances.append(template_instance) + # Set default values for any applicable custom fields + if cf_defaults := CustomField.objects.get_defaults_for_model(component_model): + for component in create_instances: + component.custom_field_data = cf_defaults + if component_model is not ModuleBay: component_model.objects.bulk_create(create_instances) # Emit the post_save signal for each newly created object @@ -1308,7 +1333,8 @@ class VirtualChassis(PrimaryModel): ) name = models.CharField( verbose_name=_('name'), - max_length=64 + max_length=64, + db_collation="natural_sort" ) domain = models.CharField( verbose_name=_('domain'), @@ -1370,7 +1396,8 @@ class VirtualDeviceContext(PrimaryModel): ) name = models.CharField( verbose_name=_('name'), - max_length=64 + max_length=64, + db_collation="natural_sort" ) status = models.CharField( verbose_name=_('status'), @@ -1461,3 +1488,37 @@ class VirtualDeviceContext(PrimaryModel): raise ValidationError({ f'primary_ip{family}': _('Primary IP address must belong to an interface on the assigned device.') }) + + +# +# Addressing +# + +class MACAddress(PrimaryModel): + mac_address = MACAddressField( + verbose_name=_('MAC address') + ) + assigned_object_type = models.ForeignKey( + to='contenttypes.ContentType', + limit_choices_to=MACADDRESS_ASSIGNMENT_MODELS, + on_delete=models.PROTECT, + related_name='+', + blank=True, + null=True + ) + assigned_object_id = models.PositiveBigIntegerField( + blank=True, + null=True + ) + assigned_object = GenericForeignKey( + ct_field='assigned_object_type', + fk_field='assigned_object_id' + ) + + class Meta: + ordering = ('mac_address',) + verbose_name = _('MAC address') + verbose_name_plural = _('MAC addresses') + + def __str__(self): + return str(self.mac_address) diff --git a/netbox/dcim/models/mixins.py b/netbox/dcim/models/mixins.py index c9be451a0..a0fc15a25 100644 --- a/netbox/dcim/models/mixins.py +++ b/netbox/dcim/models/mixins.py @@ -1,6 +1,12 @@ +from django.apps import apps +from django.contrib.contenttypes.fields import GenericForeignKey +from django.core.exceptions import ValidationError from django.db import models +from django.utils.translation import gettext_lazy as _ +from dcim.constants import LOCATION_SCOPE_TYPES __all__ = ( + 'CachedScopeMixin', 'RenderConfigMixin', ) @@ -27,3 +33,90 @@ class RenderConfigMixin(models.Model): return self.role.config_template if self.platform and self.platform.config_template: return self.platform.config_template + + +class CachedScopeMixin(models.Model): + """ + Mixin for adding a GenericForeignKey scope to a model that can point to a Region, SiteGroup, Site, or Location. + Includes cached fields for each to allow efficient filtering. Appropriate validation must be done in the clean() + method as this does not have any as validation is generally model-specific. + """ + scope_type = models.ForeignKey( + to='contenttypes.ContentType', + on_delete=models.PROTECT, + limit_choices_to=models.Q(model__in=LOCATION_SCOPE_TYPES), + related_name='+', + blank=True, + null=True + ) + scope_id = models.PositiveBigIntegerField( + blank=True, + null=True + ) + scope = GenericForeignKey( + ct_field='scope_type', + fk_field='scope_id' + ) + + _location = models.ForeignKey( + to='dcim.Location', + on_delete=models.CASCADE, + blank=True, + null=True + ) + _site = models.ForeignKey( + to='dcim.Site', + on_delete=models.CASCADE, + blank=True, + null=True + ) + _region = models.ForeignKey( + to='dcim.Region', + on_delete=models.CASCADE, + blank=True, + null=True + ) + _site_group = models.ForeignKey( + to='dcim.SiteGroup', + on_delete=models.CASCADE, + blank=True, + null=True + ) + + class Meta: + abstract = True + + def clean(self): + if self.scope_type and not self.scope: + scope_type = self.scope_type.model_class() + raise ValidationError({ + 'scope': _( + "Please select a {scope_type}." + ).format(scope_type=scope_type._meta.model_name) + }) + super().clean() + + def save(self, *args, **kwargs): + # Cache objects associated with the terminating object (for filtering) + self.cache_related_objects() + + super().save(*args, **kwargs) + + def cache_related_objects(self): + self._region = self._site_group = self._site = self._location = None + if self.scope_type: + scope_type = self.scope_type.model_class() + if scope_type == apps.get_model('dcim', 'region'): + self._region = self.scope + elif scope_type == apps.get_model('dcim', 'sitegroup'): + self._site_group = self.scope + elif scope_type == apps.get_model('dcim', 'site'): + self._region = self.scope.region + self._site_group = self.scope.group + self._site = self.scope + elif scope_type == apps.get_model('dcim', 'location'): + self._region = self.scope.site.region + self._site_group = self.scope.site.group + self._site = self.scope.site + self._location = self.scope + cache_related_objects.alters_data = True diff --git a/netbox/dcim/models/power.py b/netbox/dcim/models/power.py index d0c6b18b6..284cfe832 100644 --- a/netbox/dcim/models/power.py +++ b/netbox/dcim/models/power.py @@ -36,7 +36,8 @@ class PowerPanel(ContactsMixin, ImageAttachmentsMixin, PrimaryModel): ) name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) prerequisite_models = ( @@ -86,7 +87,8 @@ class PowerFeed(PrimaryModel, PathEndpoint, CabledObjectModel): ) name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) status = models.CharField( verbose_name=_('status'), diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index ae5513fea..78eb0ea4a 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -19,7 +19,7 @@ from netbox.models.mixins import WeightMixin from netbox.models.features import ContactsMixin, ImageAttachmentsMixin from utilities.conversion import to_grams from utilities.data import array_to_string, drange -from utilities.fields import ColorField, NaturalOrderingField +from utilities.fields import ColorField from .device_components import PowerPort from .devices import Device, Module from .power import PowerFeed @@ -83,7 +83,8 @@ class RackBase(WeightMixin, PrimaryModel): verbose_name=_('outer unit'), max_length=50, choices=RackDimensionUnitChoices, - blank=True + blank=True, + null=True ) mounting_depth = models.PositiveSmallIntegerField( verbose_name=_('mounting depth'), @@ -188,7 +189,7 @@ class RackType(RackBase): # Clear unit if outer width & depth are not set if self.outer_width is None and self.outer_depth is None: - self.outer_unit = '' + self.outer_unit = None super().save(*args, **kwargs) @@ -242,6 +243,7 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase): choices=RackFormFactorChoices, max_length=50, blank=True, + null=True, verbose_name=_('form factor') ) rack_type = models.ForeignKey( @@ -253,12 +255,8 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase): ) name = models.CharField( verbose_name=_('name'), - max_length=100 - ) - _name = NaturalOrderingField( - target_field='name', max_length=100, - blank=True + db_collation="natural_sort" ) facility_id = models.CharField( max_length=50, @@ -317,7 +315,8 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase): verbose_name=_('airflow'), max_length=50, choices=RackAirflowChoices, - blank=True + blank=True, + null=True ) # Generic relations @@ -337,7 +336,7 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase): ) class Meta: - ordering = ('site', 'location', '_name', 'pk') # (site, location, name) may be non-unique + ordering = ('site', 'location', 'name', 'pk') # (site, location, name) may be non-unique constraints = ( # Name and facility_id must be unique *only* within a Location models.UniqueConstraint( @@ -380,7 +379,9 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase): min_height = top_device.position + top_device.device_type.u_height - self.starting_unit if self.u_height < min_height: raise ValidationError({ - 'u_height': _("Rack must be at least {min_height}U tall to house currently installed devices.").format(min_height=min_height) + 'u_height': _( + "Rack must be at least {min_height}U tall to house currently installed devices." + ).format(min_height=min_height) }) # Validate that the Rack's starting unit is less than or equal to the position of the lowest mounted Device @@ -409,7 +410,7 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase): # Clear unit if outer width & depth are not set if self.outer_width is None and self.outer_depth is None: - self.outer_unit = '' + self.outer_unit = None super().save(*args, **kwargs) diff --git a/netbox/dcim/models/sites.py b/netbox/dcim/models/sites.py index 37f59045d..7880a067f 100644 --- a/netbox/dcim/models/sites.py +++ b/netbox/dcim/models/sites.py @@ -8,7 +8,6 @@ from dcim.choices import * from dcim.constants import * from netbox.models import NestedGroupModel, PrimaryModel from netbox.models.features import ContactsMixin, ImageAttachmentsMixin -from utilities.fields import NaturalOrderingField __all__ = ( 'Location', @@ -28,6 +27,12 @@ class Region(ContactsMixin, NestedGroupModel): states, and/or cities. Regions are recursively nested into a hierarchy: all sites belonging to a child region are also considered to be members of its parent and ancestor region(s). """ + prefixes = GenericRelation( + to='ipam.Prefix', + content_type_field='scope_type', + object_id_field='scope_id', + related_query_name='region' + ) vlan_groups = GenericRelation( to='ipam.VLANGroup', content_type_field='scope_type', @@ -78,6 +83,12 @@ class SiteGroup(ContactsMixin, NestedGroupModel): within corporate sites you might distinguish between offices and data centers. Like regions, site groups can be nested recursively to form a hierarchy. """ + prefixes = GenericRelation( + to='ipam.Prefix', + content_type_field='scope_type', + object_id_field='scope_id', + related_query_name='site_group' + ) vlan_groups = GenericRelation( to='ipam.VLANGroup', content_type_field='scope_type', @@ -131,12 +142,8 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel): verbose_name=_('name'), max_length=100, unique=True, - help_text=_("Full name of the site") - ) - _name = NaturalOrderingField( - target_field='name', - max_length=100, - blank=True + help_text=_("Full name of the site"), + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), @@ -182,7 +189,8 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel): blank=True ) time_zone = TimeZoneField( - blank=True + blank=True, + null=True ) physical_address = models.CharField( verbose_name=_('physical address'), @@ -214,6 +222,12 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel): ) # Generic relations + prefixes = GenericRelation( + to='ipam.Prefix', + content_type_field='scope_type', + object_id_field='scope_id', + related_query_name='site' + ) vlan_groups = GenericRelation( to='ipam.VLANGroup', content_type_field='scope_type', @@ -227,7 +241,7 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel): ) class Meta: - ordering = ('_name',) + ordering = ('name',) verbose_name = _('site') verbose_name_plural = _('sites') @@ -273,6 +287,12 @@ class Location(ContactsMixin, ImageAttachmentsMixin, NestedGroupModel): ) # Generic relations + prefixes = GenericRelation( + to='ipam.Prefix', + content_type_field='scope_type', + object_id_field='scope_id', + related_query_name='location' + ) vlan_groups = GenericRelation( to='ipam.VLANGroup', content_type_field='scope_type', diff --git a/netbox/dcim/search.py b/netbox/dcim/search.py index 45431cb05..b964421de 100644 --- a/netbox/dcim/search.py +++ b/netbox/dcim/search.py @@ -98,19 +98,28 @@ class FrontPortIndex(SearchIndex): display_attrs = ('device', 'label', 'type', 'description') +@register_search +class MACAddressIndex(SearchIndex): + model = models.MACAddress + fields = ( + ('mac_address', 100), + ('description', 500), + ) + display_attrs = ('assigned_object', 'description') + + @register_search class InterfaceIndex(SearchIndex): model = models.Interface fields = ( ('name', 100), ('label', 200), - ('mac_address', 300), ('wwn', 300), ('description', 500), ('mtu', 2000), ('speed', 2000), ) - display_attrs = ('device', 'label', 'type', 'mac_address', 'wwn', 'description') + display_attrs = ('device', 'label', 'type', 'wwn', 'description') @register_search diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index a51872719..6c213d64c 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -85,7 +85,8 @@ def update_connected_endpoints(instance, created, raw=False, **kwargs): if instance._terminations_modified: a_terminations = [] b_terminations = [] - for t in instance.terminations.all(): + # Note: instance.terminations.all() is not safe to use here as it might be stale + for t in CableTermination.objects.filter(cable=instance): if t.cable_end == CableEndChoices.SIDE_A: a_terminations.append(t.termination) else: diff --git a/netbox/dcim/svg/cables.py b/netbox/dcim/svg/cables.py index 4e0f7aea6..58fa27c6b 100644 --- a/netbox/dcim/svg/cables.py +++ b/netbox/dcim/svg/cables.py @@ -362,7 +362,7 @@ class CableTraceSVG: self.cursor += CABLE_HEIGHT # Connector (a Cable or WirelessLink) - if links: + if links and far_ends: obj_list = {end.parent_object for end in far_ends} parent_object_nodes, far_terminations = self.draw_far_objects(obj_list, far_ends) diff --git a/netbox/dcim/svg/racks.py b/netbox/dcim/svg/racks.py index 0f73095b5..94dbeeac2 100644 --- a/netbox/dcim/svg/racks.py +++ b/netbox/dcim/svg/racks.py @@ -48,6 +48,7 @@ def get_device_description(device): Name: Role: + Status: Device Type: () Asset tag: (if defined) Serial: (if defined) @@ -55,6 +56,7 @@ def get_device_description(device): """ description = f'Name: {device.name}' description += f'\nRole: {device.role}' + description += f'\nStatus: {device.get_status_display()}' u_height = f'{floatformat(device.device_type.u_height)}U' description += f'\nDevice Type: {device.device_type.manufacturer.name} {device.device_type.model} ({u_height})' if device.asset_tag: @@ -153,7 +155,10 @@ class RackElevationSVG: if self.rack.desc_units: y += int((position - self.rack.starting_unit) * self.unit_height) else: - y += int((self.rack.u_height - position + self.rack.starting_unit) * self.unit_height) - int(height * self.unit_height) + y += ( + int((self.rack.u_height - position + self.rack.starting_unit) * self.unit_height) - + int(height * self.unit_height) + ) return x, y diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index b39a2b87f..087132331 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -29,6 +29,7 @@ __all__ = ( 'InterfaceTable', 'InventoryItemRoleTable', 'InventoryItemTable', + 'MACAddressTable', 'ModuleBayTable', 'PlatformTable', 'PowerOutletTable', @@ -42,6 +43,16 @@ MODULEBAY_STATUS = """ {% badge record.installed_module.get_status_display bg_color=record.installed_module.get_status_color %} """ +MACADDRESS_LINK = """ +{% if record.pk %} + {{ record.mac_address }} +{% endif %} +""" + +MACADDRESS_COPY_BUTTON = """ +{% copy_content record.pk prefix="macaddress_" %} +""" + # # Device roles @@ -132,7 +143,6 @@ class PlatformTable(NetBoxTable): class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): name = tables.TemplateColumn( verbose_name=_('Name'), - order_by=('_name',), template_code=DEVICE_LINK, linkify=True ) @@ -288,7 +298,6 @@ class DeviceComponentTable(NetBoxTable): name = tables.Column( verbose_name=_('Name'), linkify=True, - order_by=('_name',) ) device_status = columns.ChoiceFieldColumn( accessor=tables.A('device__status'), @@ -382,7 +391,8 @@ class ConsolePortTable(ModularDeviceComponentTable, PathEndpointTable): model = models.ConsolePort fields = ( 'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'type', 'speed', 'description', - 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'inventory_items', 'tags', 'created', 'last_updated', + 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'inventory_items', 'tags', 'created', + 'last_updated', ) default_columns = ('pk', 'name', 'device', 'label', 'type', 'speed', 'description') @@ -391,7 +401,6 @@ class DeviceConsolePortTable(ConsolePortTable): name = tables.TemplateColumn( verbose_name=_('Name'), template_code=' {{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -423,7 +432,8 @@ class ConsoleServerPortTable(ModularDeviceComponentTable, PathEndpointTable): model = models.ConsoleServerPort fields = ( 'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'type', 'speed', 'description', - 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'inventory_items', 'tags', 'created', 'last_updated', + 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'inventory_items', 'tags', 'created', + 'last_updated', ) default_columns = ('pk', 'name', 'device', 'label', 'type', 'speed', 'description') @@ -433,7 +443,6 @@ class DeviceConsoleServerPortTable(ConsoleServerPortTable): verbose_name=_('Name'), template_code=' ' '{{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -482,7 +491,6 @@ class DevicePowerPortTable(PowerPortTable): verbose_name=_('Name'), template_code=' ' '{{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -531,7 +539,6 @@ class DevicePowerOutletTable(PowerOutletTable): name = tables.TemplateColumn( verbose_name=_('Name'), template_code=' {{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -550,6 +557,11 @@ class DevicePowerOutletTable(PowerOutletTable): class BaseInterfaceTable(NetBoxTable): + name = tables.Column( + verbose_name=_('Name'), + linkify=True, + order_by=('_name',) + ) enabled = columns.BooleanColumn( verbose_name=_('Enabled'), ) @@ -585,6 +597,14 @@ class BaseInterfaceTable(NetBoxTable): orderable=False, verbose_name=_('Tagged VLANs') ) + qinq_svlan = tables.Column( + verbose_name=_('Q-in-Q SVLAN'), + linkify=True + ) + primary_mac_address = tables.Column( + verbose_name=_('MAC Address'), + linkify=True + ) def value_ip_addresses(self, value): return ",".join([str(obj.address) for obj in value.all()]) @@ -593,7 +613,7 @@ class BaseInterfaceTable(NetBoxTable): return ",".join([str(obj) for obj in value.all()]) -class InterfaceTable(ModularDeviceComponentTable, BaseInterfaceTable, PathEndpointTable): +class InterfaceTable(BaseInterfaceTable, ModularDeviceComponentTable, PathEndpointTable): device = tables.Column( verbose_name=_('Device'), linkify={ @@ -627,19 +647,31 @@ class InterfaceTable(ModularDeviceComponentTable, BaseInterfaceTable, PathEndpoi verbose_name=_('VRF'), linkify=True ) + virtual_circuit_termination = tables.Column( + verbose_name=_('Virtual Circuit'), + linkify=True + ) tags = columns.TagColumn( url_name='dcim:interface_list' ) + # Override PathEndpointTable.connection to accommodate virtual circuits + connection = columns.TemplateColumn( + accessor='_path__destinations', + template_code=INTERFACE_LINKTERMINATION, + verbose_name=_('Connection'), + orderable=False + ) + class Meta(DeviceComponentTable.Meta): model = models.Interface fields = ( 'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', - 'speed', 'speed_formatted', 'duplex', 'mode', 'mac_address', 'wwn', 'poe_mode', 'poe_type', 'rf_role', 'rf_channel', - 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description', 'mark_connected', 'cable', - 'cable_color', 'wireless_link', 'wireless_lans', 'link_peer', 'connection', 'tags', 'vdcs', 'vrf', 'l2vpn', - 'tunnel', 'ip_addresses', 'fhrp_groups', 'untagged_vlan', 'tagged_vlans', 'inventory_items', 'created', - 'last_updated', + 'speed', 'speed_formatted', 'duplex', 'mode', 'primary_mac_address', 'wwn', 'poe_mode', 'poe_type', + 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description', + 'mark_connected', 'cable', 'cable_color', 'wireless_link', 'wireless_lans', 'link_peer', 'connection', + 'tags', 'vdcs', 'vrf', 'l2vpn', 'tunnel', 'ip_addresses', 'fhrp_groups', 'untagged_vlan', 'tagged_vlans', + 'qinq_svlan', 'inventory_items', 'created', 'last_updated', ) default_columns = ('pk', 'name', 'device', 'label', 'enabled', 'type', 'description') @@ -676,7 +708,7 @@ class DeviceInterfaceTable(InterfaceTable): 'mgmt_only', 'mtu', 'mode', 'mac_address', 'wwn', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description', 'mark_connected', 'cable', 'cable_color', 'wireless_link', 'wireless_lans', 'link_peer', 'connection', 'tags', 'vdcs', 'vrf', 'l2vpn', 'tunnel', 'ip_addresses', - 'fhrp_groups', 'untagged_vlan', 'tagged_vlans', 'actions', + 'fhrp_groups', 'untagged_vlan', 'tagged_vlans', 'qinq_svlan', 'actions', ) default_columns = ( 'pk', 'name', 'label', 'enabled', 'type', 'parent', 'lag', 'mtu', 'mode', 'description', 'ip_addresses', @@ -732,7 +764,6 @@ class DeviceFrontPortTable(FrontPortTable): verbose_name=_('Name'), template_code=' ' '{{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -779,7 +810,6 @@ class DeviceRearPortTable(RearPortTable): verbose_name=_('Name'), template_code=' ' '{{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -842,7 +872,6 @@ class DeviceDeviceBayTable(DeviceBayTable): verbose_name=_('Name'), template_code=' {{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) actions = columns.ActionsColumn( @@ -911,7 +940,6 @@ class DeviceModuleBayTable(ModuleBayTable): name = columns.MPTTColumn( verbose_name=_('Name'), linkify=True, - order_by=Accessor('_name') ) actions = columns.ActionsColumn( extra_buttons=MODULEBAY_BUTTONS @@ -965,8 +993,8 @@ class InventoryItemTable(DeviceComponentTable): class Meta(NetBoxTable.Meta): model = models.InventoryItem fields = ( - 'pk', 'id', 'name', 'device', 'parent', 'component', 'label', 'status', 'role', 'manufacturer', 'part_id', 'serial', - 'asset_tag', 'description', 'discovered', 'tags', 'created', 'last_updated', + 'pk', 'id', 'name', 'device', 'parent', 'component', 'label', 'status', 'role', 'manufacturer', 'part_id', + 'serial', 'asset_tag', 'description', 'discovered', 'tags', 'created', 'last_updated', ) default_columns = ( 'pk', 'name', 'device', 'label', 'status', 'role', 'manufacturer', 'part_id', 'serial', 'asset_tag', @@ -978,15 +1006,14 @@ class DeviceInventoryItemTable(InventoryItemTable): verbose_name=_('Name'), template_code='' '{{ value }}', - order_by=Accessor('_name'), attrs={'td': {'class': 'text-nowrap'}} ) class Meta(NetBoxTable.Meta): model = models.InventoryItem fields = ( - 'pk', 'id', 'name', 'label', 'status', 'role', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'component', - 'description', 'discovered', 'tags', 'actions', + 'pk', 'id', 'name', 'label', 'status', 'role', 'manufacturer', 'part_id', 'serial', 'asset_tag', + 'component', 'description', 'discovered', 'tags', 'actions', ) default_columns = ( 'pk', 'name', 'label', 'status', 'role', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'component', @@ -1100,3 +1127,35 @@ class VirtualDeviceContextTable(TenancyColumnsMixin, NetBoxTable): default_columns = ( 'pk', 'name', 'identifier', 'status', 'tenant', 'primary_ip', ) + + +class MACAddressTable(NetBoxTable): + mac_address = tables.TemplateColumn( + template_code=MACADDRESS_LINK, + verbose_name=_('MAC Address') + ) + assigned_object = tables.Column( + linkify=True, + orderable=False, + verbose_name=_('Interface') + ) + assigned_object_parent = tables.Column( + accessor='assigned_object__parent_object', + linkify=True, + orderable=False, + verbose_name=_('Parent') + ) + tags = columns.TagColumn( + url_name='dcim:macaddress_list' + ) + actions = columns.ActionsColumn( + extra_buttons=MACADDRESS_COPY_BUTTON + ) + + class Meta(DeviceComponentTable.Meta): + model = models.MACAddress + fields = ( + 'pk', 'id', 'mac_address', 'assigned_object_parent', 'assigned_object', 'description', 'comments', 'tags', + 'created', 'last_updated', + ) + default_columns = ('pk', 'mac_address', 'assigned_object_parent', 'assigned_object', 'description') diff --git a/netbox/dcim/tables/devicetypes.py b/netbox/dcim/tables/devicetypes.py index e8a4e35f1..a7f8f08e8 100644 --- a/netbox/dcim/tables/devicetypes.py +++ b/netbox/dcim/tables/devicetypes.py @@ -163,9 +163,7 @@ class ComponentTemplateTable(NetBoxTable): id = tables.Column( verbose_name=_('ID') ) - name = tables.Column( - order_by=('_name',) - ) + name = tables.Column() class Meta(NetBoxTable.Meta): exclude = ('id', ) @@ -220,6 +218,10 @@ class PowerOutletTemplateTable(ComponentTemplateTable): class InterfaceTemplateTable(ComponentTemplateTable): + name = tables.Column( + verbose_name=_('Name'), + order_by=('_name',) + ) enabled = columns.BooleanColumn( verbose_name=_('Enabled'), ) diff --git a/netbox/dcim/tables/modules.py b/netbox/dcim/tables/modules.py index 5b06e08b2..6bd0d53b5 100644 --- a/netbox/dcim/tables/modules.py +++ b/netbox/dcim/tables/modules.py @@ -41,6 +41,7 @@ class ModuleTypeTable(NetBoxTable): model = ModuleType fields = ( 'pk', 'id', 'model', 'manufacturer', 'part_number', 'airflow', 'weight', 'description', 'comments', 'tags', + 'created', 'last_updated', ) default_columns = ( 'pk', 'model', 'manufacturer', 'part_number', @@ -79,7 +80,7 @@ class ModuleTable(NetBoxTable): model = Module fields = ( 'pk', 'id', 'device', 'module_bay', 'manufacturer', 'module_type', 'status', 'serial', 'asset_tag', - 'description', 'comments', 'tags', + 'description', 'comments', 'tags', 'created', 'last_updated', ) default_columns = ( 'pk', 'id', 'device', 'module_bay', 'manufacturer', 'module_type', 'status', 'serial', 'asset_tag', diff --git a/netbox/dcim/tables/racks.py b/netbox/dcim/tables/racks.py index a6b704161..dbd99ca24 100644 --- a/netbox/dcim/tables/racks.py +++ b/netbox/dcim/tables/racks.py @@ -111,7 +111,6 @@ class RackTypeTable(NetBoxTable): class RackTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): name = tables.Column( verbose_name=_('Name'), - order_by=('_name',), linkify=True ) location = tables.Column( diff --git a/netbox/dcim/tables/template_code.py b/netbox/dcim/tables/template_code.py index 96ab803e6..449d55e14 100644 --- a/netbox/dcim/tables/template_code.py +++ b/netbox/dcim/tables/template_code.py @@ -10,6 +10,20 @@ LINKTERMINATION = """ {% endfor %} """ +INTERFACE_LINKTERMINATION = """ +{% load i18n %} +{% if record.is_virtual and record.virtual_circuit_termination %} + {% for termination in record.connected_endpoints %} + {{ termination.interface.parent_object }} + + {{ termination.interface }} + {% trans "via" %} + {{ termination.parent_object }} + {% if not forloop.last %}
{% endif %} + {% endfor %} +{% else %}""" + LINKTERMINATION + """{% endif %} +""" + CABLE_LENGTH = """ {% load helpers %} {% if record.length %}{{ record.length|floatformat:"-2" }} {{ record.length_unit }}{% endif %} @@ -314,6 +328,9 @@ INTERFACE_BUTTONS = """ {% if perms.ipam.add_ipaddress %}
  • IP Address
  • {% endif %} + {% if perms.dcim.add_macaddress %} +
  • MAC Address
  • + {% endif %} {% if perms.dcim.add_inventoryitem %}
  • Inventory Item
  • {% endif %} @@ -373,6 +390,15 @@ INTERFACE_BUTTONS = """ {% endif %} + {% if perms.circuits.add_virtualcircuittermination and not record.virtual_circuit_termination %} + + + + {% elif perms.circuits.delete_virtualcircuittermination and record.virtual_circuit_termination %} + + + + {% endif %} {% elif record.is_wired and perms.dcim.add_cable %} diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py index 1b460cd59..c273e02dd 100644 --- a/netbox/dcim/tests/test_api.py +++ b/netbox/dcim/tests/test_api.py @@ -7,6 +7,7 @@ from dcim.choices import * from dcim.constants import * from dcim.models import * from extras.models import ConfigTemplate +from ipam.choices import VLANQinQRoleChoices from ipam.models import ASN, RIR, VLAN, VRF from netbox.api.serializers import GenericObjectSerializer from tenancy.models import Tenant @@ -204,13 +205,41 @@ class LocationTest(APIViewTestCases.APIViewTestCase): Site.objects.bulk_create(sites) parent_locations = ( - Location.objects.create(site=sites[0], name='Parent Location 1', slug='parent-location-1', status=LocationStatusChoices.STATUS_ACTIVE), - Location.objects.create(site=sites[1], name='Parent Location 2', slug='parent-location-2', status=LocationStatusChoices.STATUS_ACTIVE), + Location.objects.create( + site=sites[0], + name='Parent Location 1', + slug='parent-location-1', + status=LocationStatusChoices.STATUS_ACTIVE, + ), + Location.objects.create( + site=sites[1], + name='Parent Location 2', + slug='parent-location-2', + status=LocationStatusChoices.STATUS_ACTIVE, + ), ) - Location.objects.create(site=sites[0], name='Location 1', slug='location-1', parent=parent_locations[0], status=LocationStatusChoices.STATUS_ACTIVE) - Location.objects.create(site=sites[0], name='Location 2', slug='location-2', parent=parent_locations[0], status=LocationStatusChoices.STATUS_ACTIVE) - Location.objects.create(site=sites[0], name='Location 3', slug='location-3', parent=parent_locations[0], status=LocationStatusChoices.STATUS_ACTIVE) + Location.objects.create( + site=sites[0], + name='Location 1', + slug='location-1', + parent=parent_locations[0], + status=LocationStatusChoices.STATUS_ACTIVE, + ) + Location.objects.create( + site=sites[0], + name='Location 2', + slug='location-2', + parent=parent_locations[0], + status=LocationStatusChoices.STATUS_ACTIVE, + ) + Location.objects.create( + site=sites[0], + name='Location 3', + slug='location-3', + parent=parent_locations[0], + status=LocationStatusChoices.STATUS_ACTIVE, + ) cls.create_data = [ { @@ -289,9 +318,24 @@ class RackTypeTest(APIViewTestCases.APIViewTestCase): Manufacturer.objects.bulk_create(manufacturers) rack_types = ( - RackType(manufacturer=manufacturers[0], model='Rack Type 1', slug='rack-type-1', form_factor=RackFormFactorChoices.TYPE_CABINET,), - RackType(manufacturer=manufacturers[0], model='Rack Type 2', slug='rack-type-2', form_factor=RackFormFactorChoices.TYPE_CABINET,), - RackType(manufacturer=manufacturers[0], model='Rack Type 3', slug='rack-type-3', form_factor=RackFormFactorChoices.TYPE_CABINET,), + RackType( + manufacturer=manufacturers[0], + model='Rack Type 1', + slug='rack-type-1', + form_factor=RackFormFactorChoices.TYPE_CABINET, + ), + RackType( + manufacturer=manufacturers[0], + model='Rack Type 2', + slug='rack-type-2', + form_factor=RackFormFactorChoices.TYPE_CABINET, + ), + RackType( + manufacturer=manufacturers[0], + model='Rack Type 3', + slug='rack-type-3', + form_factor=RackFormFactorChoices.TYPE_CABINET, + ), ) RackType.objects.bulk_create(rack_types) @@ -1049,10 +1093,18 @@ class InventoryItemTemplateTest(APIViewTestCases.APIViewTestCase): role = InventoryItemRole.objects.create(name='Inventory Item Role 1', slug='inventory-item-role-1') inventory_item_templates = ( - InventoryItemTemplate(device_type=devicetype, name='Inventory Item Template 1', manufacturer=manufacturer, role=role), - InventoryItemTemplate(device_type=devicetype, name='Inventory Item Template 2', manufacturer=manufacturer, role=role), - InventoryItemTemplate(device_type=devicetype, name='Inventory Item Template 3', manufacturer=manufacturer, role=role), - InventoryItemTemplate(device_type=devicetype, name='Inventory Item Template 4', manufacturer=manufacturer, role=role), + InventoryItemTemplate( + device_type=devicetype, name='Inventory Item Template 1', manufacturer=manufacturer, role=role + ), + InventoryItemTemplate( + device_type=devicetype, name='Inventory Item Template 2', manufacturer=manufacturer, role=role + ), + InventoryItemTemplate( + device_type=devicetype, name='Inventory Item Template 3', manufacturer=manufacturer, role=role + ), + InventoryItemTemplate( + device_type=devicetype, name='Inventory Item Template 4', manufacturer=manufacturer, role=role + ), ) for item in inventory_item_templates: item.save() @@ -1618,6 +1670,7 @@ class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase VLAN(name='VLAN 1', vid=1), VLAN(name='VLAN 2', vid=2), VLAN(name='VLAN 3', vid=3), + VLAN(name='SVLAN 1', vid=1001, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE), ) VLAN.objects.bulk_create(vlans) @@ -1676,18 +1729,22 @@ class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase 'vdcs': [vdcs[1].pk], 'name': 'Interface 7', 'type': InterfaceTypeChoices.TYPE_80211A, + 'mode': InterfaceModeChoices.MODE_Q_IN_Q, 'tx_power': 10, 'wireless_lans': [wireless_lans[0].pk, wireless_lans[1].pk], 'rf_channel': WirelessChannelChoices.CHANNEL_5G_32, + 'qinq_svlan': vlans[3].pk, }, { 'device': device.pk, 'vdcs': [vdcs[1].pk], 'name': 'Interface 8', 'type': InterfaceTypeChoices.TYPE_80211A, + 'mode': InterfaceModeChoices.MODE_Q_IN_Q, 'tx_power': 10, 'wireless_lans': [wireless_lans[0].pk, wireless_lans[1].pk], 'rf_channel': "", + 'qinq_svlan': vlans[3].pk, }, ] @@ -1955,9 +2012,15 @@ class InventoryItemTest(APIViewTestCases.APIViewTestCase): ) Interface.objects.bulk_create(interfaces) - InventoryItem.objects.create(device=device, name='Inventory Item 1', role=roles[0], manufacturer=manufacturer, component=interfaces[0]) - InventoryItem.objects.create(device=device, name='Inventory Item 2', role=roles[0], manufacturer=manufacturer, component=interfaces[1]) - InventoryItem.objects.create(device=device, name='Inventory Item 3', role=roles[0], manufacturer=manufacturer, component=interfaces[2]) + InventoryItem.objects.create( + device=device, name='Inventory Item 1', role=roles[0], manufacturer=manufacturer, component=interfaces[0] + ) + InventoryItem.objects.create( + device=device, name='Inventory Item 2', role=roles[0], manufacturer=manufacturer, component=interfaces[1] + ) + InventoryItem.objects.create( + device=device, name='Inventory Item 3', role=roles[0], manufacturer=manufacturer, component=interfaces[2] + ) cls.create_data = [ { diff --git a/netbox/dcim/tests/test_cablepaths.py b/netbox/dcim/tests/test_cablepaths.py index f7c337bdf..1acc9a8a1 100644 --- a/netbox/dcim/tests/test_cablepaths.py +++ b/netbox/dcim/tests/test_cablepaths.py @@ -661,24 +661,64 @@ class CablePathTestCase(TestCase): ) cable5.save() path1 = self.assertPathExists( - ([interface1, interface2], cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1, cable4, [interface5, interface6]), + ( + [interface1, interface2], + cable1, + frontport1_1, + rearport1, + cable3, + rearport2, + frontport2_1, + cable4, + [interface5, interface6], + ), is_complete=True, - is_active=True + is_active=True, ) path2 = self.assertPathExists( - ([interface3, interface4], cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2, cable5, [interface7, interface8]), + ( + [interface3, interface4], + cable2, + frontport1_2, + rearport1, + cable3, + rearport2, + frontport2_2, + cable5, + [interface7, interface8], + ), is_complete=True, - is_active=True + is_active=True, ) path3 = self.assertPathExists( - ([interface5, interface6], cable4, frontport2_1, rearport2, cable3, rearport1, frontport1_1, cable1, [interface1, interface2]), + ( + [interface5, interface6], + cable4, + frontport2_1, + rearport2, + cable3, + rearport1, + frontport1_1, + cable1, + [interface1, interface2], + ), is_complete=True, - is_active=True + is_active=True, ) path4 = self.assertPathExists( - ([interface7, interface8], cable5, frontport2_2, rearport2, cable3, rearport1, frontport1_2, cable2, [interface3, interface4]), + ( + [interface7, interface8], + cable5, + frontport2_2, + rearport2, + cable3, + rearport1, + frontport1_2, + cable2, + [interface3, interface4], + ), is_complete=True, - is_active=True + is_active=True, ) self.assertEqual(CablePath.objects.count(), 4) @@ -1167,7 +1207,11 @@ class CablePathTestCase(TestCase): [IF1] --C1-- [CT1] """ interface1 = Interface.objects.create(device=self.device, name='Interface 1') - circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A') + circuittermination1 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, + term_side='A' + ) # Create cable 1 cable1 = Cable( @@ -1198,7 +1242,11 @@ class CablePathTestCase(TestCase): """ interface1 = Interface.objects.create(device=self.device, name='Interface 1') interface2 = Interface.objects.create(device=self.device, name='Interface 2') - circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A') + circuittermination1 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, + term_side='A' + ) # Create cable 1 cable1 = Cable( @@ -1214,7 +1262,11 @@ class CablePathTestCase(TestCase): ) # Create CT2 - circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='Z') + circuittermination2 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, + term_side='Z' + ) # Check for partial path to site self.assertPathExists( @@ -1266,7 +1318,11 @@ class CablePathTestCase(TestCase): interface2 = Interface.objects.create(device=self.device, name='Interface 2') interface3 = Interface.objects.create(device=self.device, name='Interface 3') interface4 = Interface.objects.create(device=self.device, name='Interface 4') - circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A') + circuittermination1 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, + term_side='A' + ) # Create cable 1 cable1 = Cable( @@ -1282,7 +1338,11 @@ class CablePathTestCase(TestCase): ) # Create CT2 - circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='Z') + circuittermination2 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, + term_side='Z' + ) # Check for partial path to site self.assertPathExists( @@ -1299,14 +1359,28 @@ class CablePathTestCase(TestCase): # Check for complete path in each direction self.assertPathExists( - ([interface1, interface2], cable1, circuittermination1, circuittermination2, cable2, [interface3, interface4]), + ( + [interface1, interface2], + cable1, + circuittermination1, + circuittermination2, + cable2, + [interface3, interface4], + ), is_complete=True, - is_active=True + is_active=True, ) self.assertPathExists( - ([interface3, interface4], cable2, circuittermination2, circuittermination1, cable1, [interface1, interface2]), + ( + [interface3, interface4], + cable2, + circuittermination2, + circuittermination1, + cable1, + [interface1, interface2], + ), is_complete=True, - is_active=True + is_active=True, ) self.assertEqual(CablePath.objects.count(), 2) @@ -1335,8 +1409,16 @@ class CablePathTestCase(TestCase): """ interface1 = Interface.objects.create(device=self.device, name='Interface 1') site2 = Site.objects.create(name='Site 2', slug='site-2') - circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A') - circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=site2, term_side='Z') + circuittermination1 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, + term_side='A' + ) + circuittermination2 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=site2, + term_side='Z' + ) # Create cable 1 cable1 = Cable( @@ -1365,8 +1447,16 @@ class CablePathTestCase(TestCase): """ interface1 = Interface.objects.create(device=self.device, name='Interface 1') providernetwork = ProviderNetwork.objects.create(name='Provider Network 1', provider=self.circuit.provider) - circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A') - circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, provider_network=providernetwork, term_side='Z') + circuittermination1 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, + term_side='A' + ) + circuittermination2 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=providernetwork, + term_side='Z' + ) # Create cable 1 cable1 = Cable( @@ -1413,8 +1503,15 @@ class CablePathTestCase(TestCase): frontport2_2 = FrontPort.objects.create( device=self.device, name='Front Port 2:2', rear_port=rearport2, rear_port_position=2 ) - circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A') - circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='Z') + circuittermination1 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, + term_side='A' + ) + circuittermination2 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, term_side='Z' + ) # Create cables cable1 = Cable( @@ -1499,10 +1596,26 @@ class CablePathTestCase(TestCase): interface1 = Interface.objects.create(device=self.device, name='Interface 1') interface2 = Interface.objects.create(device=self.device, name='Interface 2') circuit2 = Circuit.objects.create(provider=self.circuit.provider, type=self.circuit.type, cid='Circuit 2') - circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A') - circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='Z') - circuittermination3 = CircuitTermination.objects.create(circuit=circuit2, site=self.site, term_side='A') - circuittermination4 = CircuitTermination.objects.create(circuit=circuit2, site=self.site, term_side='Z') + circuittermination1 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, + term_side='A' + ) + circuittermination2 = CircuitTermination.objects.create( + circuit=self.circuit, + termination=self.site, + term_side='Z' + ) + circuittermination3 = CircuitTermination.objects.create( + circuit=circuit2, + termination=self.site, + term_side='A' + ) + circuittermination4 = CircuitTermination.objects.create( + circuit=circuit2, + termination=self.site, + term_side='Z' + ) # Create cables cable1 = Cable( @@ -1706,45 +1819,95 @@ class CablePathTestCase(TestCase): ) cable3.save() self.assertPathExists( - (interface1, cable1, (frontport1_1, frontport1_2), rearport1, cable3, rearport2, (frontport2_1, frontport2_2)), - is_complete=False + ( + interface1, + cable1, + (frontport1_1, frontport1_2), + rearport1, + cable3, + rearport2, + (frontport2_1, frontport2_2), + ), + is_complete=False, ) self.assertPathExists( - (interface2, cable2, (frontport1_3, frontport1_4), rearport1, cable3, rearport2, (frontport2_3, frontport2_4)), - is_complete=False + ( + interface2, + cable2, + (frontport1_3, frontport1_4), + rearport1, + cable3, + rearport2, + (frontport2_3, frontport2_4), + ), + is_complete=False, ) self.assertEqual(CablePath.objects.count(), 2) # Create cables 4-5 - cable4 = Cable( - a_terminations=[frontport2_1, frontport2_2], - b_terminations=[interface3] - ) + cable4 = Cable(a_terminations=[frontport2_1, frontport2_2], b_terminations=[interface3]) cable4.save() - cable5 = Cable( - a_terminations=[frontport2_3, frontport2_4], - b_terminations=[interface4] - ) + cable5 = Cable(a_terminations=[frontport2_3, frontport2_4], b_terminations=[interface4]) cable5.save() path1 = self.assertPathExists( - (interface1, cable1, (frontport1_1, frontport1_2), rearport1, cable3, rearport2, (frontport2_1, frontport2_2), cable4, interface3), + ( + interface1, + cable1, + (frontport1_1, frontport1_2), + rearport1, + cable3, + rearport2, + (frontport2_1, frontport2_2), + cable4, + interface3, + ), is_complete=True, - is_active=True + is_active=True, ) path2 = self.assertPathExists( - (interface2, cable2, (frontport1_3, frontport1_4), rearport1, cable3, rearport2, (frontport2_3, frontport2_4), cable5, interface4), + ( + interface2, + cable2, + (frontport1_3, frontport1_4), + rearport1, + cable3, + rearport2, + (frontport2_3, frontport2_4), + cable5, + interface4, + ), is_complete=True, - is_active=True + is_active=True, ) path3 = self.assertPathExists( - (interface3, cable4, (frontport2_1, frontport2_2), rearport2, cable3, rearport1, (frontport1_1, frontport1_2), cable1, interface1), + ( + interface3, + cable4, + (frontport2_1, frontport2_2), + rearport2, + cable3, + rearport1, + (frontport1_1, frontport1_2), + cable1, + interface1, + ), is_complete=True, - is_active=True + is_active=True, ) path4 = self.assertPathExists( - (interface4, cable5, (frontport2_3, frontport2_4), rearport2, cable3, rearport1, (frontport1_3, frontport1_4), cable2, interface2), + ( + interface4, + cable5, + (frontport2_3, frontport2_4), + rearport2, + cable3, + rearport1, + (frontport1_3, frontport1_4), + cable2, + interface2, + ), is_complete=True, - is_active=True + is_active=True, ) self.assertEqual(CablePath.objects.count(), 4) @@ -1809,7 +1972,10 @@ class CablePathTestCase(TestCase): ) cable1.save() self.assertPathExists( - (interface1, cable1, (frontport1, frontport3), (rearport1, rearport3), (cable2, cable4), (rearport2, rearport4), (frontport2, frontport4)), + ( + interface1, cable1, (frontport1, frontport3), (rearport1, rearport3), (cable2, cable4), + (rearport2, rearport4), (frontport2, frontport4) + ), is_complete=False ) self.assertEqual(CablePath.objects.count(), 1) diff --git a/netbox/dcim/tests/test_filtersets.py b/netbox/dcim/tests/test_filtersets.py index ae738b57f..ede1e2a09 100644 --- a/netbox/dcim/tests/test_filtersets.py +++ b/netbox/dcim/tests/test_filtersets.py @@ -4,12 +4,13 @@ from circuits.models import Circuit, CircuitTermination, CircuitType, Provider from dcim.choices import * from dcim.filtersets import * from dcim.models import * -from ipam.models import ASN, IPAddress, RIR, VRF +from ipam.choices import VLANQinQRoleChoices +from ipam.models import ASN, IPAddress, RIR, VLAN, VLANTranslationPolicy, VRF from netbox.choices import ColorChoices, WeightUnitChoices from tenancy.models import Tenant, TenantGroup from users.models import User -from utilities.testing import ChangeLoggedFilterSetTests, create_test_device -from virtualization.models import Cluster, ClusterType, ClusterGroup +from utilities.testing import ChangeLoggedFilterSetTests, create_test_device, create_test_virtualmachine +from virtualization.models import Cluster, ClusterType, ClusterGroup, VMInterface, VirtualMachine from wireless.choices import WirelessChannelChoices, WirelessRoleChoices @@ -242,9 +243,41 @@ class SiteTestCase(TestCase, ChangeLoggedFilterSetTests): ASN.objects.bulk_create(asns) sites = ( - Site(name='Site 1', slug='site-1', region=regions[0], group=groups[0], tenant=tenants[0], status=SiteStatusChoices.STATUS_ACTIVE, facility='Facility 1', latitude=10, longitude=10, description='foobar1'), - Site(name='Site 2', slug='site-2', region=regions[1], group=groups[1], tenant=tenants[1], status=SiteStatusChoices.STATUS_PLANNED, facility='Facility 2', latitude=20, longitude=20, description='foobar2'), - Site(name='Site 3', slug='site-3', region=regions[2], group=groups[2], tenant=tenants[2], status=SiteStatusChoices.STATUS_RETIRED, facility='Facility 3', latitude=30, longitude=30), + Site( + name='Site 1', + slug='site-1', + region=regions[0], + group=groups[0], + tenant=tenants[0], + status=SiteStatusChoices.STATUS_ACTIVE, + facility='Facility 1', + latitude=10, + longitude=10, + description='foobar1', + ), + Site( + name='Site 2', + slug='site-2', + region=regions[1], + group=groups[1], + tenant=tenants[1], + status=SiteStatusChoices.STATUS_PLANNED, + facility='Facility 2', + latitude=20, + longitude=20, + description='foobar2', + ), + Site( + name='Site 3', + slug='site-3', + region=regions[2], + group=groups[2], + tenant=tenants[2], + status=SiteStatusChoices.STATUS_RETIRED, + facility='Facility 3', + latitude=30, + longitude=30, + ), ) Site.objects.bulk_create(sites) sites[0].asns.set([asns[0]]) @@ -360,9 +393,33 @@ class LocationTestCase(TestCase, ChangeLoggedFilterSetTests): location.save() locations = ( - Location(name='Location 1A', slug='location-1a', site=sites[0], parent=parent_locations[0], status=LocationStatusChoices.STATUS_PLANNED, facility='Facility 1', description='foobar1'), - Location(name='Location 2A', slug='location-2a', site=sites[1], parent=parent_locations[1], status=LocationStatusChoices.STATUS_STAGING, facility='Facility 2', description='foobar2'), - Location(name='Location 3A', slug='location-3a', site=sites[2], parent=parent_locations[2], status=LocationStatusChoices.STATUS_DECOMMISSIONING, facility='Facility 3', description='foobar3'), + Location( + name='Location 1A', + slug='location-1a', + site=sites[0], + parent=parent_locations[0], + status=LocationStatusChoices.STATUS_PLANNED, + facility='Facility 1', + description='foobar1', + ), + Location( + name='Location 2A', + slug='location-2a', + site=sites[1], + parent=parent_locations[1], + status=LocationStatusChoices.STATUS_STAGING, + facility='Facility 2', + description='foobar2', + ), + Location( + name='Location 3A', + slug='location-3a', + site=sites[2], + parent=parent_locations[2], + status=LocationStatusChoices.STATUS_DECOMMISSIONING, + facility='Facility 3', + description='foobar3', + ), ) for location in locations: location.save() @@ -871,7 +928,6 @@ class RackTestCase(TestCase, ChangeLoggedFilterSetTests): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_outer_unit(self): - self.assertEqual(Rack.objects.filter(outer_unit__isnull=False).count(), 5) params = {'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) @@ -1222,10 +1278,22 @@ class DeviceTypeTestCase(TestCase, ChangeLoggedFilterSetTests): RearPortTemplate(device_type=device_types[1], name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C), ) RearPortTemplate.objects.bulk_create(rear_ports) - FrontPortTemplate.objects.bulk_create(( - FrontPortTemplate(device_type=device_types[0], name='Front Port 1', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[0]), - FrontPortTemplate(device_type=device_types[1], name='Front Port 2', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[1]), - )) + FrontPortTemplate.objects.bulk_create( + ( + FrontPortTemplate( + device_type=device_types[0], + name='Front Port 1', + type=PortTypeChoices.TYPE_8P8C, + rear_port=rear_ports[0], + ), + FrontPortTemplate( + device_type=device_types[1], + name='Front Port 2', + type=PortTypeChoices.TYPE_8P8C, + rear_port=rear_ports[1], + ), + ) + ) ModuleBayTemplate.objects.bulk_create(( ModuleBayTemplate(device_type=device_types[0], name='Module Bay 1'), ModuleBayTemplate(device_type=device_types[1], name='Module Bay 2'), @@ -1435,10 +1503,22 @@ class ModuleTypeTestCase(TestCase, ChangeLoggedFilterSetTests): RearPortTemplate(module_type=module_types[1], name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C), ) RearPortTemplate.objects.bulk_create(rear_ports) - FrontPortTemplate.objects.bulk_create(( - FrontPortTemplate(module_type=module_types[0], name='Front Port 1', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[0]), - FrontPortTemplate(module_type=module_types[1], name='Front Port 2', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[1]), - )) + FrontPortTemplate.objects.bulk_create( + ( + FrontPortTemplate( + module_type=module_types[0], + name='Front Port 1', + type=PortTypeChoices.TYPE_8P8C, + rear_port=rear_ports[0], + ), + FrontPortTemplate( + module_type=module_types[1], + name='Front Port 2', + type=PortTypeChoices.TYPE_8P8C, + rear_port=rear_ports[1], + ), + ) + ) def test_q(self): params = {'q': 'foobar1'} @@ -1893,11 +1973,19 @@ class ModuleBayTemplateTestCase(TestCase, DeviceComponentTemplateFilterSetTests, ) ModuleType.objects.bulk_create(module_types) - ModuleBayTemplate.objects.bulk_create(( - ModuleBayTemplate(device_type=device_types[0], name='Module Bay 1', description='foobar1'), - ModuleBayTemplate(device_type=device_types[1], name='Module Bay 2', description='foobar2', module_type=module_types[0]), - ModuleBayTemplate(device_type=device_types[2], name='Module Bay 3', description='foobar3', module_type=module_types[1]), - )) + ModuleBayTemplate.objects.bulk_create( + ( + ModuleBayTemplate( + device_type=device_types[0], name='Module Bay 1', description='foobar1' + ), + ModuleBayTemplate( + device_type=device_types[1], name='Module Bay 2', description='foobar2', module_type=module_types[0] + ), + ModuleBayTemplate( + device_type=device_types[2], name='Module Bay 3', description='foobar3', module_type=module_types[1] + ), + ) + ) def test_name(self): params = {'name': ['Module Bay 1', 'Module Bay 2']} @@ -1996,9 +2084,15 @@ class InventoryItemTemplateTestCase(TestCase, DeviceComponentTemplateFilterSetTe item.save() child_inventory_item_templates = ( - InventoryItemTemplate(device_type=device_types[0], name='Inventory Item 1A', parent=inventory_item_templates[0]), - InventoryItemTemplate(device_type=device_types[1], name='Inventory Item 2A', parent=inventory_item_templates[1]), - InventoryItemTemplate(device_type=device_types[2], name='Inventory Item 3A', parent=inventory_item_templates[2]), + InventoryItemTemplate( + device_type=device_types[0], name='Inventory Item 1A', parent=inventory_item_templates[0] + ), + InventoryItemTemplate( + device_type=device_types[1], name='Inventory Item 2A', parent=inventory_item_templates[1] + ), + InventoryItemTemplate( + device_type=device_types[2], name='Inventory Item 3A', parent=inventory_item_templates[2] + ), ) for item in child_inventory_item_templates: item.save() @@ -2323,10 +2417,17 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests): PowerOutlet(device=devices[1], name='Power Outlet 2'), )) interfaces = ( - Interface(device=devices[0], name='Interface 1', mac_address='00-00-00-00-00-01'), - Interface(device=devices[1], name='Interface 2', mac_address='00-00-00-00-00-02'), + Interface(device=devices[0], name='Interface 1'), + Interface(device=devices[1], name='Interface 2'), ) Interface.objects.bulk_create(interfaces) + mac_addresses = ( + MACAddress(mac_address='00-00-00-00-00-01'), + MACAddress(mac_address='00-00-00-00-00-02'), + ) + MACAddress.objects.bulk_create(mac_addresses) + interfaces[0].mac_addresses.set([mac_addresses[0]]) + interfaces[1].mac_addresses.set([mac_addresses[1]]) rear_ports = ( RearPort(device=devices[0], name='Rear Port 1', type=PortTypeChoices.TYPE_8P8C), RearPort(device=devices[1], name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C), @@ -2841,10 +2942,41 @@ class ConsolePortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedF Rack.objects.bulk_create(racks) devices = ( - Device(name='Device 1', device_type=device_types[0], role=roles[0], site=sites[0], location=locations[0], rack=racks[0], status='active'), - Device(name='Device 2', device_type=device_types[1], role=roles[1], site=sites[1], location=locations[1], rack=racks[1], status='planned'), - Device(name='Device 3', device_type=device_types[2], role=roles[2], site=sites[2], location=locations[2], rack=racks[2], status='offline'), - Device(name=None, device_type=device_types[0], role=roles[0], site=sites[3], status='offline'), # For cable connections + Device( + name='Device 1', + device_type=device_types[0], + role=roles[0], + site=sites[0], + location=locations[0], + rack=racks[0], + status='active', + ), + Device( + name='Device 2', + device_type=device_types[1], + role=roles[1], + site=sites[1], + location=locations[1], + rack=racks[1], + status='planned', + ), + Device( + name='Device 3', + device_type=device_types[2], + role=roles[2], + site=sites[2], + location=locations[2], + rack=racks[2], + status='offline', + ), + # For cable connections + Device( + name=None, + device_type=device_types[0], + role=roles[0], + site=sites[3], + status='offline' + ), ) Device.objects.bulk_create(devices) @@ -3022,10 +3154,41 @@ class ConsoleServerPortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeL Rack.objects.bulk_create(racks) devices = ( - Device(name='Device 1', device_type=device_types[0], role=roles[0], site=sites[0], location=locations[0], rack=racks[0], status='active'), - Device(name='Device 2', device_type=device_types[1], role=roles[1], site=sites[1], location=locations[1], rack=racks[1], status='planned'), - Device(name='Device 3', device_type=device_types[2], role=roles[2], site=sites[2], location=locations[2], rack=racks[2], status='offline'), - Device(name=None, device_type=device_types[2], role=roles[2], site=sites[3], status='offline'), # For cable connections + Device( + name='Device 1', + device_type=device_types[0], + role=roles[0], + site=sites[0], + location=locations[0], + rack=racks[0], + status='active', + ), + Device( + name='Device 2', + device_type=device_types[1], + role=roles[1], + site=sites[1], + location=locations[1], + rack=racks[1], + status='planned', + ), + Device( + name='Device 3', + device_type=device_types[2], + role=roles[2], + site=sites[2], + location=locations[2], + rack=racks[2], + status='offline', + ), + # For cable connections + Device( + name=None, + device_type=device_types[2], + role=roles[2], + site=sites[3], + status='offline' + ), ) Device.objects.bulk_create(devices) @@ -3051,9 +3214,15 @@ class ConsoleServerPortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeL ConsolePort.objects.bulk_create(console_ports) console_server_ports = ( - ConsoleServerPort(device=devices[0], module=modules[0], name='Console Server Port 1', label='A', description='First'), - ConsoleServerPort(device=devices[1], module=modules[1], name='Console Server Port 2', label='B', description='Second'), - ConsoleServerPort(device=devices[2], module=modules[2], name='Console Server Port 3', label='C', description='Third'), + ConsoleServerPort( + device=devices[0], module=modules[0], name='Console Server Port 1', label='A', description='First' + ), + ConsoleServerPort( + device=devices[1], module=modules[1], name='Console Server Port 2', label='B', description='Second' + ), + ConsoleServerPort( + device=devices[2], module=modules[2], name='Console Server Port 3', label='C', description='Third' + ), ) ConsoleServerPort.objects.bulk_create(console_server_ports) @@ -3203,10 +3372,41 @@ class PowerPortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil Rack.objects.bulk_create(racks) devices = ( - Device(name='Device 1', device_type=device_types[0], role=roles[0], site=sites[0], location=locations[0], rack=racks[0], status='active'), - Device(name='Device 2', device_type=device_types[1], role=roles[1], site=sites[1], location=locations[1], rack=racks[1], status='planned'), - Device(name='Device 3', device_type=device_types[2], role=roles[2], site=sites[2], location=locations[2], rack=racks[2], status='offline'), - Device(name=None, device_type=device_types[2], role=roles[2], site=sites[3], status='offline'), # For cable connections + Device( + name='Device 1', + device_type=device_types[0], + role=roles[0], + site=sites[0], + location=locations[0], + rack=racks[0], + status='active', + ), + Device( + name='Device 2', + device_type=device_types[1], + role=roles[1], + site=sites[1], + location=locations[1], + rack=racks[1], + status='planned', + ), + Device( + name='Device 3', + device_type=device_types[2], + role=roles[2], + site=sites[2], + location=locations[2], + rack=racks[2], + status='offline', + ), + # For cable connections + Device( + name=None, + device_type=device_types[2], + role=roles[2], + site=sites[3], + status='offline' + ), ) Device.objects.bulk_create(devices) @@ -3232,9 +3432,33 @@ class PowerPortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil PowerOutlet.objects.bulk_create(power_outlets) power_ports = ( - PowerPort(device=devices[0], module=modules[0], name='Power Port 1', label='A', maximum_draw=100, allocated_draw=50, description='First'), - PowerPort(device=devices[1], module=modules[1], name='Power Port 2', label='B', maximum_draw=200, allocated_draw=100, description='Second'), - PowerPort(device=devices[2], module=modules[2], name='Power Port 3', label='C', maximum_draw=300, allocated_draw=150, description='Third'), + PowerPort( + device=devices[0], + module=modules[0], + name='Power Port 1', + label='A', + maximum_draw=100, + allocated_draw=50, + description='First', + ), + PowerPort( + device=devices[1], + module=modules[1], + name='Power Port 2', + label='B', + maximum_draw=200, + allocated_draw=100, + description='Second', + ), + PowerPort( + device=devices[2], + module=modules[2], + name='Power Port 3', + label='C', + maximum_draw=300, + allocated_draw=150, + description='Third', + ), ) PowerPort.objects.bulk_create(power_ports) @@ -3392,10 +3616,41 @@ class PowerOutletTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedF Rack.objects.bulk_create(racks) devices = ( - Device(name='Device 1', device_type=device_types[0], role=roles[0], site=sites[0], location=locations[0], rack=racks[0], status='active'), - Device(name='Device 2', device_type=device_types[1], role=roles[1], site=sites[1], location=locations[1], rack=racks[1], status='planned'), - Device(name='Device 3', device_type=device_types[2], role=roles[2], site=sites[2], location=locations[2], rack=racks[2], status='offline'), - Device(name=None, device_type=device_types[2], role=roles[2], site=sites[3], status='offline'), # For cable connections + Device( + name='Device 1', + device_type=device_types[0], + role=roles[0], + site=sites[0], + location=locations[0], + rack=racks[0], + status='active', + ), + Device( + name='Device 2', + device_type=device_types[1], + role=roles[1], + site=sites[1], + location=locations[1], + rack=racks[1], + status='planned', + ), + Device( + name='Device 3', + device_type=device_types[2], + role=roles[2], + site=sites[2], + location=locations[2], + rack=racks[2], + status='offline', + ), + # For cable connections + Device( + name=None, + device_type=device_types[2], + role=roles[2], + site=sites[3], + status='offline' + ), ) Device.objects.bulk_create(devices) @@ -3421,9 +3676,33 @@ class PowerOutletTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedF PowerPort.objects.bulk_create(power_ports) power_outlets = ( - PowerOutlet(device=devices[0], module=modules[0], name='Power Outlet 1', label='A', feed_leg=PowerOutletFeedLegChoices.FEED_LEG_A, description='First', color='ff0000'), - PowerOutlet(device=devices[1], module=modules[1], name='Power Outlet 2', label='B', feed_leg=PowerOutletFeedLegChoices.FEED_LEG_B, description='Second', color='00ff00'), - PowerOutlet(device=devices[2], module=modules[2], name='Power Outlet 3', label='C', feed_leg=PowerOutletFeedLegChoices.FEED_LEG_C, description='Third', color='0000ff'), + PowerOutlet( + device=devices[0], + module=modules[0], + name='Power Outlet 1', + label='A', + feed_leg=PowerOutletFeedLegChoices.FEED_LEG_A, + description='First', + color='ff0000', + ), + PowerOutlet( + device=devices[1], + module=modules[1], + name='Power Outlet 2', + label='B', + feed_leg=PowerOutletFeedLegChoices.FEED_LEG_B, + description='Second', + color='00ff00', + ), + PowerOutlet( + device=devices[2], + module=modules[2], + name='Power Outlet 3', + label='C', + feed_leg=PowerOutletFeedLegChoices.FEED_LEG_C, + description='Third', + color='0000ff', + ), ) PowerOutlet.objects.bulk_create(power_outlets) @@ -3521,7 +3800,7 @@ class PowerOutletTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedF class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFilterSetTests): queryset = Interface.objects.all() filterset = InterfaceFilterSet - ignore_fields = ('tagged_vlans', 'untagged_vlan', 'vdcs') + ignore_fields = ('tagged_vlans', 'untagged_vlan', 'qinq_svlan', 'vdcs') @classmethod def setUpTestData(cls): @@ -3665,11 +3944,36 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil # Virtual Device Context Creation vdcs = ( - VirtualDeviceContext(device=devices[4], name='VDC 1', identifier=1, status=VirtualDeviceContextStatusChoices.STATUS_ACTIVE), - VirtualDeviceContext(device=devices[4], name='VDC 2', identifier=2, status=VirtualDeviceContextStatusChoices.STATUS_PLANNED), + VirtualDeviceContext( + device=devices[4], name='VDC 1', identifier=1, status=VirtualDeviceContextStatusChoices.STATUS_ACTIVE + ), + VirtualDeviceContext( + device=devices[4], name='VDC 2', identifier=2, status=VirtualDeviceContextStatusChoices.STATUS_PLANNED + ), ) VirtualDeviceContext.objects.bulk_create(vdcs) + mac_addresses = ( + MACAddress(mac_address='00-00-00-00-00-01'), + MACAddress(mac_address='00-00-00-00-00-02'), + MACAddress(mac_address='00-00-00-00-00-03'), + ) + MACAddress.objects.bulk_create(mac_addresses) + + vlans = ( + VLAN(name='SVLAN 1', vid=1001, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE), + VLAN(name='SVLAN 2', vid=1002, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE), + VLAN(name='SVLAN 3', vid=1003, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE), + ) + VLAN.objects.bulk_create(vlans) + + vlan_translation_policies = ( + VLANTranslationPolicy(name='Policy 1'), + VLANTranslationPolicy(name='Policy 2'), + VLANTranslationPolicy(name='Policy 3'), + ) + VLANTranslationPolicy.objects.bulk_create(vlan_translation_policies) + interfaces = ( Interface( device=devices[0], @@ -3681,13 +3985,13 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil mgmt_only=True, mtu=100, mode=InterfaceModeChoices.MODE_ACCESS, - mac_address='00-00-00-00-00-01', description='First', vrf=vrfs[0], speed=1000000, duplex='half', poe_mode=InterfacePoEModeChoices.MODE_PSE, - poe_type=InterfacePoETypeChoices.TYPE_1_8023AF + poe_type=InterfacePoETypeChoices.TYPE_1_8023AF, + vlan_translation_policy=vlan_translation_policies[0], ), Interface( device=devices[1], @@ -3706,13 +4010,13 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil mgmt_only=True, mtu=200, mode=InterfaceModeChoices.MODE_TAGGED, - mac_address='00-00-00-00-00-02', description='Second', vrf=vrfs[1], speed=1000000, duplex='full', poe_mode=InterfacePoEModeChoices.MODE_PD, - poe_type=InterfacePoETypeChoices.TYPE_1_8023AF + poe_type=InterfacePoETypeChoices.TYPE_1_8023AF, + vlan_translation_policy=vlan_translation_policies[0], ), Interface( device=devices[3], @@ -3724,13 +4028,13 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil mgmt_only=False, mtu=300, mode=InterfaceModeChoices.MODE_TAGGED_ALL, - mac_address='00-00-00-00-00-03', description='Third', vrf=vrfs[2], speed=100000, duplex='half', poe_mode=InterfacePoEModeChoices.MODE_PSE, - poe_type=InterfacePoETypeChoices.TYPE_2_8023AT + poe_type=InterfacePoETypeChoices.TYPE_2_8023AT, + vlan_translation_policy=vlan_translation_policies[1], ), Interface( device=devices[4], @@ -3743,7 +4047,10 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil speed=100000, duplex='full', poe_mode=InterfacePoEModeChoices.MODE_PD, - poe_type=InterfacePoETypeChoices.TYPE_2_8023AT + poe_type=InterfacePoETypeChoices.TYPE_2_8023AT, + mode=InterfaceModeChoices.MODE_Q_IN_Q, + qinq_svlan=vlans[0], + vlan_translation_policy=vlan_translation_policies[1], ), Interface( device=devices[4], @@ -3752,7 +4059,9 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil type=InterfaceTypeChoices.TYPE_OTHER, enabled=True, mgmt_only=True, - tx_power=40 + tx_power=40, + mode=InterfaceModeChoices.MODE_Q_IN_Q, + qinq_svlan=vlans[1] ), Interface( device=devices[4], @@ -3761,7 +4070,9 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil type=InterfaceTypeChoices.TYPE_OTHER, enabled=False, mgmt_only=False, - tx_power=40 + tx_power=40, + mode=InterfaceModeChoices.MODE_Q_IN_Q, + qinq_svlan=vlans[2] ), Interface( device=devices[4], @@ -3790,6 +4101,10 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil interfaces[6].vdcs.set([vdcs[0]]) interfaces[7].vdcs.set([vdcs[1]]) + interfaces[0].mac_addresses.set([mac_addresses[0]]) + interfaces[2].mac_addresses.set([mac_addresses[1]]) + interfaces[3].mac_addresses.set([mac_addresses[2]]) + # Cables Cable(a_terminations=[interfaces[0]], b_terminations=[interfaces[5]]).save() Cable(a_terminations=[interfaces[1]], b_terminations=[interfaces[6]]).save() @@ -3847,9 +4162,24 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil # Create child interfaces parent_interface = Interface.objects.first() child_interfaces = ( - Interface(device=parent_interface.device, name='Child 1', parent=parent_interface, type=InterfaceTypeChoices.TYPE_VIRTUAL), - Interface(device=parent_interface.device, name='Child 2', parent=parent_interface, type=InterfaceTypeChoices.TYPE_VIRTUAL), - Interface(device=parent_interface.device, name='Child 3', parent=parent_interface, type=InterfaceTypeChoices.TYPE_VIRTUAL), + Interface( + device=parent_interface.device, + name='Child 1', + parent=parent_interface, + type=InterfaceTypeChoices.TYPE_VIRTUAL, + ), + Interface( + device=parent_interface.device, + name='Child 2', + parent=parent_interface, + type=InterfaceTypeChoices.TYPE_VIRTUAL, + ), + Interface( + device=parent_interface.device, + name='Child 3', + parent=parent_interface, + type=InterfaceTypeChoices.TYPE_VIRTUAL, + ), ) Interface.objects.bulk_create(child_interfaces) @@ -3860,9 +4190,24 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil # Create bridged interfaces bridge_interface = Interface.objects.first() bridged_interfaces = ( - Interface(device=bridge_interface.device, name='Bridged 1', bridge=bridge_interface, type=InterfaceTypeChoices.TYPE_1GE_FIXED), - Interface(device=bridge_interface.device, name='Bridged 2', bridge=bridge_interface, type=InterfaceTypeChoices.TYPE_1GE_FIXED), - Interface(device=bridge_interface.device, name='Bridged 3', bridge=bridge_interface, type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface( + device=bridge_interface.device, + name='Bridged 1', + bridge=bridge_interface, + type=InterfaceTypeChoices.TYPE_1GE_FIXED, + ), + Interface( + device=bridge_interface.device, + name='Bridged 2', + bridge=bridge_interface, + type=InterfaceTypeChoices.TYPE_1GE_FIXED, + ), + Interface( + device=bridge_interface.device, + name='Bridged 3', + bridge=bridge_interface, + type=InterfaceTypeChoices.TYPE_1GE_FIXED, + ), ) Interface.objects.bulk_create(bridged_interfaces) @@ -4017,6 +4362,20 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil params = {'vdc_identifier': vdc.values_list('identifier', flat=True)} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + def test_vlan(self): + vlan = VLAN.objects.filter(qinq_role=VLANQinQRoleChoices.ROLE_SERVICE).first() + params = {'vlan_id': vlan.pk} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'vlan': vlan.vid} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_vlan_translation_policy(self): + vlan_translation_policies = VLANTranslationPolicy.objects.all()[:2] + params = {'vlan_translation_policy_id': [vlan_translation_policies[0].pk, vlan_translation_policies[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'vlan_translation_policy': [vlan_translation_policies[0].name, vlan_translation_policies[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + class FrontPortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFilterSetTests): queryset = FrontPort.objects.all() @@ -4081,10 +4440,41 @@ class FrontPortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil Rack.objects.bulk_create(racks) devices = ( - Device(name='Device 1', device_type=device_types[0], role=roles[0], site=sites[0], location=locations[0], rack=racks[0], status='active'), - Device(name='Device 2', device_type=device_types[1], role=roles[1], site=sites[1], location=locations[1], rack=racks[1], status='planned'), - Device(name='Device 3', device_type=device_types[2], role=roles[2], site=sites[2], location=locations[2], rack=racks[2], status='offline'), - Device(name=None, device_type=device_types[2], role=roles[2], site=sites[3], status='offline'), # For cable connections + Device( + name='Device 1', + device_type=device_types[0], + role=roles[0], + site=sites[0], + location=locations[0], + rack=racks[0], + status='active', + ), + Device( + name='Device 2', + device_type=device_types[1], + role=roles[1], + site=sites[1], + location=locations[1], + rack=racks[1], + status='planned', + ), + Device( + name='Device 3', + device_type=device_types[2], + role=roles[2], + site=sites[2], + location=locations[2], + rack=racks[2], + status='offline', + ), + # For cable connections + Device( + name=None, + device_type=device_types[2], + role=roles[2], + site=sites[3], + status='offline' + ), ) Device.objects.bulk_create(devices) @@ -4114,12 +4504,63 @@ class FrontPortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil RearPort.objects.bulk_create(rear_ports) front_ports = ( - FrontPort(device=devices[0], module=modules[0], name='Front Port 1', label='A', type=PortTypeChoices.TYPE_8P8C, color=ColorChoices.COLOR_RED, rear_port=rear_ports[0], rear_port_position=1, description='First'), - FrontPort(device=devices[1], module=modules[1], name='Front Port 2', label='B', type=PortTypeChoices.TYPE_110_PUNCH, color=ColorChoices.COLOR_GREEN, rear_port=rear_ports[1], rear_port_position=2, description='Second'), - FrontPort(device=devices[2], module=modules[2], name='Front Port 3', label='C', type=PortTypeChoices.TYPE_BNC, color=ColorChoices.COLOR_BLUE, rear_port=rear_ports[2], rear_port_position=3, description='Third'), - FrontPort(device=devices[3], name='Front Port 4', label='D', type=PortTypeChoices.TYPE_FC, rear_port=rear_ports[3], rear_port_position=1), - FrontPort(device=devices[3], name='Front Port 5', label='E', type=PortTypeChoices.TYPE_FC, rear_port=rear_ports[4], rear_port_position=1), - FrontPort(device=devices[3], name='Front Port 6', label='F', type=PortTypeChoices.TYPE_FC, rear_port=rear_ports[5], rear_port_position=1), + FrontPort( + device=devices[0], + module=modules[0], + name='Front Port 1', + label='A', + type=PortTypeChoices.TYPE_8P8C, + color=ColorChoices.COLOR_RED, + rear_port=rear_ports[0], + rear_port_position=1, + description='First', + ), + FrontPort( + device=devices[1], + module=modules[1], + name='Front Port 2', + label='B', + type=PortTypeChoices.TYPE_110_PUNCH, + color=ColorChoices.COLOR_GREEN, + rear_port=rear_ports[1], + rear_port_position=2, + description='Second', + ), + FrontPort( + device=devices[2], + module=modules[2], + name='Front Port 3', + label='C', + type=PortTypeChoices.TYPE_BNC, + color=ColorChoices.COLOR_BLUE, + rear_port=rear_ports[2], + rear_port_position=3, + description='Third', + ), + FrontPort( + device=devices[3], + name='Front Port 4', + label='D', + type=PortTypeChoices.TYPE_FC, + rear_port=rear_ports[3], + rear_port_position=1, + ), + FrontPort( + device=devices[3], + name='Front Port 5', + label='E', + type=PortTypeChoices.TYPE_FC, + rear_port=rear_ports[4], + rear_port_position=1, + ), + FrontPort( + device=devices[3], + name='Front Port 6', + label='F', + type=PortTypeChoices.TYPE_FC, + rear_port=rear_ports[5], + rear_port_position=1, + ), ) FrontPort.objects.bulk_create(front_ports) @@ -4271,10 +4712,41 @@ class RearPortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFilt Rack.objects.bulk_create(racks) devices = ( - Device(name='Device 1', device_type=device_types[0], role=roles[0], site=sites[0], location=locations[0], rack=racks[0], status='active'), - Device(name='Device 2', device_type=device_types[1], role=roles[1], site=sites[1], location=locations[1], rack=racks[1], status='planned'), - Device(name='Device 3', device_type=device_types[2], role=roles[2], site=sites[2], location=locations[2], rack=racks[2], status='offline'), - Device(name=None, device_type=device_types[2], role=roles[2], site=sites[3], status='offline'), # For cable connections + Device( + name='Device 1', + device_type=device_types[0], + role=roles[0], + site=sites[0], + location=locations[0], + rack=racks[0], + status='active', + ), + Device( + name='Device 2', + device_type=device_types[1], + role=roles[1], + site=sites[1], + location=locations[1], + rack=racks[1], + status='planned', + ), + Device( + name='Device 3', + device_type=device_types[2], + role=roles[2], + site=sites[2], + location=locations[2], + rack=racks[2], + status='offline', + ), + # For cable connections + Device( + name=None, + device_type=device_types[2], + role=roles[2], + site=sites[3], + status='offline' + ), ) Device.objects.bulk_create(devices) @@ -4294,9 +4766,36 @@ class RearPortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFilt Module.objects.bulk_create(modules) rear_ports = ( - RearPort(device=devices[0], module=modules[0], name='Rear Port 1', label='A', type=PortTypeChoices.TYPE_8P8C, color=ColorChoices.COLOR_RED, positions=1, description='First'), - RearPort(device=devices[1], module=modules[1], name='Rear Port 2', label='B', type=PortTypeChoices.TYPE_110_PUNCH, color=ColorChoices.COLOR_GREEN, positions=2, description='Second'), - RearPort(device=devices[2], module=modules[2], name='Rear Port 3', label='C', type=PortTypeChoices.TYPE_BNC, color=ColorChoices.COLOR_BLUE, positions=3, description='Third'), + RearPort( + device=devices[0], + module=modules[0], + name='Rear Port 1', + label='A', + type=PortTypeChoices.TYPE_8P8C, + color=ColorChoices.COLOR_RED, + positions=1, + description='First', + ), + RearPort( + device=devices[1], + module=modules[1], + name='Rear Port 2', + label='B', + type=PortTypeChoices.TYPE_110_PUNCH, + color=ColorChoices.COLOR_GREEN, + positions=2, + description='Second', + ), + RearPort( + device=devices[2], + module=modules[2], + name='Rear Port 3', + label='C', + type=PortTypeChoices.TYPE_BNC, + color=ColorChoices.COLOR_BLUE, + positions=3, + description='Third', + ), RearPort(device=devices[3], name='Rear Port 4', label='D', type=PortTypeChoices.TYPE_FC, positions=4), RearPort(device=devices[3], name='Rear Port 5', label='E', type=PortTypeChoices.TYPE_FC, positions=5), RearPort(device=devices[3], name='Rear Port 6', label='F', type=PortTypeChoices.TYPE_FC, positions=6), @@ -4453,9 +4952,33 @@ class ModuleBayTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil Rack.objects.bulk_create(racks) devices = ( - Device(name='Device 1', device_type=device_types[0], role=roles[0], site=sites[0], location=locations[0], rack=racks[0], status='active'), - Device(name='Device 2', device_type=device_types[1], role=roles[1], site=sites[1], location=locations[1], rack=racks[1], status='planned'), - Device(name='Device 3', device_type=device_types[2], role=roles[2], site=sites[2], location=locations[2], rack=racks[2], status='offline'), + Device( + name='Device 1', + device_type=device_types[0], + role=roles[0], + site=sites[0], + location=locations[0], + rack=racks[0], + status='active', + ), + Device( + name='Device 2', + device_type=device_types[1], + role=roles[1], + site=sites[1], + location=locations[1], + rack=racks[1], + status='planned', + ), + Device( + name='Device 3', + device_type=device_types[2], + role=roles[2], + site=sites[2], + location=locations[2], + rack=racks[2], + status='offline', + ), ) Device.objects.bulk_create(devices) @@ -4601,9 +5124,33 @@ class DeviceBayTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil Rack.objects.bulk_create(racks) devices = ( - Device(name='Device 1', device_type=device_types[0], role=roles[0], site=sites[0], location=locations[0], rack=racks[0], status='active'), - Device(name='Device 2', device_type=device_types[1], role=roles[1], site=sites[1], location=locations[1], rack=racks[1], status='planned'), - Device(name='Device 3', device_type=device_types[2], role=roles[2], site=sites[2], location=locations[2], rack=racks[2], status='offline'), + Device( + name='Device 1', + device_type=device_types[0], + role=roles[0], + site=sites[0], + location=locations[0], + rack=racks[0], + status='active', + ), + Device( + name='Device 2', + device_type=device_types[1], + role=roles[1], + site=sites[1], + location=locations[1], + rack=racks[1], + status='planned', + ), + Device( + name='Device 3', + device_type=device_types[2], + role=roles[2], + site=sites[2], + location=locations[2], + rack=racks[2], + status='offline', + ), ) Device.objects.bulk_create(devices) @@ -4735,9 +5282,30 @@ class InventoryItemTestCase(TestCase, ChangeLoggedFilterSetTests): Rack.objects.bulk_create(racks) devices = ( - Device(name='Device 1', device_type=device_types[0], role=roles[0], site=sites[0], location=locations[0], rack=racks[0]), - Device(name='Device 2', device_type=device_types[1], role=roles[1], site=sites[1], location=locations[1], rack=racks[1]), - Device(name='Device 3', device_type=device_types[2], role=roles[2], site=sites[2], location=locations[2], rack=racks[2]), + Device( + name='Device 1', + device_type=device_types[0], + role=roles[0], + site=sites[0], + location=locations[0], + rack=racks[0], + ), + Device( + name='Device 2', + device_type=device_types[1], + role=roles[1], + site=sites[1], + location=locations[1], + rack=racks[1], + ), + Device( + name='Device 3', + device_type=device_types[2], + role=roles[2], + site=sites[2], + location=locations[2], + rack=racks[2], + ), ) Device.objects.bulk_create(devices) @@ -4755,9 +5323,48 @@ class InventoryItemTestCase(TestCase, ChangeLoggedFilterSetTests): ) inventory_items = ( - InventoryItem(device=devices[0], role=roles[0], manufacturer=manufacturers[0], name='Inventory Item 1', label='A', part_id='1001', serial='ABC', asset_tag='1001', discovered=True, status=ModuleStatusChoices.STATUS_ACTIVE, description='First', component=components[0]), - InventoryItem(device=devices[1], role=roles[1], manufacturer=manufacturers[1], name='Inventory Item 2', label='B', part_id='1002', serial='DEF', asset_tag='1002', discovered=True, status=ModuleStatusChoices.STATUS_PLANNED, description='Second', component=components[1]), - InventoryItem(device=devices[2], role=roles[2], manufacturer=manufacturers[2], name='Inventory Item 3', label='C', part_id='1003', serial='GHI', asset_tag='1003', discovered=False, status=ModuleStatusChoices.STATUS_FAILED, description='Third', component=components[2]), + InventoryItem( + device=devices[0], + role=roles[0], + manufacturer=manufacturers[0], + name='Inventory Item 1', + label='A', + part_id='1001', + serial='ABC', + asset_tag='1001', + discovered=True, + status=ModuleStatusChoices.STATUS_ACTIVE, + description='First', + component=components[0], + ), + InventoryItem( + device=devices[1], + role=roles[1], + manufacturer=manufacturers[1], + name='Inventory Item 2', + label='B', + part_id='1002', + serial='DEF', + asset_tag='1002', + discovered=True, + status=ModuleStatusChoices.STATUS_PLANNED, + description='Second', + component=components[1], + ), + InventoryItem( + device=devices[2], + role=roles[2], + manufacturer=manufacturers[2], + name='Inventory Item 3', + label='C', + part_id='1003', + serial='GHI', + asset_tag='1003', + discovered=False, + status=ModuleStatusChoices.STATUS_FAILED, + description='Third', + component=components[2], + ), ) for i in inventory_items: i.save() @@ -5074,12 +5681,60 @@ class CableTestCase(TestCase, ChangeLoggedFilterSetTests): role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') devices = ( - Device(name='Device 1', device_type=device_type, role=role, site=sites[0], rack=racks[0], location=locations[0], position=1), - Device(name='Device 2', device_type=device_type, role=role, site=sites[0], rack=racks[0], location=locations[0], position=2), - Device(name='Device 3', device_type=device_type, role=role, site=sites[1], rack=racks[1], location=locations[1], position=1), - Device(name='Device 4', device_type=device_type, role=role, site=sites[1], rack=racks[1], location=locations[1], position=2), - Device(name='Device 5', device_type=device_type, role=role, site=sites[2], rack=racks[2], location=locations[2], position=1), - Device(name='Device 6', device_type=device_type, role=role, site=sites[2], rack=racks[2], location=locations[2], position=2), + Device( + name='Device 1', + device_type=device_type, + role=role, + site=sites[0], + rack=racks[0], + location=locations[0], + position=1, + ), + Device( + name='Device 2', + device_type=device_type, + role=role, + site=sites[0], + rack=racks[0], + location=locations[0], + position=2, + ), + Device( + name='Device 3', + device_type=device_type, + role=role, + site=sites[1], + rack=racks[1], + location=locations[1], + position=1, + ), + Device( + name='Device 4', + device_type=device_type, + role=role, + site=sites[1], + rack=racks[1], + location=locations[1], + position=2, + ), + Device( + name='Device 5', + device_type=device_type, + role=role, + site=sites[2], + rack=racks[2], + location=locations[2], + position=1, + ), + Device( + name='Device 6', + device_type=device_type, + role=role, + site=sites[2], + rack=racks[2], + location=locations[2], + position=2, + ), ) Device.objects.bulk_create(devices) @@ -5118,7 +5773,7 @@ class CableTestCase(TestCase, ChangeLoggedFilterSetTests): provider = Provider.objects.create(name='Provider 1', slug='provider-1') circuit_type = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1') circuit = Circuit.objects.create(cid='Circuit 1', provider=provider, type=circuit_type) - circuit_termination = CircuitTermination.objects.create(circuit=circuit, term_side='A', site=sites[0]) + circuit_termination = CircuitTermination.objects.create(circuit=circuit, term_side='A', termination=sites[0]) # Cables cables = ( @@ -5291,9 +5946,9 @@ class CableTestCase(TestCase, ChangeLoggedFilterSetTests): def test_site(self): site = Site.objects.all()[:2] params = {'site_id': [site[0].pk, site[1].pk]} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 12) + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 11) params = {'site': [site[0].slug, site[1].slug]} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 12) + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 11) def test_tenant(self): tenant = Tenant.objects.all()[:2] @@ -5804,3 +6459,80 @@ class VirtualDeviceContextTestCase(TestCase, ChangeLoggedFilterSetTests): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) params = {'primary_ip6_id': [addresses[2].pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 0) + + +class MACAddressTestCase(TestCase, ChangeLoggedFilterSetTests): + queryset = MACAddress.objects.all() + filterset = MACAddressFilterSet + + @classmethod + def setUpTestData(cls): + devices = ( + create_test_device('Device 1'), + create_test_device('Device 2'), + create_test_device('Device 3'), + ) + interfaces = ( + Interface(device=devices[0], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface(device=devices[1], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface(device=devices[2], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED), + ) + Interface.objects.bulk_create(interfaces) + + virtual_machines = ( + create_test_virtualmachine('Virtual Machine 1'), + create_test_virtualmachine('Virtual Machine 2'), + create_test_virtualmachine('Virtual Machine 3'), + ) + vm_interfaces = ( + VMInterface(virtual_machine=virtual_machines[0], name='Interface 1'), + VMInterface(virtual_machine=virtual_machines[1], name='Interface 2'), + VMInterface(virtual_machine=virtual_machines[2], name='Interface 3'), + ) + VMInterface.objects.bulk_create(vm_interfaces) + + mac_addresses = ( + # Device MACs + MACAddress(mac_address='00-00-00-01-01-01', assigned_object=interfaces[0]), + MACAddress(mac_address='00-00-00-02-01-01', assigned_object=interfaces[1]), + MACAddress(mac_address='00-00-00-03-01-01', assigned_object=interfaces[2]), + MACAddress(mac_address='00-00-00-03-01-02', assigned_object=interfaces[2]), + # VM MACs + MACAddress(mac_address='00-00-00-04-01-01', assigned_object=vm_interfaces[0]), + MACAddress(mac_address='00-00-00-05-01-01', assigned_object=vm_interfaces[1]), + MACAddress(mac_address='00-00-00-06-01-01', assigned_object=vm_interfaces[2]), + MACAddress(mac_address='00-00-00-06-01-02', assigned_object=vm_interfaces[2]), + ) + MACAddress.objects.bulk_create(mac_addresses) + + def test_mac_address(self): + params = {'mac_address': ['00-00-00-01-01-01', '00-00-00-02-01-01']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_device(self): + devices = Device.objects.all()[:2] + params = {'device_id': [devices[0].pk, devices[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device': [devices[0].name, devices[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_virtual_machine(self): + virtual_machines = VirtualMachine.objects.all()[:2] + params = {'virtual_machine_id': [virtual_machines[0].pk, virtual_machines[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'virtual_machine': [virtual_machines[0].name, virtual_machines[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_interface(self): + interfaces = Interface.objects.all()[:2] + params = {'interface_id': [interfaces[0].pk, interfaces[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'interface': [interfaces[0].name, interfaces[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_vminterface(self): + vm_interfaces = VMInterface.objects.all()[:2] + params = {'vminterface_id': [vm_interfaces[0].pk, vm_interfaces[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'vminterface': [vm_interfaces[0].name, vm_interfaces[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) diff --git a/netbox/dcim/tests/test_models.py b/netbox/dcim/tests/test_models.py index c11badbdd..ff1eddd56 100644 --- a/netbox/dcim/tests/test_models.py +++ b/netbox/dcim/tests/test_models.py @@ -601,24 +601,42 @@ class DeviceTestCase(TestCase): Site.objects.bulk_create(sites) clusters = ( - Cluster(name='Cluster 1', type=cluster_type, site=sites[0]), - Cluster(name='Cluster 2', type=cluster_type, site=sites[1]), - Cluster(name='Cluster 3', type=cluster_type, site=None), + Cluster(name='Cluster 1', type=cluster_type, scope=sites[0]), + Cluster(name='Cluster 2', type=cluster_type, scope=sites[1]), + Cluster(name='Cluster 3', type=cluster_type, scope=None), ) - Cluster.objects.bulk_create(clusters) + for cluster in clusters: + cluster.save() device_type = DeviceType.objects.first() device_role = DeviceRole.objects.first() # Device with site only should pass - Device(name='device1', site=sites[0], device_type=device_type, role=device_role).full_clean() + Device( + name='device1', + site=sites[0], + device_type=device_type, + role=device_role + ).full_clean() # Device with site, cluster non-site should pass - Device(name='device1', site=sites[0], device_type=device_type, role=device_role, cluster=clusters[2]).full_clean() + Device( + name='device1', + site=sites[0], + device_type=device_type, + role=device_role, + cluster=clusters[2] + ).full_clean() # Device with mismatched site & cluster should fail with self.assertRaises(ValidationError): - Device(name='device1', site=sites[0], device_type=device_type, role=device_role, cluster=clusters[1]).full_clean() + Device( + name='device1', + site=sites[0], + device_type=device_type, + role=device_role, + cluster=clusters[1] + ).full_clean() class ModuleBayTestCase(TestCase): @@ -635,7 +653,9 @@ class ModuleBayTestCase(TestCase): # Create a CustomField with a default value & assign it to all component models location = Location.objects.create(name='Location 1', slug='location-1', site=site) rack = Rack.objects.create(name='Rack 1', site=site) - device = Device.objects.create(name='Device 1', device_type=device_type, role=device_role, site=site, location=location, rack=rack) + device = Device.objects.create( + name='Device 1', device_type=device_type, role=device_role, site=site, location=location, rack=rack + ) module_bays = ( ModuleBay(device=device, name='Module Bay 1', label='A', description='First'), @@ -762,9 +782,9 @@ class CableTestCase(TestCase): circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1') circuit1 = Circuit.objects.create(provider=provider, type=circuittype, cid='1') circuit2 = Circuit.objects.create(provider=provider, type=circuittype, cid='2') - CircuitTermination.objects.create(circuit=circuit1, site=site, term_side='A') - CircuitTermination.objects.create(circuit=circuit1, site=site, term_side='Z') - CircuitTermination.objects.create(circuit=circuit2, provider_network=provider_network, term_side='A') + CircuitTermination.objects.create(circuit=circuit1, termination=site, term_side='A') + CircuitTermination.objects.create(circuit=circuit1, termination=site, term_side='Z') + CircuitTermination.objects.create(circuit=circuit2, termination=provider_network, term_side='A') def test_cable_creation(self): """ diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index ca0db5588..bb942c685 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -196,9 +196,27 @@ class LocationTestCase(ViewTestCases.OrganizationalObjectViewTestCase): tenant = Tenant.objects.create(name='Tenant 1', slug='tenant-1') locations = ( - Location(name='Location 1', slug='location-1', site=site, status=LocationStatusChoices.STATUS_ACTIVE, tenant=tenant), - Location(name='Location 2', slug='location-2', site=site, status=LocationStatusChoices.STATUS_ACTIVE, tenant=tenant), - Location(name='Location 3', slug='location-3', site=site, status=LocationStatusChoices.STATUS_ACTIVE, tenant=tenant), + Location( + name='Location 1', + slug='location-1', + site=site, + status=LocationStatusChoices.STATUS_ACTIVE, + tenant=tenant, + ), + Location( + name='Location 2', + slug='location-2', + site=site, + status=LocationStatusChoices.STATUS_ACTIVE, + tenant=tenant, + ), + Location( + name='Location 3', + slug='location-3', + site=site, + status=LocationStatusChoices.STATUS_ACTIVE, + tenant=tenant, + ), ) for location in locations: location.save() @@ -346,9 +364,24 @@ class RackTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase): Manufacturer.objects.bulk_create(manufacturers) rack_types = ( - RackType(manufacturer=manufacturers[0], model='RackType 1', slug='rack-type-1', form_factor=RackFormFactorChoices.TYPE_CABINET,), - RackType(manufacturer=manufacturers[0], model='RackType 2', slug='rack-type-2', form_factor=RackFormFactorChoices.TYPE_CABINET,), - RackType(manufacturer=manufacturers[0], model='RackType 3', slug='rack-type-3', form_factor=RackFormFactorChoices.TYPE_CABINET,), + RackType( + manufacturer=manufacturers[0], + model='RackType 1', + slug='rack-type-1', + form_factor=RackFormFactorChoices.TYPE_CABINET, + ), + RackType( + manufacturer=manufacturers[0], + model='RackType 2', + slug='rack-type-2', + form_factor=RackFormFactorChoices.TYPE_CABINET, + ), + RackType( + manufacturer=manufacturers[0], + model='RackType 3', + slug='rack-type-3', + form_factor=RackFormFactorChoices.TYPE_CABINET, + ), ) RackType.objects.bulk_create(rack_types) @@ -592,7 +625,7 @@ class DeviceTypeTestCase( 'part_number': '123ABC', 'u_height': 2, 'is_full_depth': True, - 'subdevice_role': '', # CharField + 'subdevice_role': None, 'comments': 'Some comments', 'tags': [t.pk for t in tags], } @@ -692,9 +725,15 @@ class DeviceTypeTestCase( ) RearPortTemplate.objects.bulk_create(rear_ports) front_ports = ( - FrontPortTemplate(device_type=devicetype, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1), - FrontPortTemplate(device_type=devicetype, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1), - FrontPortTemplate(device_type=devicetype, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1), + FrontPortTemplate( + device_type=devicetype, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1 + ), + FrontPortTemplate( + device_type=devicetype, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1 + ), + FrontPortTemplate( + device_type=devicetype, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1 + ), ) FrontPortTemplate.objects.bulk_create(front_ports) @@ -861,7 +900,7 @@ inventory-items: 'data': IMPORT_DATA, 'format': 'yaml' } - response = self.client.post(reverse('dcim:devicetype_import'), data=form_data, follow=True) + response = self.client.post(reverse('dcim:devicetype_bulk_import'), data=form_data, follow=True) self.assertHttpStatus(response, 200) device_type = DeviceType.objects.get(model='TEST-1000') @@ -1081,9 +1120,15 @@ class ModuleTypeTestCase( ) RearPortTemplate.objects.bulk_create(rear_ports) front_ports = ( - FrontPortTemplate(module_type=moduletype, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1), - FrontPortTemplate(module_type=moduletype, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1), - FrontPortTemplate(module_type=moduletype, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1), + FrontPortTemplate( + module_type=moduletype, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1 + ), + FrontPortTemplate( + module_type=moduletype, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1 + ), + FrontPortTemplate( + module_type=moduletype, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1 + ), ) FrontPortTemplate.objects.bulk_create(front_ports) @@ -1183,7 +1228,7 @@ front-ports: 'data': IMPORT_DATA, 'format': 'yaml' } - response = self.client.post(reverse('dcim:moduletype_import'), data=form_data, follow=True) + response = self.client.post(reverse('dcim:moduletype_bulk_import'), data=form_data, follow=True) self.assertHttpStatus(response, 200) module_type = ModuleType.objects.get(model='TEST-1000') @@ -1453,11 +1498,19 @@ class FrontPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCas ) RearPortTemplate.objects.bulk_create(rearports) - FrontPortTemplate.objects.bulk_create(( - FrontPortTemplate(device_type=devicetype, name='Front Port Template 1', rear_port=rearports[0], rear_port_position=1), - FrontPortTemplate(device_type=devicetype, name='Front Port Template 2', rear_port=rearports[1], rear_port_position=1), - FrontPortTemplate(device_type=devicetype, name='Front Port Template 3', rear_port=rearports[2], rear_port_position=1), - )) + FrontPortTemplate.objects.bulk_create( + ( + FrontPortTemplate( + device_type=devicetype, name='Front Port Template 1', rear_port=rearports[0], rear_port_position=1 + ), + FrontPortTemplate( + device_type=devicetype, name='Front Port Template 2', rear_port=rearports[1], rear_port_position=1 + ), + FrontPortTemplate( + device_type=devicetype, name='Front Port Template 3', rear_port=rearports[2], rear_port_position=1 + ), + ) + ) cls.form_data = { 'device_type': devicetype.pk, @@ -1550,7 +1603,12 @@ class DeviceBayTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCas @classmethod def setUpTestData(cls): manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') - devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1', subdevice_role=SubdeviceRoleChoices.ROLE_PARENT) + devicetype = DeviceType.objects.create( + manufacturer=manufacturer, + model='Device Type 1', + slug='device-type-1', + subdevice_role=SubdeviceRoleChoices.ROLE_PARENT + ) DeviceBayTemplate.objects.bulk_create(( DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 1'), @@ -1584,12 +1642,20 @@ class InventoryItemTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTes Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), ) Manufacturer.objects.bulk_create(manufacturers) - devicetype = DeviceType.objects.create(manufacturer=manufacturers[0], model='Device Type 1', slug='device-type-1') + devicetype = DeviceType.objects.create( + manufacturer=manufacturers[0], model='Device Type 1', slug='device-type-1' + ) inventory_item_templates = ( - InventoryItemTemplate(device_type=devicetype, name='Inventory Item Template 1', manufacturer=manufacturers[0]), - InventoryItemTemplate(device_type=devicetype, name='Inventory Item Template 2', manufacturer=manufacturers[0]), - InventoryItemTemplate(device_type=devicetype, name='Inventory Item Template 3', manufacturer=manufacturers[0]), + InventoryItemTemplate( + device_type=devicetype, name='Inventory Item Template 1', manufacturer=manufacturers[0] + ), + InventoryItemTemplate( + device_type=devicetype, name='Inventory Item Template 2', manufacturer=manufacturers[0] + ), + InventoryItemTemplate( + device_type=devicetype, name='Inventory Item Template 3', manufacturer=manufacturers[0] + ), ) for item in inventory_item_templates: item.save() @@ -1741,9 +1807,30 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase): Platform.objects.bulk_create(platforms) devices = ( - Device(name='Device 1', site=sites[0], rack=racks[0], device_type=devicetypes[0], role=roles[0], platform=platforms[0]), - Device(name='Device 2', site=sites[0], rack=racks[0], device_type=devicetypes[0], role=roles[0], platform=platforms[0]), - Device(name='Device 3', site=sites[0], rack=racks[0], device_type=devicetypes[0], role=roles[0], platform=platforms[0]), + Device( + name='Device 1', + site=sites[0], + rack=racks[0], + device_type=devicetypes[0], + role=roles[0], + platform=platforms[0], + ), + Device( + name='Device 2', + site=sites[0], + rack=racks[0], + device_type=devicetypes[0], + role=roles[0], + platform=platforms[0], + ), + Device( + name='Device 3', + site=sites[0], + rack=racks[0], + device_type=devicetypes[0], + role=roles[0], + platform=platforms[0], + ), ) Device.objects.bulk_create(devices) @@ -1778,10 +1865,22 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase): } cls.csv_data = ( - "role,manufacturer,device_type,status,name,site,location,rack,position,face,virtual_chassis,vc_position,vc_priority", - "Device Role 1,Manufacturer 1,Device Type 1,active,Device 4,Site 1,Location 1,Rack 1,10,front,Virtual Chassis 1,1,10", - "Device Role 1,Manufacturer 1,Device Type 1,active,Device 5,Site 1,Location 1,Rack 1,20,front,Virtual Chassis 1,2,20", - "Device Role 1,Manufacturer 1,Device Type 1,active,Device 6,Site 1,Location 1,Rack 1,30,front,Virtual Chassis 1,3,30", + ( + "role,manufacturer,device_type,status,name,site,location,rack,position,face,virtual_chassis," + "vc_position,vc_priority" + ), + ( + "Device Role 1,Manufacturer 1,Device Type 1,active,Device 4,Site 1,Location 1,Rack 1,10,front," + "Virtual Chassis 1,1,10" + ), + ( + "Device Role 1,Manufacturer 1,Device Type 1,active,Device 5,Site 1,Location 1,Rack 1,20,front," + "Virtual Chassis 1,2,20" + ), + ( + "Device Role 1,Manufacturer 1,Device Type 1,active,Device 6,Site 1,Location 1,Rack 1,30,front," + "Virtual Chassis 1,3,30" + ), ) cls.csv_update_data = ( @@ -2071,7 +2170,7 @@ class ModuleTestCase( f"{device.name},{module_bay.name},{module_type.model},active,false" ] request = { - 'path': self._get_url('import'), + 'path': self._get_url('bulk_import'), 'data': { 'data': '\n'.join(csv_data), 'format': ImportFormatChoices.CSV, @@ -2088,7 +2187,7 @@ class ModuleTestCase( module_bay = ModuleBay.objects.get(device=device, name='Module Bay 5') csv_data[1] = f"{device.name},{module_bay.name},{module_type.model},active,true" request = { - 'path': self._get_url('import'), + 'path': self._get_url('bulk_import'), 'data': { 'data': '\n'.join(csv_data), 'format': ImportFormatChoices.CSV, @@ -2165,7 +2264,7 @@ class ModuleTestCase( f"{device.name},{module_bay.name},{module_type.model},active,false,true" ] request = { - 'path': self._get_url('import'), + 'path': self._get_url('bulk_import'), 'data': { 'data': '\n'.join(csv_data), 'format': ImportFormatChoices.CSV, @@ -2508,7 +2607,6 @@ class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase): 'enabled': False, 'bridge': interfaces[4].pk, 'lag': interfaces[3].pk, - 'mac_address': EUI('01:02:03:04:05:06'), 'wwn': EUI('01:02:03:04:05:06:07:08', version=64), 'mtu': 65000, 'speed': 1000000, @@ -2533,7 +2631,6 @@ class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase): 'enabled': False, 'bridge': interfaces[4].pk, 'lag': interfaces[3].pk, - 'mac_address': EUI('01:02:03:04:05:06'), 'wwn': EUI('01:02:03:04:05:06:07:08', version=64), 'mtu': 2000, 'speed': 100000, @@ -2554,7 +2651,6 @@ class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase): 'type': InterfaceTypeChoices.TYPE_1GE_FIXED, 'enabled': True, 'lag': interfaces[3].pk, - 'mac_address': EUI('01:02:03:04:05:06'), 'wwn': EUI('01:02:03:04:05:06:07:08', version=64), 'mtu': 2000, 'speed': 1000000, @@ -2887,9 +2983,15 @@ class InventoryItemTestCase(ViewTestCases.DeviceComponentViewTestCase): ) InventoryItemRole.objects.bulk_create(roles) - inventory_item1 = InventoryItem.objects.create(device=device, name='Inventory Item 1', role=roles[0], manufacturer=manufacturer) - inventory_item2 = InventoryItem.objects.create(device=device, name='Inventory Item 2', role=roles[0], manufacturer=manufacturer) - inventory_item3 = InventoryItem.objects.create(device=device, name='Inventory Item 3', role=roles[0], manufacturer=manufacturer) + inventory_item1 = InventoryItem.objects.create( + device=device, name='Inventory Item 1', role=roles[0], manufacturer=manufacturer + ) + inventory_item2 = InventoryItem.objects.create( + device=device, name='Inventory Item 2', role=roles[0], manufacturer=manufacturer + ) + inventory_item3 = InventoryItem.objects.create( + device=device, name='Inventory Item 3', role=roles[0], manufacturer=manufacturer + ) tags = create_tags('Alpha', 'Bravo', 'Charlie') diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index 627136bf9..bcfd32707 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -6,327 +6,144 @@ from . import views app_name = 'dcim' urlpatterns = [ - # Regions - path('regions/', views.RegionListView.as_view(), name='region_list'), - path('regions/add/', views.RegionEditView.as_view(), name='region_add'), - path('regions/import/', views.RegionBulkImportView.as_view(), name='region_import'), - path('regions/edit/', views.RegionBulkEditView.as_view(), name='region_bulk_edit'), - path('regions/delete/', views.RegionBulkDeleteView.as_view(), name='region_bulk_delete'), + path('regions/', include(get_model_urls('dcim', 'region', detail=False))), path('regions//', include(get_model_urls('dcim', 'region'))), - # Site groups - path('site-groups/', views.SiteGroupListView.as_view(), name='sitegroup_list'), - path('site-groups/add/', views.SiteGroupEditView.as_view(), name='sitegroup_add'), - path('site-groups/import/', views.SiteGroupBulkImportView.as_view(), name='sitegroup_import'), - path('site-groups/edit/', views.SiteGroupBulkEditView.as_view(), name='sitegroup_bulk_edit'), - path('site-groups/delete/', views.SiteGroupBulkDeleteView.as_view(), name='sitegroup_bulk_delete'), + path('site-groups/', include(get_model_urls('dcim', 'sitegroup', detail=False))), path('site-groups//', include(get_model_urls('dcim', 'sitegroup'))), - # Sites - path('sites/', views.SiteListView.as_view(), name='site_list'), - path('sites/add/', views.SiteEditView.as_view(), name='site_add'), - path('sites/import/', views.SiteBulkImportView.as_view(), name='site_import'), - path('sites/edit/', views.SiteBulkEditView.as_view(), name='site_bulk_edit'), - path('sites/delete/', views.SiteBulkDeleteView.as_view(), name='site_bulk_delete'), + path('sites/', include(get_model_urls('dcim', 'site', detail=False))), path('sites//', include(get_model_urls('dcim', 'site'))), - # Locations - path('locations/', views.LocationListView.as_view(), name='location_list'), - path('locations/add/', views.LocationEditView.as_view(), name='location_add'), - path('locations/import/', views.LocationBulkImportView.as_view(), name='location_import'), - path('locations/edit/', views.LocationBulkEditView.as_view(), name='location_bulk_edit'), - path('locations/delete/', views.LocationBulkDeleteView.as_view(), name='location_bulk_delete'), + path('locations/', include(get_model_urls('dcim', 'location', detail=False))), path('locations//', include(get_model_urls('dcim', 'location'))), - # Rack roles - path('rack-roles/', views.RackRoleListView.as_view(), name='rackrole_list'), - path('rack-roles/add/', views.RackRoleEditView.as_view(), name='rackrole_add'), - path('rack-roles/import/', views.RackRoleBulkImportView.as_view(), name='rackrole_import'), - path('rack-roles/edit/', views.RackRoleBulkEditView.as_view(), name='rackrole_bulk_edit'), - path('rack-roles/delete/', views.RackRoleBulkDeleteView.as_view(), name='rackrole_bulk_delete'), + path('rack-roles/', include(get_model_urls('dcim', 'rackrole', detail=False))), path('rack-roles//', include(get_model_urls('dcim', 'rackrole'))), - # Rack reservations - path('rack-reservations/', views.RackReservationListView.as_view(), name='rackreservation_list'), - path('rack-reservations/add/', views.RackReservationEditView.as_view(), name='rackreservation_add'), - path('rack-reservations/import/', views.RackReservationImportView.as_view(), name='rackreservation_import'), - path('rack-reservations/edit/', views.RackReservationBulkEditView.as_view(), name='rackreservation_bulk_edit'), - path('rack-reservations/delete/', views.RackReservationBulkDeleteView.as_view(), name='rackreservation_bulk_delete'), + path('rack-reservations/', include(get_model_urls('dcim', 'rackreservation', detail=False))), path('rack-reservations//', include(get_model_urls('dcim', 'rackreservation'))), - # Racks - path('racks/', views.RackListView.as_view(), name='rack_list'), - path('rack-elevations/', views.RackElevationListView.as_view(), name='rack_elevation_list'), - path('racks/add/', views.RackEditView.as_view(), name='rack_add'), - path('racks/import/', views.RackBulkImportView.as_view(), name='rack_import'), - path('racks/edit/', views.RackBulkEditView.as_view(), name='rack_bulk_edit'), - path('racks/delete/', views.RackBulkDeleteView.as_view(), name='rack_bulk_delete'), + path('racks/', include(get_model_urls('dcim', 'rack', detail=False))), path('racks//', include(get_model_urls('dcim', 'rack'))), + path('rack-elevations/', views.RackElevationListView.as_view(), name='rack_elevation_list'), - # Rack Types - path('rack-types/', views.RackTypeListView.as_view(), name='racktype_list'), - path('rack-types/add/', views.RackTypeEditView.as_view(), name='racktype_add'), - path('rack-types/import/', views.RackTypeBulkImportView.as_view(), name='racktype_import'), - path('rack-types/edit/', views.RackTypeBulkEditView.as_view(), name='racktype_bulk_edit'), - path('rack-types/delete/', views.RackTypeBulkDeleteView.as_view(), name='racktype_bulk_delete'), + path('rack-types/', include(get_model_urls('dcim', 'racktype', detail=False))), path('rack-types//', include(get_model_urls('dcim', 'racktype'))), - # Manufacturers - path('manufacturers/', views.ManufacturerListView.as_view(), name='manufacturer_list'), - path('manufacturers/add/', views.ManufacturerEditView.as_view(), name='manufacturer_add'), - path('manufacturers/import/', views.ManufacturerBulkImportView.as_view(), name='manufacturer_import'), - path('manufacturers/edit/', views.ManufacturerBulkEditView.as_view(), name='manufacturer_bulk_edit'), - path('manufacturers/delete/', views.ManufacturerBulkDeleteView.as_view(), name='manufacturer_bulk_delete'), + path('manufacturers/', include(get_model_urls('dcim', 'manufacturer', detail=False))), path('manufacturers//', include(get_model_urls('dcim', 'manufacturer'))), - # Device types - path('device-types/', views.DeviceTypeListView.as_view(), name='devicetype_list'), - path('device-types/add/', views.DeviceTypeEditView.as_view(), name='devicetype_add'), - path('device-types/import/', views.DeviceTypeImportView.as_view(), name='devicetype_import'), - path('device-types/edit/', views.DeviceTypeBulkEditView.as_view(), name='devicetype_bulk_edit'), - path('device-types/delete/', views.DeviceTypeBulkDeleteView.as_view(), name='devicetype_bulk_delete'), + path('device-types/', include(get_model_urls('dcim', 'devicetype', detail=False))), path('device-types//', include(get_model_urls('dcim', 'devicetype'))), - # Module types - path('module-types/', views.ModuleTypeListView.as_view(), name='moduletype_list'), - path('module-types/add/', views.ModuleTypeEditView.as_view(), name='moduletype_add'), - path('module-types/import/', views.ModuleTypeImportView.as_view(), name='moduletype_import'), - path('module-types/edit/', views.ModuleTypeBulkEditView.as_view(), name='moduletype_bulk_edit'), - path('module-types/delete/', views.ModuleTypeBulkDeleteView.as_view(), name='moduletype_bulk_delete'), + path('module-types/', include(get_model_urls('dcim', 'moduletype', detail=False))), path('module-types//', include(get_model_urls('dcim', 'moduletype'))), - # Console port templates - path('console-port-templates/add/', views.ConsolePortTemplateCreateView.as_view(), name='consoleporttemplate_add'), - path('console-port-templates/edit/', views.ConsolePortTemplateBulkEditView.as_view(), name='consoleporttemplate_bulk_edit'), - path('console-port-templates/rename/', views.ConsolePortTemplateBulkRenameView.as_view(), name='consoleporttemplate_bulk_rename'), - path('console-port-templates/delete/', views.ConsolePortTemplateBulkDeleteView.as_view(), name='consoleporttemplate_bulk_delete'), + path('console-port-templates/', include(get_model_urls('dcim', 'consoleporttemplate', detail=False))), path('console-port-templates//', include(get_model_urls('dcim', 'consoleporttemplate'))), - # Console server port templates - path('console-server-port-templates/add/', views.ConsoleServerPortTemplateCreateView.as_view(), name='consoleserverporttemplate_add'), - path('console-server-port-templates/edit/', views.ConsoleServerPortTemplateBulkEditView.as_view(), name='consoleserverporttemplate_bulk_edit'), - path('console-server-port-templates/rename/', views.ConsoleServerPortTemplateBulkRenameView.as_view(), name='consoleserverporttemplate_bulk_rename'), - path('console-server-port-templates/delete/', views.ConsoleServerPortTemplateBulkDeleteView.as_view(), name='consoleserverporttemplate_bulk_delete'), + path('console-server-port-templates/', include(get_model_urls('dcim', 'consoleserverporttemplate', detail=False))), path('console-server-port-templates//', include(get_model_urls('dcim', 'consoleserverporttemplate'))), - # Power port templates - path('power-port-templates/add/', views.PowerPortTemplateCreateView.as_view(), name='powerporttemplate_add'), - path('power-port-templates/edit/', views.PowerPortTemplateBulkEditView.as_view(), name='powerporttemplate_bulk_edit'), - path('power-port-templates/rename/', views.PowerPortTemplateBulkRenameView.as_view(), name='powerporttemplate_bulk_rename'), - path('power-port-templates/delete/', views.PowerPortTemplateBulkDeleteView.as_view(), name='powerporttemplate_bulk_delete'), + path('power-port-templates/', include(get_model_urls('dcim', 'powerporttemplate', detail=False))), path('power-port-templates//', include(get_model_urls('dcim', 'powerporttemplate'))), - # Power outlet templates - path('power-outlet-templates/add/', views.PowerOutletTemplateCreateView.as_view(), name='poweroutlettemplate_add'), - path('power-outlet-templates/edit/', views.PowerOutletTemplateBulkEditView.as_view(), name='poweroutlettemplate_bulk_edit'), - path('power-outlet-templates/rename/', views.PowerOutletTemplateBulkRenameView.as_view(), name='poweroutlettemplate_bulk_rename'), - path('power-outlet-templates/delete/', views.PowerOutletTemplateBulkDeleteView.as_view(), name='poweroutlettemplate_bulk_delete'), + path('power-outlet-templates/', include(get_model_urls('dcim', 'poweroutlettemplate', detail=False))), path('power-outlet-templates//', include(get_model_urls('dcim', 'poweroutlettemplate'))), - # Interface templates - path('interface-templates/add/', views.InterfaceTemplateCreateView.as_view(), name='interfacetemplate_add'), - path('interface-templates/edit/', views.InterfaceTemplateBulkEditView.as_view(), name='interfacetemplate_bulk_edit'), - path('interface-templates/rename/', views.InterfaceTemplateBulkRenameView.as_view(), name='interfacetemplate_bulk_rename'), - path('interface-templates/delete/', views.InterfaceTemplateBulkDeleteView.as_view(), name='interfacetemplate_bulk_delete'), + path('interface-templates/', include(get_model_urls('dcim', 'interfacetemplate', detail=False))), path('interface-templates//', include(get_model_urls('dcim', 'interfacetemplate'))), - # Front port templates - path('front-port-templates/add/', views.FrontPortTemplateCreateView.as_view(), name='frontporttemplate_add'), - path('front-port-templates/edit/', views.FrontPortTemplateBulkEditView.as_view(), name='frontporttemplate_bulk_edit'), - path('front-port-templates/rename/', views.FrontPortTemplateBulkRenameView.as_view(), name='frontporttemplate_bulk_rename'), - path('front-port-templates/delete/', views.FrontPortTemplateBulkDeleteView.as_view(), name='frontporttemplate_bulk_delete'), + path('front-port-templates/', include(get_model_urls('dcim', 'frontporttemplate', detail=False))), path('front-port-templates//', include(get_model_urls('dcim', 'frontporttemplate'))), - # Rear port templates - path('rear-port-templates/add/', views.RearPortTemplateCreateView.as_view(), name='rearporttemplate_add'), - path('rear-port-templates/edit/', views.RearPortTemplateBulkEditView.as_view(), name='rearporttemplate_bulk_edit'), - path('rear-port-templates/rename/', views.RearPortTemplateBulkRenameView.as_view(), name='rearporttemplate_bulk_rename'), - path('rear-port-templates/delete/', views.RearPortTemplateBulkDeleteView.as_view(), name='rearporttemplate_bulk_delete'), + path('rear-port-templates/', include(get_model_urls('dcim', 'rearporttemplate', detail=False))), path('rear-port-templates//', include(get_model_urls('dcim', 'rearporttemplate'))), - # Device bay templates - path('device-bay-templates/add/', views.DeviceBayTemplateCreateView.as_view(), name='devicebaytemplate_add'), - path('device-bay-templates/edit/', views.DeviceBayTemplateBulkEditView.as_view(), name='devicebaytemplate_bulk_edit'), - path('device-bay-templates/rename/', views.DeviceBayTemplateBulkRenameView.as_view(), name='devicebaytemplate_bulk_rename'), - path('device-bay-templates/delete/', views.DeviceBayTemplateBulkDeleteView.as_view(), name='devicebaytemplate_bulk_delete'), + path('device-bay-templates/', include(get_model_urls('dcim', 'devicebaytemplate', detail=False))), path('device-bay-templates//', include(get_model_urls('dcim', 'devicebaytemplate'))), - # Module bay templates - path('module-bay-templates/add/', views.ModuleBayTemplateCreateView.as_view(), name='modulebaytemplate_add'), - path('module-bay-templates/edit/', views.ModuleBayTemplateBulkEditView.as_view(), name='modulebaytemplate_bulk_edit'), - path('module-bay-templates/rename/', views.ModuleBayTemplateBulkRenameView.as_view(), name='modulebaytemplate_bulk_rename'), - path('module-bay-templates/delete/', views.ModuleBayTemplateBulkDeleteView.as_view(), name='modulebaytemplate_bulk_delete'), + path('module-bay-templates/', include(get_model_urls('dcim', 'modulebaytemplate', detail=False))), path('module-bay-templates//', include(get_model_urls('dcim', 'modulebaytemplate'))), - # Inventory item templates - path('inventory-item-templates/add/', views.InventoryItemTemplateCreateView.as_view(), name='inventoryitemtemplate_add'), - path('inventory-item-templates/edit/', views.InventoryItemTemplateBulkEditView.as_view(), name='inventoryitemtemplate_bulk_edit'), - path('inventory-item-templates/rename/', views.InventoryItemTemplateBulkRenameView.as_view(), name='inventoryitemtemplate_bulk_rename'), - path('inventory-item-templates/delete/', views.InventoryItemTemplateBulkDeleteView.as_view(), name='inventoryitemtemplate_bulk_delete'), + path('inventory-item-templates/', include(get_model_urls('dcim', 'inventoryitemtemplate', detail=False))), path('inventory-item-templates//', include(get_model_urls('dcim', 'inventoryitemtemplate'))), - # Device roles - path('device-roles/', views.DeviceRoleListView.as_view(), name='devicerole_list'), - path('device-roles/add/', views.DeviceRoleEditView.as_view(), name='devicerole_add'), - path('device-roles/import/', views.DeviceRoleBulkImportView.as_view(), name='devicerole_import'), - path('device-roles/edit/', views.DeviceRoleBulkEditView.as_view(), name='devicerole_bulk_edit'), - path('device-roles/delete/', views.DeviceRoleBulkDeleteView.as_view(), name='devicerole_bulk_delete'), + path('device-roles/', include(get_model_urls('dcim', 'devicerole', detail=False))), path('device-roles//', include(get_model_urls('dcim', 'devicerole'))), - # Platforms - path('platforms/', views.PlatformListView.as_view(), name='platform_list'), - path('platforms/add/', views.PlatformEditView.as_view(), name='platform_add'), - path('platforms/import/', views.PlatformBulkImportView.as_view(), name='platform_import'), - path('platforms/edit/', views.PlatformBulkEditView.as_view(), name='platform_bulk_edit'), - path('platforms/delete/', views.PlatformBulkDeleteView.as_view(), name='platform_bulk_delete'), + path('platforms/', include(get_model_urls('dcim', 'platform', detail=False))), path('platforms//', include(get_model_urls('dcim', 'platform'))), - # Devices - path('devices/', views.DeviceListView.as_view(), name='device_list'), - path('devices/add/', views.DeviceEditView.as_view(), name='device_add'), - path('devices/import/', views.DeviceBulkImportView.as_view(), name='device_import'), - path('devices/edit/', views.DeviceBulkEditView.as_view(), name='device_bulk_edit'), - path('devices/rename/', views.DeviceBulkRenameView.as_view(), name='device_bulk_rename'), - path('devices/delete/', views.DeviceBulkDeleteView.as_view(), name='device_bulk_delete'), + path('devices/', include(get_model_urls('dcim', 'device', detail=False))), path('devices//', include(get_model_urls('dcim', 'device'))), - # Virtual Device Context - path('virtual-device-contexts/', views.VirtualDeviceContextListView.as_view(), name='virtualdevicecontext_list'), - path('virtual-device-contexts/add/', views.VirtualDeviceContextEditView.as_view(), name='virtualdevicecontext_add'), - path('virtual-device-contexts/import/', views.VirtualDeviceContextBulkImportView.as_view(), name='virtualdevicecontext_import'), - path('virtual-device-contexts/edit/', views.VirtualDeviceContextBulkEditView.as_view(), name='virtualdevicecontext_bulk_edit'), - path('virtual-device-contexts/delete/', views.VirtualDeviceContextBulkDeleteView.as_view(), name='virtualdevicecontext_bulk_delete'), + path('virtual-device-contexts/', include(get_model_urls('dcim', 'virtualdevicecontext', detail=False))), path('virtual-device-contexts//', include(get_model_urls('dcim', 'virtualdevicecontext'))), - # Modules - path('modules/', views.ModuleListView.as_view(), name='module_list'), - path('modules/add/', views.ModuleEditView.as_view(), name='module_add'), - path('modules/import/', views.ModuleBulkImportView.as_view(), name='module_import'), - path('modules/edit/', views.ModuleBulkEditView.as_view(), name='module_bulk_edit'), - path('modules/delete/', views.ModuleBulkDeleteView.as_view(), name='module_bulk_delete'), + path('modules/', include(get_model_urls('dcim', 'module', detail=False))), path('modules//', include(get_model_urls('dcim', 'module'))), - # Console ports - path('console-ports/', views.ConsolePortListView.as_view(), name='consoleport_list'), - path('console-ports/add/', views.ConsolePortCreateView.as_view(), name='consoleport_add'), - path('console-ports/import/', views.ConsolePortBulkImportView.as_view(), name='consoleport_import'), - path('console-ports/edit/', views.ConsolePortBulkEditView.as_view(), name='consoleport_bulk_edit'), - path('console-ports/rename/', views.ConsolePortBulkRenameView.as_view(), name='consoleport_bulk_rename'), - path('console-ports/disconnect/', views.ConsolePortBulkDisconnectView.as_view(), name='consoleport_bulk_disconnect'), - path('console-ports/delete/', views.ConsolePortBulkDeleteView.as_view(), name='consoleport_bulk_delete'), + path('console-ports/', include(get_model_urls('dcim', 'consoleport', detail=False))), path('console-ports//', include(get_model_urls('dcim', 'consoleport'))), - path('devices/console-ports/add/', views.DeviceBulkAddConsolePortView.as_view(), name='device_bulk_add_consoleport'), + path( + 'devices/console-ports/add/', + views.DeviceBulkAddConsolePortView.as_view(), + name='device_bulk_add_consoleport' + ), - # Console server ports - path('console-server-ports/', views.ConsoleServerPortListView.as_view(), name='consoleserverport_list'), - path('console-server-ports/add/', views.ConsoleServerPortCreateView.as_view(), name='consoleserverport_add'), - path('console-server-ports/import/', views.ConsoleServerPortBulkImportView.as_view(), name='consoleserverport_import'), - path('console-server-ports/edit/', views.ConsoleServerPortBulkEditView.as_view(), name='consoleserverport_bulk_edit'), - path('console-server-ports/rename/', views.ConsoleServerPortBulkRenameView.as_view(), name='consoleserverport_bulk_rename'), - path('console-server-ports/disconnect/', views.ConsoleServerPortBulkDisconnectView.as_view(), name='consoleserverport_bulk_disconnect'), - path('console-server-ports/delete/', views.ConsoleServerPortBulkDeleteView.as_view(), name='consoleserverport_bulk_delete'), + path('console-server-ports/', include(get_model_urls('dcim', 'consoleserverport', detail=False))), path('console-server-ports//', include(get_model_urls('dcim', 'consoleserverport'))), - path('devices/console-server-ports/add/', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'), + path( + 'devices/console-server-ports/add/', + views.DeviceBulkAddConsoleServerPortView.as_view(), + name='device_bulk_add_consoleserverport' + ), - # Power ports - path('power-ports/', views.PowerPortListView.as_view(), name='powerport_list'), - path('power-ports/add/', views.PowerPortCreateView.as_view(), name='powerport_add'), - path('power-ports/import/', views.PowerPortBulkImportView.as_view(), name='powerport_import'), - path('power-ports/edit/', views.PowerPortBulkEditView.as_view(), name='powerport_bulk_edit'), - path('power-ports/rename/', views.PowerPortBulkRenameView.as_view(), name='powerport_bulk_rename'), - path('power-ports/disconnect/', views.PowerPortBulkDisconnectView.as_view(), name='powerport_bulk_disconnect'), - path('power-ports/delete/', views.PowerPortBulkDeleteView.as_view(), name='powerport_bulk_delete'), + path('power-ports/', include(get_model_urls('dcim', 'powerport', detail=False))), path('power-ports//', include(get_model_urls('dcim', 'powerport'))), path('devices/power-ports/add/', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'), - # Power outlets - path('power-outlets/', views.PowerOutletListView.as_view(), name='poweroutlet_list'), - path('power-outlets/add/', views.PowerOutletCreateView.as_view(), name='poweroutlet_add'), - path('power-outlets/import/', views.PowerOutletBulkImportView.as_view(), name='poweroutlet_import'), - path('power-outlets/edit/', views.PowerOutletBulkEditView.as_view(), name='poweroutlet_bulk_edit'), - path('power-outlets/rename/', views.PowerOutletBulkRenameView.as_view(), name='poweroutlet_bulk_rename'), - path('power-outlets/disconnect/', views.PowerOutletBulkDisconnectView.as_view(), name='poweroutlet_bulk_disconnect'), - path('power-outlets/delete/', views.PowerOutletBulkDeleteView.as_view(), name='poweroutlet_bulk_delete'), + path('power-outlets/', include(get_model_urls('dcim', 'poweroutlet', detail=False))), path('power-outlets//', include(get_model_urls('dcim', 'poweroutlet'))), - path('devices/power-outlets/add/', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'), + path( + 'devices/power-outlets/add/', + views.DeviceBulkAddPowerOutletView.as_view(), + name='device_bulk_add_poweroutlet' + ), - # Interfaces - path('interfaces/', views.InterfaceListView.as_view(), name='interface_list'), - path('interfaces/add/', views.InterfaceCreateView.as_view(), name='interface_add'), - path('interfaces/import/', views.InterfaceBulkImportView.as_view(), name='interface_import'), - path('interfaces/edit/', views.InterfaceBulkEditView.as_view(), name='interface_bulk_edit'), - path('interfaces/rename/', views.InterfaceBulkRenameView.as_view(), name='interface_bulk_rename'), - path('interfaces/disconnect/', views.InterfaceBulkDisconnectView.as_view(), name='interface_bulk_disconnect'), - path('interfaces/delete/', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'), + path('interfaces/', include(get_model_urls('dcim', 'interface', detail=False))), path('interfaces//', include(get_model_urls('dcim', 'interface'))), path('devices/interfaces/add/', views.DeviceBulkAddInterfaceView.as_view(), name='device_bulk_add_interface'), - # Front ports - path('front-ports/', views.FrontPortListView.as_view(), name='frontport_list'), - path('front-ports/add/', views.FrontPortCreateView.as_view(), name='frontport_add'), - path('front-ports/import/', views.FrontPortBulkImportView.as_view(), name='frontport_import'), - path('front-ports/edit/', views.FrontPortBulkEditView.as_view(), name='frontport_bulk_edit'), - path('front-ports/rename/', views.FrontPortBulkRenameView.as_view(), name='frontport_bulk_rename'), - path('front-ports/disconnect/', views.FrontPortBulkDisconnectView.as_view(), name='frontport_bulk_disconnect'), - path('front-ports/delete/', views.FrontPortBulkDeleteView.as_view(), name='frontport_bulk_delete'), + path('front-ports/', include(get_model_urls('dcim', 'frontport', detail=False))), path('front-ports//', include(get_model_urls('dcim', 'frontport'))), - # path('devices/front-ports/add/', views.DeviceBulkAddFrontPortView.as_view(), name='device_bulk_add_frontport'), - # Rear ports - path('rear-ports/', views.RearPortListView.as_view(), name='rearport_list'), - path('rear-ports/add/', views.RearPortCreateView.as_view(), name='rearport_add'), - path('rear-ports/import/', views.RearPortBulkImportView.as_view(), name='rearport_import'), - path('rear-ports/edit/', views.RearPortBulkEditView.as_view(), name='rearport_bulk_edit'), - path('rear-ports/rename/', views.RearPortBulkRenameView.as_view(), name='rearport_bulk_rename'), - path('rear-ports/disconnect/', views.RearPortBulkDisconnectView.as_view(), name='rearport_bulk_disconnect'), - path('rear-ports/delete/', views.RearPortBulkDeleteView.as_view(), name='rearport_bulk_delete'), + path('rear-ports/', include(get_model_urls('dcim', 'rearport', detail=False))), path('rear-ports//', include(get_model_urls('dcim', 'rearport'))), path('devices/rear-ports/add/', views.DeviceBulkAddRearPortView.as_view(), name='device_bulk_add_rearport'), - # Module bays - path('module-bays/', views.ModuleBayListView.as_view(), name='modulebay_list'), - path('module-bays/add/', views.ModuleBayCreateView.as_view(), name='modulebay_add'), - path('module-bays/import/', views.ModuleBayBulkImportView.as_view(), name='modulebay_import'), - path('module-bays/edit/', views.ModuleBayBulkEditView.as_view(), name='modulebay_bulk_edit'), - path('module-bays/rename/', views.ModuleBayBulkRenameView.as_view(), name='modulebay_bulk_rename'), - path('module-bays/delete/', views.ModuleBayBulkDeleteView.as_view(), name='modulebay_bulk_delete'), + path('module-bays/', include(get_model_urls('dcim', 'modulebay', detail=False))), path('module-bays//', include(get_model_urls('dcim', 'modulebay'))), path('devices/module-bays/add/', views.DeviceBulkAddModuleBayView.as_view(), name='device_bulk_add_modulebay'), - # Device bays - path('device-bays/', views.DeviceBayListView.as_view(), name='devicebay_list'), - path('device-bays/add/', views.DeviceBayCreateView.as_view(), name='devicebay_add'), - path('device-bays/import/', views.DeviceBayBulkImportView.as_view(), name='devicebay_import'), - path('device-bays/edit/', views.DeviceBayBulkEditView.as_view(), name='devicebay_bulk_edit'), - path('device-bays/rename/', views.DeviceBayBulkRenameView.as_view(), name='devicebay_bulk_rename'), - path('device-bays/delete/', views.DeviceBayBulkDeleteView.as_view(), name='devicebay_bulk_delete'), + path('device-bays/', include(get_model_urls('dcim', 'devicebay', detail=False))), path('device-bays//', include(get_model_urls('dcim', 'devicebay'))), path('devices/device-bays/add/', views.DeviceBulkAddDeviceBayView.as_view(), name='device_bulk_add_devicebay'), - # Inventory items - path('inventory-items/', views.InventoryItemListView.as_view(), name='inventoryitem_list'), - path('inventory-items/add/', views.InventoryItemCreateView.as_view(), name='inventoryitem_add'), - path('inventory-items/import/', views.InventoryItemBulkImportView.as_view(), name='inventoryitem_import'), - path('inventory-items/edit/', views.InventoryItemBulkEditView.as_view(), name='inventoryitem_bulk_edit'), - path('inventory-items/rename/', views.InventoryItemBulkRenameView.as_view(), name='inventoryitem_bulk_rename'), - path('inventory-items/delete/', views.InventoryItemBulkDeleteView.as_view(), name='inventoryitem_bulk_delete'), + path('inventory-items/', include(get_model_urls('dcim', 'inventoryitem', detail=False))), path('inventory-items//', include(get_model_urls('dcim', 'inventoryitem'))), - path('devices/inventory-items/add/', views.DeviceBulkAddInventoryItemView.as_view(), name='device_bulk_add_inventoryitem'), + path( + 'devices/inventory-items/add/', + views.DeviceBulkAddInventoryItemView.as_view(), + name='device_bulk_add_inventoryitem' + ), - # Inventory item roles - path('inventory-item-roles/', views.InventoryItemRoleListView.as_view(), name='inventoryitemrole_list'), - path('inventory-item-roles/add/', views.InventoryItemRoleEditView.as_view(), name='inventoryitemrole_add'), - path('inventory-item-roles/import/', views.InventoryItemRoleBulkImportView.as_view(), name='inventoryitemrole_import'), - path('inventory-item-roles/edit/', views.InventoryItemRoleBulkEditView.as_view(), name='inventoryitemrole_bulk_edit'), - path('inventory-item-roles/delete/', views.InventoryItemRoleBulkDeleteView.as_view(), name='inventoryitemrole_bulk_delete'), + path('inventory-item-roles/', include(get_model_urls('dcim', 'inventoryitemrole', detail=False))), path('inventory-item-roles//', include(get_model_urls('dcim', 'inventoryitemrole'))), - # Cables - path('cables/', views.CableListView.as_view(), name='cable_list'), - path('cables/add/', views.CableEditView.as_view(), name='cable_add'), - path('cables/import/', views.CableBulkImportView.as_view(), name='cable_import'), - path('cables/edit/', views.CableBulkEditView.as_view(), name='cable_bulk_edit'), - path('cables/delete/', views.CableBulkDeleteView.as_view(), name='cable_bulk_delete'), + path('cables/', include(get_model_urls('dcim', 'cable', detail=False))), path('cables//', include(get_model_urls('dcim', 'cable'))), # Console/power/interface connections (read-only) @@ -334,30 +151,21 @@ urlpatterns = [ path('power-connections/', views.PowerConnectionsListView.as_view(), name='power_connections_list'), path('interface-connections/', views.InterfaceConnectionsListView.as_view(), name='interface_connections_list'), - # Virtual chassis - path('virtual-chassis/', views.VirtualChassisListView.as_view(), name='virtualchassis_list'), - path('virtual-chassis/add/', views.VirtualChassisCreateView.as_view(), name='virtualchassis_add'), - path('virtual-chassis/import/', views.VirtualChassisBulkImportView.as_view(), name='virtualchassis_import'), - path('virtual-chassis/edit/', views.VirtualChassisBulkEditView.as_view(), name='virtualchassis_bulk_edit'), - path('virtual-chassis/delete/', views.VirtualChassisBulkDeleteView.as_view(), name='virtualchassis_bulk_delete'), + path('virtual-chassis/', include(get_model_urls('dcim', 'virtualchassis', detail=False))), path('virtual-chassis//', include(get_model_urls('dcim', 'virtualchassis'))), - path('virtual-chassis-members//delete/', views.VirtualChassisRemoveMemberView.as_view(), name='virtualchassis_remove_member'), + path( + 'virtual-chassis-members//delete/', + views.VirtualChassisRemoveMemberView.as_view(), + name='virtualchassis_remove_member' + ), - # Power panels - path('power-panels/', views.PowerPanelListView.as_view(), name='powerpanel_list'), - path('power-panels/add/', views.PowerPanelEditView.as_view(), name='powerpanel_add'), - path('power-panels/import/', views.PowerPanelBulkImportView.as_view(), name='powerpanel_import'), - path('power-panels/edit/', views.PowerPanelBulkEditView.as_view(), name='powerpanel_bulk_edit'), - path('power-panels/delete/', views.PowerPanelBulkDeleteView.as_view(), name='powerpanel_bulk_delete'), + path('power-panels/', include(get_model_urls('dcim', 'powerpanel', detail=False))), path('power-panels//', include(get_model_urls('dcim', 'powerpanel'))), - # Power feeds - path('power-feeds/', views.PowerFeedListView.as_view(), name='powerfeed_list'), - path('power-feeds/add/', views.PowerFeedEditView.as_view(), name='powerfeed_add'), - path('power-feeds/import/', views.PowerFeedBulkImportView.as_view(), name='powerfeed_import'), - path('power-feeds/edit/', views.PowerFeedBulkEditView.as_view(), name='powerfeed_bulk_edit'), - path('power-feeds/disconnect/', views.PowerFeedBulkDisconnectView.as_view(), name='powerfeed_bulk_disconnect'), - path('power-feeds/delete/', views.PowerFeedBulkDeleteView.as_view(), name='powerfeed_bulk_delete'), + path('power-feeds/', include(get_model_urls('dcim', 'powerfeed', detail=False))), path('power-feeds//', include(get_model_urls('dcim', 'powerfeed'))), + path('mac-addresses/', include(get_model_urls('dcim', 'macaddress', detail=False))), + path('mac-addresses//', include(get_model_urls('dcim', 'macaddress'))), + ] diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 98665a7a0..9a96b0c7f 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1,5 +1,3 @@ -import traceback - from django.contrib import messages from django.contrib.contenttypes.models import ContentType from django.core.paginator import EmptyPage, PageNotAnInteger @@ -11,14 +9,14 @@ from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.html import escape from django.utils.safestring import mark_safe -from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy as _ from django.views.generic import View from jinja2.exceptions import TemplateError from circuits.models import Circuit, CircuitTermination from extras.views import ObjectConfigContextView from ipam.models import ASN, IPAddress, VLANGroup -from ipam.tables import InterfaceVLANTable +from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable from netbox.constants import DEFAULT_ACTION_PERMISSIONS from netbox.views import generic from tenancy.views import ObjectContactsView @@ -35,7 +33,7 @@ from virtualization.forms import VirtualMachineFilterForm from virtualization.models import VirtualMachine from virtualization.tables import VirtualMachineTable from . import filtersets, forms, tables -from .choices import DeviceFaceChoices +from .choices import DeviceFaceChoices, InterfaceModeChoices from .models import * CABLE_TERMINATION_TYPES = { @@ -215,6 +213,7 @@ class PathTraceView(generic.ObjectView): # Regions # +@register_model_view(Region, 'list', path='', detail=False) class RegionListView(generic.ObjectListView): queryset = Region.objects.add_related_count( Region.objects.all(), @@ -242,11 +241,18 @@ class RegionView(GetRelatedModelsMixin, generic.ObjectView): extra=( (Location.objects.restrict(request.user, 'view').filter(site__region__in=regions), 'region_id'), (Rack.objects.restrict(request.user, 'view').filter(site__region__in=regions), 'region_id'), + ( + Circuit.objects.restrict(request.user, 'view').filter( + terminations___region=instance + ).distinct(), + 'region_id' + ), ), ), } +@register_model_view(Region, 'add', detail=False) @register_model_view(Region, 'edit') class RegionEditView(generic.ObjectEditView): queryset = Region.objects.all() @@ -258,11 +264,13 @@ class RegionDeleteView(generic.ObjectDeleteView): queryset = Region.objects.all() +@register_model_view(Region, 'bulk_import', detail=False) class RegionBulkImportView(generic.BulkImportView): queryset = Region.objects.all() model_form = forms.RegionImportForm +@register_model_view(Region, 'bulk_edit', path='edit', detail=False) class RegionBulkEditView(generic.BulkEditView): queryset = Region.objects.add_related_count( Region.objects.all(), @@ -276,6 +284,7 @@ class RegionBulkEditView(generic.BulkEditView): form = forms.RegionBulkEditForm +@register_model_view(Region, 'bulk_delete', path='delete', detail=False) class RegionBulkDeleteView(generic.BulkDeleteView): queryset = Region.objects.add_related_count( Region.objects.all(), @@ -297,6 +306,7 @@ class RegionContactsView(ObjectContactsView): # Site groups # +@register_model_view(SiteGroup, 'list', path='', detail=False) class SiteGroupListView(generic.ObjectListView): queryset = SiteGroup.objects.add_related_count( SiteGroup.objects.all(), @@ -324,11 +334,18 @@ class SiteGroupView(GetRelatedModelsMixin, generic.ObjectView): extra=( (Location.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'), (Rack.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'), + ( + Circuit.objects.restrict(request.user, 'view').filter( + terminations___site_group=instance + ).distinct(), + 'site_group_id' + ), ), ), } +@register_model_view(SiteGroup, 'add', detail=False) @register_model_view(SiteGroup, 'edit') class SiteGroupEditView(generic.ObjectEditView): queryset = SiteGroup.objects.all() @@ -340,11 +357,13 @@ class SiteGroupDeleteView(generic.ObjectDeleteView): queryset = SiteGroup.objects.all() +@register_model_view(SiteGroup, 'bulk_import', detail=False) class SiteGroupBulkImportView(generic.BulkImportView): queryset = SiteGroup.objects.all() model_form = forms.SiteGroupImportForm +@register_model_view(SiteGroup, 'bulk_edit', path='edit', detail=False) class SiteGroupBulkEditView(generic.BulkEditView): queryset = SiteGroup.objects.add_related_count( SiteGroup.objects.all(), @@ -358,6 +377,7 @@ class SiteGroupBulkEditView(generic.BulkEditView): form = forms.SiteGroupBulkEditForm +@register_model_view(SiteGroup, 'bulk_delete', path='delete', detail=False) class SiteGroupBulkDeleteView(generic.BulkDeleteView): queryset = SiteGroup.objects.add_related_count( SiteGroup.objects.all(), @@ -379,6 +399,7 @@ class SiteGroupContactsView(ObjectContactsView): # Sites # +@register_model_view(Site, 'list', path='', detail=False) class SiteListView(generic.ObjectListView): queryset = Site.objects.annotate( device_count=count_related(Device, 'site') @@ -404,13 +425,16 @@ class SiteView(GetRelatedModelsMixin, generic.ObjectView): scope_id=instance.pk ), 'site'), (ASN.objects.restrict(request.user, 'view').filter(sites=instance), 'site_id'), - (Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).distinct(), - 'site_id'), + ( + Circuit.objects.restrict(request.user, 'view').filter(terminations___site=instance).distinct(), + 'site_id' + ), ), ), } +@register_model_view(Site, 'add', detail=False) @register_model_view(Site, 'edit') class SiteEditView(generic.ObjectEditView): queryset = Site.objects.all() @@ -422,11 +446,13 @@ class SiteDeleteView(generic.ObjectDeleteView): queryset = Site.objects.all() +@register_model_view(Site, 'bulk_import', detail=False) class SiteBulkImportView(generic.BulkImportView): queryset = Site.objects.all() model_form = forms.SiteImportForm +@register_model_view(Site, 'bulk_edit', path='edit', detail=False) class SiteBulkEditView(generic.BulkEditView): queryset = Site.objects.all() filterset = filtersets.SiteFilterSet @@ -434,6 +460,7 @@ class SiteBulkEditView(generic.BulkEditView): form = forms.SiteBulkEditForm +@register_model_view(Site, 'bulk_delete', path='delete', detail=False) class SiteBulkDeleteView(generic.BulkDeleteView): queryset = Site.objects.all() filterset = filtersets.SiteFilterSet @@ -449,6 +476,7 @@ class SiteContactsView(ObjectContactsView): # Locations # +@register_model_view(Location, 'list', path='', detail=False) class LocationListView(generic.ObjectListView): queryset = Location.objects.add_related_count( Location.objects.add_related_count( @@ -475,10 +503,23 @@ class LocationView(GetRelatedModelsMixin, generic.ObjectView): def get_extra_context(self, request, instance): locations = instance.get_descendants(include_self=True) return { - 'related_models': self.get_related_models(request, locations, [CableTermination]), + 'related_models': self.get_related_models( + request, + locations, + [CableTermination], + ( + ( + Circuit.objects.restrict(request.user, 'view').filter( + terminations___location=instance + ).distinct(), + 'location_id' + ), + ), + ), } +@register_model_view(Location, 'add', detail=False) @register_model_view(Location, 'edit') class LocationEditView(generic.ObjectEditView): queryset = Location.objects.all() @@ -490,11 +531,13 @@ class LocationDeleteView(generic.ObjectDeleteView): queryset = Location.objects.all() +@register_model_view(Location, 'bulk_import', detail=False) class LocationBulkImportView(generic.BulkImportView): queryset = Location.objects.all() model_form = forms.LocationImportForm +@register_model_view(Location, 'bulk_edit', path='edit', detail=False) class LocationBulkEditView(generic.BulkEditView): queryset = Location.objects.add_related_count( Location.objects.all(), @@ -508,6 +551,7 @@ class LocationBulkEditView(generic.BulkEditView): form = forms.LocationBulkEditForm +@register_model_view(Location, 'bulk_delete', path='delete', detail=False) class LocationBulkDeleteView(generic.BulkDeleteView): queryset = Location.objects.add_related_count( Location.objects.all(), @@ -529,6 +573,7 @@ class LocationContactsView(ObjectContactsView): # Rack roles # +@register_model_view(RackRole, 'list', path='', detail=False) class RackRoleListView(generic.ObjectListView): queryset = RackRole.objects.annotate( rack_count=count_related(Rack, 'role') @@ -548,6 +593,7 @@ class RackRoleView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(RackRole, 'add', detail=False) @register_model_view(RackRole, 'edit') class RackRoleEditView(generic.ObjectEditView): queryset = RackRole.objects.all() @@ -559,11 +605,13 @@ class RackRoleDeleteView(generic.ObjectDeleteView): queryset = RackRole.objects.all() +@register_model_view(RackRole, 'bulk_import', detail=False) class RackRoleBulkImportView(generic.BulkImportView): queryset = RackRole.objects.all() model_form = forms.RackRoleImportForm +@register_model_view(RackRole, 'bulk_edit', path='edit', detail=False) class RackRoleBulkEditView(generic.BulkEditView): queryset = RackRole.objects.annotate( rack_count=count_related(Rack, 'role') @@ -573,6 +621,7 @@ class RackRoleBulkEditView(generic.BulkEditView): form = forms.RackRoleBulkEditForm +@register_model_view(RackRole, 'bulk_delete', path='delete', detail=False) class RackRoleBulkDeleteView(generic.BulkDeleteView): queryset = RackRole.objects.annotate( rack_count=count_related(Rack, 'role') @@ -585,6 +634,7 @@ class RackRoleBulkDeleteView(generic.BulkDeleteView): # RackTypes # +@register_model_view(RackType, 'list', path='', detail=False) class RackTypeListView(generic.ObjectListView): queryset = RackType.objects.annotate( instance_count=count_related(Rack, 'rack_type') @@ -604,6 +654,7 @@ class RackTypeView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(RackType, 'add', detail=False) @register_model_view(RackType, 'edit') class RackTypeEditView(generic.ObjectEditView): queryset = RackType.objects.all() @@ -615,11 +666,13 @@ class RackTypeDeleteView(generic.ObjectDeleteView): queryset = RackType.objects.all() +@register_model_view(RackType, 'bulk_import', detail=False) class RackTypeBulkImportView(generic.BulkImportView): queryset = RackType.objects.all() model_form = forms.RackTypeImportForm +@register_model_view(RackType, 'bulk_edit', path='edit', detail=False) class RackTypeBulkEditView(generic.BulkEditView): queryset = RackType.objects.all() filterset = filtersets.RackTypeFilterSet @@ -627,6 +680,7 @@ class RackTypeBulkEditView(generic.BulkEditView): form = forms.RackTypeBulkEditForm +@register_model_view(RackType, 'bulk_delete', path='delete', detail=False) class RackTypeBulkDeleteView(generic.BulkDeleteView): queryset = RackType.objects.all() filterset = filtersets.RackTypeFilterSet @@ -637,6 +691,7 @@ class RackTypeBulkDeleteView(generic.BulkDeleteView): # Racks # +@register_model_view(Rack, 'list', path='', detail=False) class RackListView(generic.ObjectListView): queryset = Rack.objects.annotate( device_count=count_related(Device, 'rack') @@ -668,8 +723,7 @@ class RackElevationListView(generic.ObjectListView): sort = request.GET.get('sort', 'name') if sort not in ORDERING_CHOICES: sort = 'name' - sort_field = sort.replace("name", "_name") # Use natural ordering - racks = racks.order_by(sort_field) + racks = racks.order_by(sort) # Pagination per_page = get_paginate_count(request) @@ -711,8 +765,8 @@ class RackView(GetRelatedModelsMixin, generic.ObjectView): peer_racks = peer_racks.filter(location=instance.location) else: peer_racks = peer_racks.filter(location__isnull=True) - next_rack = peer_racks.filter(_name__gt=instance._name).first() - prev_rack = peer_racks.filter(_name__lt=instance._name).reverse().first() + next_rack = peer_racks.filter(name__gt=instance.name).first() + prev_rack = peer_racks.filter(name__lt=instance.name).reverse().first() # Determine any additional parameters to pass when embedding the rack elevations svg_extra = '&'.join([ @@ -768,6 +822,7 @@ class RackNonRackedView(generic.ObjectChildrenView): ) +@register_model_view(Rack, 'add', detail=False) @register_model_view(Rack, 'edit') class RackEditView(generic.ObjectEditView): queryset = Rack.objects.all() @@ -779,11 +834,13 @@ class RackDeleteView(generic.ObjectDeleteView): queryset = Rack.objects.all() +@register_model_view(Rack, 'bulk_import', detail=False) class RackBulkImportView(generic.BulkImportView): queryset = Rack.objects.all() model_form = forms.RackImportForm +@register_model_view(Rack, 'bulk_edit', path='edit', detail=False) class RackBulkEditView(generic.BulkEditView): queryset = Rack.objects.all() filterset = filtersets.RackFilterSet @@ -791,6 +848,7 @@ class RackBulkEditView(generic.BulkEditView): form = forms.RackBulkEditForm +@register_model_view(Rack, 'bulk_delete', path='delete', detail=False) class RackBulkDeleteView(generic.BulkDeleteView): queryset = Rack.objects.all() filterset = filtersets.RackFilterSet @@ -806,6 +864,7 @@ class RackContactsView(ObjectContactsView): # Rack reservations # +@register_model_view(RackReservation, 'list', path='', detail=False) class RackReservationListView(generic.ObjectListView): queryset = RackReservation.objects.all() filterset = filtersets.RackReservationFilterSet @@ -818,6 +877,7 @@ class RackReservationView(generic.ObjectView): queryset = RackReservation.objects.all() +@register_model_view(RackReservation, 'add', detail=False) @register_model_view(RackReservation, 'edit') class RackReservationEditView(generic.ObjectEditView): queryset = RackReservation.objects.all() @@ -836,6 +896,7 @@ class RackReservationDeleteView(generic.ObjectDeleteView): queryset = RackReservation.objects.all() +@register_model_view(RackReservation, 'bulk_import', detail=False) class RackReservationImportView(generic.BulkImportView): queryset = RackReservation.objects.all() model_form = forms.RackReservationImportForm @@ -851,6 +912,7 @@ class RackReservationImportView(generic.BulkImportView): return instance +@register_model_view(RackReservation, 'bulk_edit', path='edit', detail=False) class RackReservationBulkEditView(generic.BulkEditView): queryset = RackReservation.objects.all() filterset = filtersets.RackReservationFilterSet @@ -858,6 +920,7 @@ class RackReservationBulkEditView(generic.BulkEditView): form = forms.RackReservationBulkEditForm +@register_model_view(RackReservation, 'bulk_delete', path='delete', detail=False) class RackReservationBulkDeleteView(generic.BulkDeleteView): queryset = RackReservation.objects.all() filterset = filtersets.RackReservationFilterSet @@ -868,6 +931,7 @@ class RackReservationBulkDeleteView(generic.BulkDeleteView): # Manufacturers # +@register_model_view(Manufacturer, 'list', path='', detail=False) class ManufacturerListView(generic.ObjectListView): queryset = Manufacturer.objects.annotate( devicetype_count=count_related(DeviceType, 'manufacturer'), @@ -890,6 +954,7 @@ class ManufacturerView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(Manufacturer, 'add', detail=False) @register_model_view(Manufacturer, 'edit') class ManufacturerEditView(generic.ObjectEditView): queryset = Manufacturer.objects.all() @@ -901,11 +966,13 @@ class ManufacturerDeleteView(generic.ObjectDeleteView): queryset = Manufacturer.objects.all() +@register_model_view(Manufacturer, 'bulk_import', detail=False) class ManufacturerBulkImportView(generic.BulkImportView): queryset = Manufacturer.objects.all() model_form = forms.ManufacturerImportForm +@register_model_view(Manufacturer, 'bulk_edit', path='edit', detail=False) class ManufacturerBulkEditView(generic.BulkEditView): queryset = Manufacturer.objects.annotate( devicetype_count=count_related(DeviceType, 'manufacturer'), @@ -918,6 +985,7 @@ class ManufacturerBulkEditView(generic.BulkEditView): form = forms.ManufacturerBulkEditForm +@register_model_view(Manufacturer, 'bulk_delete', path='delete', detail=False) class ManufacturerBulkDeleteView(generic.BulkDeleteView): queryset = Manufacturer.objects.annotate( devicetype_count=count_related(DeviceType, 'manufacturer'), @@ -938,6 +1006,7 @@ class ManufacturerContactsView(ObjectContactsView): # Device types # +@register_model_view(DeviceType, 'list', path='', detail=False) class DeviceTypeListView(generic.ObjectListView): queryset = DeviceType.objects.annotate( instance_count=count_related(Device, 'device_type') @@ -961,6 +1030,7 @@ class DeviceTypeView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(DeviceType, 'add', detail=False) @register_model_view(DeviceType, 'edit') class DeviceTypeEditView(generic.ObjectEditView): queryset = DeviceType.objects.all() @@ -1122,6 +1192,7 @@ class DeviceTypeInventoryItemsView(DeviceTypeComponentsView): ) +@register_model_view(DeviceType, 'bulk_import', detail=False) class DeviceTypeImportView(generic.BulkImportView): additional_permissions = [ 'dcim.add_devicetype', @@ -1156,6 +1227,7 @@ class DeviceTypeImportView(generic.BulkImportView): return data +@register_model_view(DeviceType, 'bulk_edit', path='edit', detail=False) class DeviceTypeBulkEditView(generic.BulkEditView): queryset = DeviceType.objects.annotate( instance_count=count_related(Device, 'device_type') @@ -1165,6 +1237,7 @@ class DeviceTypeBulkEditView(generic.BulkEditView): form = forms.DeviceTypeBulkEditForm +@register_model_view(DeviceType, 'bulk_delete', path='delete', detail=False) class DeviceTypeBulkDeleteView(generic.BulkDeleteView): queryset = DeviceType.objects.annotate( instance_count=count_related(Device, 'device_type') @@ -1177,6 +1250,7 @@ class DeviceTypeBulkDeleteView(generic.BulkDeleteView): # Module types # +@register_model_view(ModuleType, 'list', path='', detail=False) class ModuleTypeListView(generic.ObjectListView): queryset = ModuleType.objects.annotate( instance_count=count_related(Module, 'module_type') @@ -1200,6 +1274,7 @@ class ModuleTypeView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(ModuleType, 'add', detail=False) @register_model_view(ModuleType, 'edit') class ModuleTypeEditView(generic.ObjectEditView): queryset = ModuleType.objects.all() @@ -1331,6 +1406,7 @@ class ModuleTypeModuleBaysView(ModuleTypeComponentsView): ) +@register_model_view(ModuleType, 'bulk_import', detail=False) class ModuleTypeImportView(generic.BulkImportView): additional_permissions = [ 'dcim.add_moduletype', @@ -1359,6 +1435,7 @@ class ModuleTypeImportView(generic.BulkImportView): return data +@register_model_view(ModuleType, 'bulk_edit', path='edit', detail=False) class ModuleTypeBulkEditView(generic.BulkEditView): queryset = ModuleType.objects.annotate( instance_count=count_related(Module, 'module_type') @@ -1368,6 +1445,7 @@ class ModuleTypeBulkEditView(generic.BulkEditView): form = forms.ModuleTypeBulkEditForm +@register_model_view(ModuleType, 'bulk_delete', path='delete', detail=False) class ModuleTypeBulkDeleteView(generic.BulkDeleteView): queryset = ModuleType.objects.annotate( instance_count=count_related(Module, 'module_type') @@ -1380,6 +1458,7 @@ class ModuleTypeBulkDeleteView(generic.BulkDeleteView): # Console port templates # +@register_model_view(ConsolePortTemplate, 'add', detail=False) class ConsolePortTemplateCreateView(generic.ComponentCreateView): queryset = ConsolePortTemplate.objects.all() form = forms.ConsolePortTemplateCreateForm @@ -1397,16 +1476,19 @@ class ConsolePortTemplateDeleteView(generic.ObjectDeleteView): queryset = ConsolePortTemplate.objects.all() +@register_model_view(ConsolePortTemplate, 'bulk_edit', path='edit', detail=False) class ConsolePortTemplateBulkEditView(generic.BulkEditView): queryset = ConsolePortTemplate.objects.all() table = tables.ConsolePortTemplateTable form = forms.ConsolePortTemplateBulkEditForm +@register_model_view(ConsolePortTemplate, 'bulk_rename', path='rename', detail=False) class ConsolePortTemplateBulkRenameView(generic.BulkRenameView): queryset = ConsolePortTemplate.objects.all() +@register_model_view(ConsolePortTemplate, 'bulk_delete', path='delete', detail=False) class ConsolePortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ConsolePortTemplate.objects.all() table = tables.ConsolePortTemplateTable @@ -1416,6 +1498,7 @@ class ConsolePortTemplateBulkDeleteView(generic.BulkDeleteView): # Console server port templates # +@register_model_view(ConsoleServerPortTemplate, 'add', detail=False) class ConsoleServerPortTemplateCreateView(generic.ComponentCreateView): queryset = ConsoleServerPortTemplate.objects.all() form = forms.ConsoleServerPortTemplateCreateForm @@ -1433,16 +1516,19 @@ class ConsoleServerPortTemplateDeleteView(generic.ObjectDeleteView): queryset = ConsoleServerPortTemplate.objects.all() +@register_model_view(ConsoleServerPortTemplate, 'bulk_edit', path='edit', detail=False) class ConsoleServerPortTemplateBulkEditView(generic.BulkEditView): queryset = ConsoleServerPortTemplate.objects.all() table = tables.ConsoleServerPortTemplateTable form = forms.ConsoleServerPortTemplateBulkEditForm +@register_model_view(ConsoleServerPortTemplate, 'bulk_rename', detail=False) class ConsoleServerPortTemplateBulkRenameView(generic.BulkRenameView): queryset = ConsoleServerPortTemplate.objects.all() +@register_model_view(ConsoleServerPortTemplate, 'bulk_delete', path='delete', detail=False) class ConsoleServerPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ConsoleServerPortTemplate.objects.all() table = tables.ConsoleServerPortTemplateTable @@ -1452,6 +1538,7 @@ class ConsoleServerPortTemplateBulkDeleteView(generic.BulkDeleteView): # Power port templates # +@register_model_view(PowerPortTemplate, 'add', detail=False) class PowerPortTemplateCreateView(generic.ComponentCreateView): queryset = PowerPortTemplate.objects.all() form = forms.PowerPortTemplateCreateForm @@ -1469,16 +1556,19 @@ class PowerPortTemplateDeleteView(generic.ObjectDeleteView): queryset = PowerPortTemplate.objects.all() +@register_model_view(PowerPortTemplate, 'bulk_edit', path='edit', detail=False) class PowerPortTemplateBulkEditView(generic.BulkEditView): queryset = PowerPortTemplate.objects.all() table = tables.PowerPortTemplateTable form = forms.PowerPortTemplateBulkEditForm +@register_model_view(PowerPortTemplate, 'bulk_rename', path='rename', detail=False) class PowerPortTemplateBulkRenameView(generic.BulkRenameView): queryset = PowerPortTemplate.objects.all() +@register_model_view(PowerPortTemplate, 'bulk_delete', path='delete', detail=False) class PowerPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = PowerPortTemplate.objects.all() table = tables.PowerPortTemplateTable @@ -1488,6 +1578,7 @@ class PowerPortTemplateBulkDeleteView(generic.BulkDeleteView): # Power outlet templates # +@register_model_view(PowerOutletTemplate, 'add', detail=False) class PowerOutletTemplateCreateView(generic.ComponentCreateView): queryset = PowerOutletTemplate.objects.all() form = forms.PowerOutletTemplateCreateForm @@ -1505,16 +1596,19 @@ class PowerOutletTemplateDeleteView(generic.ObjectDeleteView): queryset = PowerOutletTemplate.objects.all() +@register_model_view(PowerOutletTemplate, 'bulk_edit', path='edit', detail=False) class PowerOutletTemplateBulkEditView(generic.BulkEditView): queryset = PowerOutletTemplate.objects.all() table = tables.PowerOutletTemplateTable form = forms.PowerOutletTemplateBulkEditForm +@register_model_view(PowerOutletTemplate, 'bulk_rename', path='rename', detail=False) class PowerOutletTemplateBulkRenameView(generic.BulkRenameView): queryset = PowerOutletTemplate.objects.all() +@register_model_view(PowerOutletTemplate, 'bulk_delete', path='delete', detail=False) class PowerOutletTemplateBulkDeleteView(generic.BulkDeleteView): queryset = PowerOutletTemplate.objects.all() table = tables.PowerOutletTemplateTable @@ -1524,6 +1618,7 @@ class PowerOutletTemplateBulkDeleteView(generic.BulkDeleteView): # Interface templates # +@register_model_view(InterfaceTemplate, 'add', detail=False) class InterfaceTemplateCreateView(generic.ComponentCreateView): queryset = InterfaceTemplate.objects.all() form = forms.InterfaceTemplateCreateForm @@ -1541,16 +1636,19 @@ class InterfaceTemplateDeleteView(generic.ObjectDeleteView): queryset = InterfaceTemplate.objects.all() +@register_model_view(InterfaceTemplate, 'bulk_edit', path='edit', detail=False) class InterfaceTemplateBulkEditView(generic.BulkEditView): queryset = InterfaceTemplate.objects.all() table = tables.InterfaceTemplateTable form = forms.InterfaceTemplateBulkEditForm +@register_model_view(InterfaceTemplate, 'bulk_rename', path='rename', detail=False) class InterfaceTemplateBulkRenameView(generic.BulkRenameView): queryset = InterfaceTemplate.objects.all() +@register_model_view(InterfaceTemplate, 'bulk_delete', path='delete', detail=False) class InterfaceTemplateBulkDeleteView(generic.BulkDeleteView): queryset = InterfaceTemplate.objects.all() table = tables.InterfaceTemplateTable @@ -1560,6 +1658,7 @@ class InterfaceTemplateBulkDeleteView(generic.BulkDeleteView): # Front port templates # +@register_model_view(FrontPortTemplate, 'add', detail=False) class FrontPortTemplateCreateView(generic.ComponentCreateView): queryset = FrontPortTemplate.objects.all() form = forms.FrontPortTemplateCreateForm @@ -1577,16 +1676,19 @@ class FrontPortTemplateDeleteView(generic.ObjectDeleteView): queryset = FrontPortTemplate.objects.all() +@register_model_view(FrontPortTemplate, 'bulk_edit', path='edit', detail=False) class FrontPortTemplateBulkEditView(generic.BulkEditView): queryset = FrontPortTemplate.objects.all() table = tables.FrontPortTemplateTable form = forms.FrontPortTemplateBulkEditForm +@register_model_view(FrontPortTemplate, 'bulk_rename', path='rename', detail=False) class FrontPortTemplateBulkRenameView(generic.BulkRenameView): queryset = FrontPortTemplate.objects.all() +@register_model_view(FrontPortTemplate, 'bulk_delete', path='delete', detail=False) class FrontPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = FrontPortTemplate.objects.all() table = tables.FrontPortTemplateTable @@ -1596,6 +1698,7 @@ class FrontPortTemplateBulkDeleteView(generic.BulkDeleteView): # Rear port templates # +@register_model_view(RearPortTemplate, 'add', detail=False) class RearPortTemplateCreateView(generic.ComponentCreateView): queryset = RearPortTemplate.objects.all() form = forms.RearPortTemplateCreateForm @@ -1613,16 +1716,19 @@ class RearPortTemplateDeleteView(generic.ObjectDeleteView): queryset = RearPortTemplate.objects.all() +@register_model_view(RearPortTemplate, 'bulk_edit', path='edit', detail=False) class RearPortTemplateBulkEditView(generic.BulkEditView): queryset = RearPortTemplate.objects.all() table = tables.RearPortTemplateTable form = forms.RearPortTemplateBulkEditForm +@register_model_view(RearPortTemplate, 'bulk_rename', path='rename', detail=False) class RearPortTemplateBulkRenameView(generic.BulkRenameView): queryset = RearPortTemplate.objects.all() +@register_model_view(RearPortTemplate, 'bulk_delete', path='delete', detail=False) class RearPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = RearPortTemplate.objects.all() table = tables.RearPortTemplateTable @@ -1632,6 +1738,7 @@ class RearPortTemplateBulkDeleteView(generic.BulkDeleteView): # Module bay templates # +@register_model_view(ModuleBayTemplate, 'add', detail=False) class ModuleBayTemplateCreateView(generic.ComponentCreateView): queryset = ModuleBayTemplate.objects.all() form = forms.ModuleBayTemplateCreateForm @@ -1649,16 +1756,19 @@ class ModuleBayTemplateDeleteView(generic.ObjectDeleteView): queryset = ModuleBayTemplate.objects.all() +@register_model_view(ModuleBayTemplate, 'bulk_edit', path='edit', detail=False) class ModuleBayTemplateBulkEditView(generic.BulkEditView): queryset = ModuleBayTemplate.objects.all() table = tables.ModuleBayTemplateTable form = forms.ModuleBayTemplateBulkEditForm +@register_model_view(ModuleBayTemplate, 'bulk_rename', path='rename', detail=False) class ModuleBayTemplateBulkRenameView(generic.BulkRenameView): queryset = ModuleBayTemplate.objects.all() +@register_model_view(ModuleBayTemplate, 'bulk_delete', path='delete', detail=False) class ModuleBayTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ModuleBayTemplate.objects.all() table = tables.ModuleBayTemplateTable @@ -1668,6 +1778,7 @@ class ModuleBayTemplateBulkDeleteView(generic.BulkDeleteView): # Device bay templates # +@register_model_view(DeviceBayTemplate, 'add', detail=False) class DeviceBayTemplateCreateView(generic.ComponentCreateView): queryset = DeviceBayTemplate.objects.all() form = forms.DeviceBayTemplateCreateForm @@ -1685,16 +1796,19 @@ class DeviceBayTemplateDeleteView(generic.ObjectDeleteView): queryset = DeviceBayTemplate.objects.all() +@register_model_view(DeviceBayTemplate, 'bulk_edit', path='edit', detail=False) class DeviceBayTemplateBulkEditView(generic.BulkEditView): queryset = DeviceBayTemplate.objects.all() table = tables.DeviceBayTemplateTable form = forms.DeviceBayTemplateBulkEditForm +@register_model_view(DeviceBayTemplate, 'bulk_rename', path='rename', detail=False) class DeviceBayTemplateBulkRenameView(generic.BulkRenameView): queryset = DeviceBayTemplate.objects.all() +@register_model_view(DeviceBayTemplate, 'bulk_delete', path='delete', detail=False) class DeviceBayTemplateBulkDeleteView(generic.BulkDeleteView): queryset = DeviceBayTemplate.objects.all() table = tables.DeviceBayTemplateTable @@ -1704,6 +1818,7 @@ class DeviceBayTemplateBulkDeleteView(generic.BulkDeleteView): # Inventory item templates # +@register_model_view(InventoryItemTemplate, 'add', detail=False) class InventoryItemTemplateCreateView(generic.ComponentCreateView): queryset = InventoryItemTemplate.objects.all() form = forms.InventoryItemTemplateCreateForm @@ -1732,16 +1847,19 @@ class InventoryItemTemplateDeleteView(generic.ObjectDeleteView): queryset = InventoryItemTemplate.objects.all() +@register_model_view(InventoryItemTemplate, 'bulk_edit', path='edit', detail=False) class InventoryItemTemplateBulkEditView(generic.BulkEditView): queryset = InventoryItemTemplate.objects.all() table = tables.InventoryItemTemplateTable form = forms.InventoryItemTemplateBulkEditForm +@register_model_view(InventoryItemTemplate, 'bulk_rename', path='rename', detail=False) class InventoryItemTemplateBulkRenameView(generic.BulkRenameView): queryset = InventoryItemTemplate.objects.all() +@register_model_view(InventoryItemTemplate, 'bulk_delete', path='delete', detail=False) class InventoryItemTemplateBulkDeleteView(generic.BulkDeleteView): queryset = InventoryItemTemplate.objects.all() table = tables.InventoryItemTemplateTable @@ -1751,6 +1869,7 @@ class InventoryItemTemplateBulkDeleteView(generic.BulkDeleteView): # Device roles # +@register_model_view(DeviceRole, 'list', path='', detail=False) class DeviceRoleListView(generic.ObjectListView): queryset = DeviceRole.objects.annotate( device_count=count_related(Device, 'role'), @@ -1771,6 +1890,7 @@ class DeviceRoleView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(DeviceRole, 'add', detail=False) @register_model_view(DeviceRole, 'edit') class DeviceRoleEditView(generic.ObjectEditView): queryset = DeviceRole.objects.all() @@ -1782,11 +1902,13 @@ class DeviceRoleDeleteView(generic.ObjectDeleteView): queryset = DeviceRole.objects.all() +@register_model_view(DeviceRole, 'bulk_import', detail=False) class DeviceRoleBulkImportView(generic.BulkImportView): queryset = DeviceRole.objects.all() model_form = forms.DeviceRoleImportForm +@register_model_view(DeviceRole, 'bulk_edit', path='edit', detail=False) class DeviceRoleBulkEditView(generic.BulkEditView): queryset = DeviceRole.objects.annotate( device_count=count_related(Device, 'role'), @@ -1797,6 +1919,7 @@ class DeviceRoleBulkEditView(generic.BulkEditView): form = forms.DeviceRoleBulkEditForm +@register_model_view(DeviceRole, 'bulk_delete', path='delete', detail=False) class DeviceRoleBulkDeleteView(generic.BulkDeleteView): queryset = DeviceRole.objects.annotate( device_count=count_related(Device, 'role'), @@ -1810,6 +1933,7 @@ class DeviceRoleBulkDeleteView(generic.BulkDeleteView): # Platforms # +@register_model_view(Platform, 'list', path='', detail=False) class PlatformListView(generic.ObjectListView): queryset = Platform.objects.annotate( device_count=count_related(Device, 'platform'), @@ -1830,6 +1954,7 @@ class PlatformView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(Platform, 'add', detail=False) @register_model_view(Platform, 'edit') class PlatformEditView(generic.ObjectEditView): queryset = Platform.objects.all() @@ -1841,11 +1966,13 @@ class PlatformDeleteView(generic.ObjectDeleteView): queryset = Platform.objects.all() +@register_model_view(Platform, 'bulk_import', detail=False) class PlatformBulkImportView(generic.BulkImportView): queryset = Platform.objects.all() model_form = forms.PlatformImportForm +@register_model_view(Platform, 'bulk_edit', path='edit', detail=False) class PlatformBulkEditView(generic.BulkEditView): queryset = Platform.objects.all() filterset = filtersets.PlatformFilterSet @@ -1853,6 +1980,7 @@ class PlatformBulkEditView(generic.BulkEditView): form = forms.PlatformBulkEditForm +@register_model_view(Platform, 'bulk_delete', path='delete', detail=False) class PlatformBulkDeleteView(generic.BulkDeleteView): queryset = Platform.objects.all() filterset = filtersets.PlatformFilterSet @@ -1863,6 +1991,7 @@ class PlatformBulkDeleteView(generic.BulkDeleteView): # Devices # +@register_model_view(Device, 'list', path='', detail=False) class DeviceListView(generic.ObjectListView): queryset = Device.objects.all() filterset = filtersets.DeviceFilterSet @@ -1890,6 +2019,7 @@ class DeviceView(generic.ObjectView): } +@register_model_view(Device, 'add', detail=False) @register_model_view(Device, 'edit') class DeviceEditView(generic.ObjectEditView): queryset = Device.objects.all() @@ -2106,7 +2236,8 @@ class DeviceRenderConfigView(generic.ObjectView): # If a direct export has been requested, return the rendered template content as a # downloadable file. if request.GET.get('export'): - response = HttpResponse(context['rendered_config'], content_type='text') + content = context['rendered_config'] or context['error_message'] + response = HttpResponse(content, content_type='text') filename = f"{instance.name or 'config'}.txt" response['Content-Disposition'] = f'attachment; filename="{filename}"' return response @@ -2124,17 +2255,18 @@ class DeviceRenderConfigView(generic.ObjectView): # Render the config template rendered_config = None + error_message = None if config_template := instance.get_config_template(): try: rendered_config = config_template.render(context=context_data) except TemplateError as e: - messages.error(request, _("An error occurred while rendering the template: {error}").format(error=e)) - rendered_config = traceback.format_exc() + error_message = _("An error occurred while rendering the template: {error}").format(error=e) return { 'config_template': config_template, 'context_data': context_data, 'rendered_config': rendered_config, + 'error_message': error_message, } @@ -2157,6 +2289,7 @@ class DeviceVirtualMachinesView(generic.ObjectChildrenView): return self.child_model.objects.restrict(request.user, 'view').filter(cluster=parent.cluster, device=parent) +@register_model_view(Device, 'bulk_import', detail=False) class DeviceBulkImportView(generic.BulkImportView): queryset = Device.objects.all() model_form = forms.DeviceImportForm @@ -2173,6 +2306,7 @@ class DeviceBulkImportView(generic.BulkImportView): return obj +@register_model_view(Device, 'bulk_edit', path='edit', detail=False) class DeviceBulkEditView(generic.BulkEditView): queryset = Device.objects.prefetch_related('device_type__manufacturer') filterset = filtersets.DeviceFilterSet @@ -2180,12 +2314,14 @@ class DeviceBulkEditView(generic.BulkEditView): form = forms.DeviceBulkEditForm +@register_model_view(Device, 'bulk_delete', path='delete', detail=False) class DeviceBulkDeleteView(generic.BulkDeleteView): queryset = Device.objects.prefetch_related('device_type__manufacturer') filterset = filtersets.DeviceFilterSet table = tables.DeviceTable +@register_model_view(Device, 'bulk_rename', path='rename', detail=False) class DeviceBulkRenameView(generic.BulkRenameView): queryset = Device.objects.all() filterset = filtersets.DeviceFilterSet @@ -2201,6 +2337,7 @@ class DeviceContactsView(ObjectContactsView): # Modules # +@register_model_view(Module, 'list', path='', detail=False) class ModuleListView(generic.ObjectListView): queryset = Module.objects.prefetch_related('module_type__manufacturer') filterset = filtersets.ModuleFilterSet @@ -2218,6 +2355,7 @@ class ModuleView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(Module, 'add', detail=False) @register_model_view(Module, 'edit') class ModuleEditView(generic.ObjectEditView): queryset = Module.objects.all() @@ -2229,11 +2367,13 @@ class ModuleDeleteView(generic.ObjectDeleteView): queryset = Module.objects.all() +@register_model_view(Module, 'bulk_import', detail=False) class ModuleBulkImportView(generic.BulkImportView): queryset = Module.objects.all() model_form = forms.ModuleImportForm +@register_model_view(Module, 'bulk_edit', path='edit', detail=False) class ModuleBulkEditView(generic.BulkEditView): queryset = Module.objects.prefetch_related('module_type__manufacturer') filterset = filtersets.ModuleFilterSet @@ -2241,6 +2381,7 @@ class ModuleBulkEditView(generic.BulkEditView): form = forms.ModuleBulkEditForm +@register_model_view(Module, 'bulk_delete', path='delete', detail=False) class ModuleBulkDeleteView(generic.BulkDeleteView): queryset = Module.objects.prefetch_related('module_type__manufacturer') filterset = filtersets.ModuleFilterSet @@ -2251,6 +2392,7 @@ class ModuleBulkDeleteView(generic.BulkDeleteView): # Console ports # +@register_model_view(ConsolePort, 'list', path='', detail=False) class ConsolePortListView(generic.ObjectListView): queryset = ConsolePort.objects.all() filterset = filtersets.ConsolePortFilterSet @@ -2268,6 +2410,7 @@ class ConsolePortView(generic.ObjectView): queryset = ConsolePort.objects.all() +@register_model_view(ConsolePort, 'add', detail=False) class ConsolePortCreateView(generic.ComponentCreateView): queryset = ConsolePort.objects.all() form = forms.ConsolePortCreateForm @@ -2285,11 +2428,13 @@ class ConsolePortDeleteView(generic.ObjectDeleteView): queryset = ConsolePort.objects.all() +@register_model_view(ConsolePort, 'bulk_import', detail=False) class ConsolePortBulkImportView(generic.BulkImportView): queryset = ConsolePort.objects.all() model_form = forms.ConsolePortImportForm +@register_model_view(ConsolePort, 'bulk_edit', path='edit', detail=False) class ConsolePortBulkEditView(generic.BulkEditView): queryset = ConsolePort.objects.all() filterset = filtersets.ConsolePortFilterSet @@ -2297,14 +2442,17 @@ class ConsolePortBulkEditView(generic.BulkEditView): form = forms.ConsolePortBulkEditForm +@register_model_view(ConsolePort, 'bulk_rename', path='rename', detail=False) class ConsolePortBulkRenameView(generic.BulkRenameView): queryset = ConsolePort.objects.all() +@register_model_view(ConsolePort, 'bulk_disconnect', path='disconnect', detail=False) class ConsolePortBulkDisconnectView(BulkDisconnectView): queryset = ConsolePort.objects.all() +@register_model_view(ConsolePort, 'bulk_delete', path='delete', detail=False) class ConsolePortBulkDeleteView(generic.BulkDeleteView): queryset = ConsolePort.objects.all() filterset = filtersets.ConsolePortFilterSet @@ -2319,6 +2467,7 @@ register_model_view(ConsolePort, 'trace', kwargs={'model': ConsolePort})(PathTra # Console server ports # +@register_model_view(ConsoleServerPort, 'list', path='', detail=False) class ConsoleServerPortListView(generic.ObjectListView): queryset = ConsoleServerPort.objects.all() filterset = filtersets.ConsoleServerPortFilterSet @@ -2336,6 +2485,7 @@ class ConsoleServerPortView(generic.ObjectView): queryset = ConsoleServerPort.objects.all() +@register_model_view(ConsoleServerPort, 'add', detail=False) class ConsoleServerPortCreateView(generic.ComponentCreateView): queryset = ConsoleServerPort.objects.all() form = forms.ConsoleServerPortCreateForm @@ -2353,11 +2503,13 @@ class ConsoleServerPortDeleteView(generic.ObjectDeleteView): queryset = ConsoleServerPort.objects.all() +@register_model_view(ConsoleServerPort, 'bulk_import', detail=False) class ConsoleServerPortBulkImportView(generic.BulkImportView): queryset = ConsoleServerPort.objects.all() model_form = forms.ConsoleServerPortImportForm +@register_model_view(ConsoleServerPort, 'bulk_edit', path='edit', detail=False) class ConsoleServerPortBulkEditView(generic.BulkEditView): queryset = ConsoleServerPort.objects.all() filterset = filtersets.ConsoleServerPortFilterSet @@ -2365,14 +2517,17 @@ class ConsoleServerPortBulkEditView(generic.BulkEditView): form = forms.ConsoleServerPortBulkEditForm +@register_model_view(ConsoleServerPort, 'bulk_rename', path='rename', detail=False) class ConsoleServerPortBulkRenameView(generic.BulkRenameView): queryset = ConsoleServerPort.objects.all() +@register_model_view(ConsoleServerPort, 'bulk_disconnect', path='disconnect', detail=False) class ConsoleServerPortBulkDisconnectView(BulkDisconnectView): queryset = ConsoleServerPort.objects.all() +@register_model_view(ConsoleServerPort, 'bulk_delete', path='delete', detail=False) class ConsoleServerPortBulkDeleteView(generic.BulkDeleteView): queryset = ConsoleServerPort.objects.all() filterset = filtersets.ConsoleServerPortFilterSet @@ -2387,6 +2542,7 @@ register_model_view(ConsoleServerPort, 'trace', kwargs={'model': ConsoleServerPo # Power ports # +@register_model_view(PowerPort, 'list', path='', detail=False) class PowerPortListView(generic.ObjectListView): queryset = PowerPort.objects.all() filterset = filtersets.PowerPortFilterSet @@ -2404,6 +2560,7 @@ class PowerPortView(generic.ObjectView): queryset = PowerPort.objects.all() +@register_model_view(PowerPort, 'add', detail=False) class PowerPortCreateView(generic.ComponentCreateView): queryset = PowerPort.objects.all() form = forms.PowerPortCreateForm @@ -2421,11 +2578,13 @@ class PowerPortDeleteView(generic.ObjectDeleteView): queryset = PowerPort.objects.all() +@register_model_view(PowerPort, 'bulk_import', detail=False) class PowerPortBulkImportView(generic.BulkImportView): queryset = PowerPort.objects.all() model_form = forms.PowerPortImportForm +@register_model_view(PowerPort, 'bulk_edit', path='edit', detail=False) class PowerPortBulkEditView(generic.BulkEditView): queryset = PowerPort.objects.all() filterset = filtersets.PowerPortFilterSet @@ -2433,14 +2592,17 @@ class PowerPortBulkEditView(generic.BulkEditView): form = forms.PowerPortBulkEditForm +@register_model_view(PowerPort, 'bulk_rename', path='rename', detail=False) class PowerPortBulkRenameView(generic.BulkRenameView): queryset = PowerPort.objects.all() +@register_model_view(PowerPort, 'bulk_disconnect', path='disconnect', detail=False) class PowerPortBulkDisconnectView(BulkDisconnectView): queryset = PowerPort.objects.all() +@register_model_view(PowerPort, 'bulk_delete', path='delete', detail=False) class PowerPortBulkDeleteView(generic.BulkDeleteView): queryset = PowerPort.objects.all() filterset = filtersets.PowerPortFilterSet @@ -2455,6 +2617,7 @@ register_model_view(PowerPort, 'trace', kwargs={'model': PowerPort})(PathTraceVi # Power outlets # +@register_model_view(PowerOutlet, 'list', path='', detail=False) class PowerOutletListView(generic.ObjectListView): queryset = PowerOutlet.objects.all() filterset = filtersets.PowerOutletFilterSet @@ -2472,6 +2635,7 @@ class PowerOutletView(generic.ObjectView): queryset = PowerOutlet.objects.all() +@register_model_view(PowerOutlet, 'add', detail=False) class PowerOutletCreateView(generic.ComponentCreateView): queryset = PowerOutlet.objects.all() form = forms.PowerOutletCreateForm @@ -2489,11 +2653,13 @@ class PowerOutletDeleteView(generic.ObjectDeleteView): queryset = PowerOutlet.objects.all() +@register_model_view(PowerOutlet, 'bulk_import', detail=False) class PowerOutletBulkImportView(generic.BulkImportView): queryset = PowerOutlet.objects.all() model_form = forms.PowerOutletImportForm +@register_model_view(PowerOutlet, 'bulk_edit', path='edit', detail=False) class PowerOutletBulkEditView(generic.BulkEditView): queryset = PowerOutlet.objects.all() filterset = filtersets.PowerOutletFilterSet @@ -2501,14 +2667,17 @@ class PowerOutletBulkEditView(generic.BulkEditView): form = forms.PowerOutletBulkEditForm +@register_model_view(PowerOutlet, 'bulk_rename', path='rename', detail=False) class PowerOutletBulkRenameView(generic.BulkRenameView): queryset = PowerOutlet.objects.all() +@register_model_view(PowerOutlet, 'bulk_disconnect', path='disconnect', detail=False) class PowerOutletBulkDisconnectView(BulkDisconnectView): queryset = PowerOutlet.objects.all() +@register_model_view(PowerOutlet, 'bulk_delete', path='delete', detail=False) class PowerOutletBulkDeleteView(generic.BulkDeleteView): queryset = PowerOutlet.objects.all() filterset = filtersets.PowerOutletFilterSet @@ -2523,6 +2692,7 @@ register_model_view(PowerOutlet, 'trace', kwargs={'model': PowerOutlet})(PathTra # Interfaces # +@register_model_view(Interface, 'list', path='', detail=False) class InterfaceListView(generic.ObjectListView): queryset = Interface.objects.all() filterset = filtersets.InterfaceFilterSet @@ -2552,7 +2722,7 @@ class InterfaceView(generic.ObjectView): # Get bridge interfaces bridge_interfaces = Interface.objects.restrict(request.user, 'view').filter(bridge=instance) - bridge_interfaces_tables = tables.InterfaceTable( + bridge_interfaces_table = tables.InterfaceTable( bridge_interfaces, exclude=('device', 'parent'), orderable=False @@ -2560,7 +2730,7 @@ class InterfaceView(generic.ObjectView): # Get child interfaces child_interfaces = Interface.objects.restrict(request.user, 'view').filter(parent=instance) - child_interfaces_tables = tables.InterfaceTable( + child_interfaces_table = tables.InterfaceTable( child_interfaces, exclude=('device', 'parent'), orderable=False @@ -2580,14 +2750,24 @@ class InterfaceView(generic.ObjectView): orderable=False ) + # Get VLAN translation rules + vlan_translation_table = None + if instance.vlan_translation_policy: + vlan_translation_table = VLANTranslationRuleTable( + data=instance.vlan_translation_policy.rules.all(), + orderable=False + ) + return { 'vdc_table': vdc_table, - 'bridge_interfaces_table': bridge_interfaces_tables, - 'child_interfaces_table': child_interfaces_tables, + 'bridge_interfaces_table': bridge_interfaces_table, + 'child_interfaces_table': child_interfaces_table, 'vlan_table': vlan_table, + 'vlan_translation_table': vlan_translation_table, } +@register_model_view(Interface, 'add', detail=False) class InterfaceCreateView(generic.ComponentCreateView): queryset = Interface.objects.all() form = forms.InterfaceCreateForm @@ -2605,26 +2785,41 @@ class InterfaceDeleteView(generic.ObjectDeleteView): queryset = Interface.objects.all() +@register_model_view(Interface, 'bulk_import', detail=False) class InterfaceBulkImportView(generic.BulkImportView): queryset = Interface.objects.all() model_form = forms.InterfaceImportForm +@register_model_view(Interface, 'bulk_edit', path='edit', detail=False) class InterfaceBulkEditView(generic.BulkEditView): queryset = Interface.objects.all() filterset = filtersets.InterfaceFilterSet table = tables.InterfaceTable form = forms.InterfaceBulkEditForm + def post_save_operations(self, form, obj): + super().post_save_operations(form, obj) + # Add/remove tagged VLANs + if obj.mode == InterfaceModeChoices.MODE_TAGGED: + if form.cleaned_data.get('add_tagged_vlans', None): + obj.tagged_vlans.add(*form.cleaned_data['add_tagged_vlans']) + if form.cleaned_data.get('remove_tagged_vlans', None): + obj.tagged_vlans.remove(*form.cleaned_data['remove_tagged_vlans']) + + +@register_model_view(Interface, 'bulk_rename', path='rename', detail=False) class InterfaceBulkRenameView(generic.BulkRenameView): queryset = Interface.objects.all() +@register_model_view(Interface, 'bulk_disconnect', path='disconnect', detail=False) class InterfaceBulkDisconnectView(BulkDisconnectView): queryset = Interface.objects.all() +@register_model_view(Interface, 'bulk_delete', path='delete', detail=False) class InterfaceBulkDeleteView(generic.BulkDeleteView): # Ensure child interfaces are deleted prior to their parents queryset = Interface.objects.order_by('device', 'parent', CollateAsChar('_name')) @@ -2640,6 +2835,7 @@ register_model_view(Interface, 'trace', kwargs={'model': Interface})(PathTraceVi # Front ports # +@register_model_view(FrontPort, 'list', path='', detail=False) class FrontPortListView(generic.ObjectListView): queryset = FrontPort.objects.all() filterset = filtersets.FrontPortFilterSet @@ -2657,6 +2853,7 @@ class FrontPortView(generic.ObjectView): queryset = FrontPort.objects.all() +@register_model_view(FrontPort, 'add', detail=False) class FrontPortCreateView(generic.ComponentCreateView): queryset = FrontPort.objects.all() form = forms.FrontPortCreateForm @@ -2674,11 +2871,13 @@ class FrontPortDeleteView(generic.ObjectDeleteView): queryset = FrontPort.objects.all() +@register_model_view(FrontPort, 'bulk_import', detail=False) class FrontPortBulkImportView(generic.BulkImportView): queryset = FrontPort.objects.all() model_form = forms.FrontPortImportForm +@register_model_view(FrontPort, 'bulk_edit', path='edit', detail=False) class FrontPortBulkEditView(generic.BulkEditView): queryset = FrontPort.objects.all() filterset = filtersets.FrontPortFilterSet @@ -2686,14 +2885,17 @@ class FrontPortBulkEditView(generic.BulkEditView): form = forms.FrontPortBulkEditForm +@register_model_view(FrontPort, 'bulk_rename', path='rename', detail=False) class FrontPortBulkRenameView(generic.BulkRenameView): queryset = FrontPort.objects.all() +@register_model_view(FrontPort, 'bulk_disconnect', path='disconnect', detail=False) class FrontPortBulkDisconnectView(BulkDisconnectView): queryset = FrontPort.objects.all() +@register_model_view(FrontPort, 'bulk_delete', path='delete', detail=False) class FrontPortBulkDeleteView(generic.BulkDeleteView): queryset = FrontPort.objects.all() filterset = filtersets.FrontPortFilterSet @@ -2708,6 +2910,7 @@ register_model_view(FrontPort, 'trace', kwargs={'model': FrontPort})(PathTraceVi # Rear ports # +@register_model_view(RearPort, 'list', path='', detail=False) class RearPortListView(generic.ObjectListView): queryset = RearPort.objects.all() filterset = filtersets.RearPortFilterSet @@ -2725,6 +2928,7 @@ class RearPortView(generic.ObjectView): queryset = RearPort.objects.all() +@register_model_view(RearPort, 'add', detail=False) class RearPortCreateView(generic.ComponentCreateView): queryset = RearPort.objects.all() form = forms.RearPortCreateForm @@ -2742,11 +2946,13 @@ class RearPortDeleteView(generic.ObjectDeleteView): queryset = RearPort.objects.all() +@register_model_view(RearPort, 'bulk_import', detail=False) class RearPortBulkImportView(generic.BulkImportView): queryset = RearPort.objects.all() model_form = forms.RearPortImportForm +@register_model_view(RearPort, 'bulk_edit', path='edit', detail=False) class RearPortBulkEditView(generic.BulkEditView): queryset = RearPort.objects.all() filterset = filtersets.RearPortFilterSet @@ -2754,14 +2960,17 @@ class RearPortBulkEditView(generic.BulkEditView): form = forms.RearPortBulkEditForm +@register_model_view(RearPort, 'bulk_rename', path='rename', detail=False) class RearPortBulkRenameView(generic.BulkRenameView): queryset = RearPort.objects.all() +@register_model_view(RearPort, 'bulk_disconnect', path='disconnect', detail=False) class RearPortBulkDisconnectView(BulkDisconnectView): queryset = RearPort.objects.all() +@register_model_view(RearPort, 'bulk_delete', path='delete', detail=False) class RearPortBulkDeleteView(generic.BulkDeleteView): queryset = RearPort.objects.all() filterset = filtersets.RearPortFilterSet @@ -2776,6 +2985,7 @@ register_model_view(RearPort, 'trace', kwargs={'model': RearPort})(PathTraceView # Module bays # +@register_model_view(ModuleBay, 'list', path='', detail=False) class ModuleBayListView(generic.ObjectListView): queryset = ModuleBay.objects.select_related('installed_module__module_type') filterset = filtersets.ModuleBayFilterSet @@ -2793,6 +3003,7 @@ class ModuleBayView(generic.ObjectView): queryset = ModuleBay.objects.all() +@register_model_view(ModuleBay, 'add', detail=False) class ModuleBayCreateView(generic.ComponentCreateView): queryset = ModuleBay.objects.all() form = forms.ModuleBayCreateForm @@ -2810,11 +3021,13 @@ class ModuleBayDeleteView(generic.ObjectDeleteView): queryset = ModuleBay.objects.all() +@register_model_view(ModuleBay, 'bulk_import', detail=False) class ModuleBayBulkImportView(generic.BulkImportView): queryset = ModuleBay.objects.all() model_form = forms.ModuleBayImportForm +@register_model_view(ModuleBay, 'bulk_edit', path='edit', detail=False) class ModuleBayBulkEditView(generic.BulkEditView): queryset = ModuleBay.objects.all() filterset = filtersets.ModuleBayFilterSet @@ -2822,10 +3035,12 @@ class ModuleBayBulkEditView(generic.BulkEditView): form = forms.ModuleBayBulkEditForm +@register_model_view(ModuleBay, 'bulk_rename', path='rename', detail=False) class ModuleBayBulkRenameView(generic.BulkRenameView): queryset = ModuleBay.objects.all() +@register_model_view(ModuleBay, 'bulk_delete', path='delete', detail=False) class ModuleBayBulkDeleteView(generic.BulkDeleteView): queryset = ModuleBay.objects.all() filterset = filtersets.ModuleBayFilterSet @@ -2836,6 +3051,7 @@ class ModuleBayBulkDeleteView(generic.BulkDeleteView): # Device bays # +@register_model_view(DeviceBay, 'list', path='', detail=False) class DeviceBayListView(generic.ObjectListView): queryset = DeviceBay.objects.all() filterset = filtersets.DeviceBayFilterSet @@ -2853,6 +3069,7 @@ class DeviceBayView(generic.ObjectView): queryset = DeviceBay.objects.all() +@register_model_view(DeviceBay, 'add', detail=False) class DeviceBayCreateView(generic.ComponentCreateView): queryset = DeviceBay.objects.all() form = forms.DeviceBayCreateForm @@ -2951,11 +3168,13 @@ class DeviceBayDepopulateView(generic.ObjectEditView): }) +@register_model_view(DeviceBay, 'bulk_import', detail=False) class DeviceBayBulkImportView(generic.BulkImportView): queryset = DeviceBay.objects.all() model_form = forms.DeviceBayImportForm +@register_model_view(DeviceBay, 'bulk_edit', path='edit', detail=False) class DeviceBayBulkEditView(generic.BulkEditView): queryset = DeviceBay.objects.all() filterset = filtersets.DeviceBayFilterSet @@ -2963,10 +3182,12 @@ class DeviceBayBulkEditView(generic.BulkEditView): form = forms.DeviceBayBulkEditForm +@register_model_view(DeviceBay, 'bulk_rename', path='rename', detail=False) class DeviceBayBulkRenameView(generic.BulkRenameView): queryset = DeviceBay.objects.all() +@register_model_view(DeviceBay, 'bulk_delete', path='delete', detail=False) class DeviceBayBulkDeleteView(generic.BulkDeleteView): queryset = DeviceBay.objects.all() filterset = filtersets.DeviceBayFilterSet @@ -2977,6 +3198,7 @@ class DeviceBayBulkDeleteView(generic.BulkDeleteView): # Inventory items # +@register_model_view(InventoryItem, 'list', path='', detail=False) class InventoryItemListView(generic.ObjectListView): queryset = InventoryItem.objects.all() filterset = filtersets.InventoryItemFilterSet @@ -3000,6 +3222,7 @@ class InventoryItemEditView(generic.ObjectEditView): form = forms.InventoryItemForm +@register_model_view(InventoryItem, 'add', detail=False) class InventoryItemCreateView(generic.ComponentCreateView): queryset = InventoryItem.objects.all() form = forms.InventoryItemCreateForm @@ -3011,11 +3234,13 @@ class InventoryItemDeleteView(generic.ObjectDeleteView): queryset = InventoryItem.objects.all() +@register_model_view(InventoryItem, 'bulk_import', detail=False) class InventoryItemBulkImportView(generic.BulkImportView): queryset = InventoryItem.objects.all() model_form = forms.InventoryItemImportForm +@register_model_view(InventoryItem, 'bulk_edit', path='edit', detail=False) class InventoryItemBulkEditView(generic.BulkEditView): queryset = InventoryItem.objects.all() filterset = filtersets.InventoryItemFilterSet @@ -3023,10 +3248,12 @@ class InventoryItemBulkEditView(generic.BulkEditView): form = forms.InventoryItemBulkEditForm +@register_model_view(InventoryItem, 'bulk_rename', path='rename', detail=False) class InventoryItemBulkRenameView(generic.BulkRenameView): queryset = InventoryItem.objects.all() +@register_model_view(InventoryItem, 'bulk_delete', path='delete', detail=False) class InventoryItemBulkDeleteView(generic.BulkDeleteView): queryset = InventoryItem.objects.all() filterset = filtersets.InventoryItemFilterSet @@ -3056,6 +3283,7 @@ class InventoryItemChildrenView(generic.ObjectChildrenView): # Inventory item roles # +@register_model_view(InventoryItemRole, 'list', path='', detail=False) class InventoryItemRoleListView(generic.ObjectListView): queryset = InventoryItemRole.objects.annotate( inventoryitem_count=count_related(InventoryItem, 'role'), @@ -3075,6 +3303,7 @@ class InventoryItemRoleView(generic.ObjectView): } +@register_model_view(InventoryItemRole, 'add', detail=False) @register_model_view(InventoryItemRole, 'edit') class InventoryItemRoleEditView(generic.ObjectEditView): queryset = InventoryItemRole.objects.all() @@ -3086,11 +3315,13 @@ class InventoryItemRoleDeleteView(generic.ObjectDeleteView): queryset = InventoryItemRole.objects.all() +@register_model_view(InventoryItemRole, 'bulk_import', detail=False) class InventoryItemRoleBulkImportView(generic.BulkImportView): queryset = InventoryItemRole.objects.all() model_form = forms.InventoryItemRoleImportForm +@register_model_view(InventoryItemRole, 'bulk_edit', path='edit', detail=False) class InventoryItemRoleBulkEditView(generic.BulkEditView): queryset = InventoryItemRole.objects.annotate( inventoryitem_count=count_related(InventoryItem, 'role'), @@ -3100,6 +3331,7 @@ class InventoryItemRoleBulkEditView(generic.BulkEditView): form = forms.InventoryItemRoleBulkEditForm +@register_model_view(InventoryItemRole, 'bulk_delete', path='delete', detail=False) class InventoryItemRoleBulkDeleteView(generic.BulkDeleteView): queryset = InventoryItemRole.objects.annotate( inventoryitem_count=count_related(InventoryItem, 'role'), @@ -3167,17 +3399,6 @@ class DeviceBulkAddInterfaceView(generic.BulkComponentCreateView): default_return_url = 'dcim:device_list' -# class DeviceBulkAddFrontPortView(generic.BulkComponentCreateView): -# parent_model = Device -# parent_field = 'device' -# form = forms.FrontPortBulkCreateForm -# queryset = FrontPort.objects.all() -# model_form = forms.FrontPortForm -# filterset = filtersets.DeviceFilterSet -# table = tables.DeviceTable -# default_return_url = 'dcim:device_list' - - class DeviceBulkAddRearPortView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' @@ -3226,6 +3447,7 @@ class DeviceBulkAddInventoryItemView(generic.BulkComponentCreateView): # Cables # +@register_model_view(Cable, 'list', path='', detail=False) class CableListView(generic.ObjectListView): queryset = Cable.objects.prefetch_related( 'terminations__termination', 'terminations___device', 'terminations___rack', 'terminations___location', @@ -3241,6 +3463,7 @@ class CableView(generic.ObjectView): queryset = Cable.objects.all() +@register_model_view(Cable, 'add', detail=False) @register_model_view(Cable, 'edit') class CableEditView(generic.ObjectEditView): queryset = Cable.objects.all() @@ -3288,11 +3511,13 @@ class CableDeleteView(generic.ObjectDeleteView): queryset = Cable.objects.all() +@register_model_view(Cable, 'bulk_import', detail=False) class CableBulkImportView(generic.BulkImportView): queryset = Cable.objects.all() model_form = forms.CableImportForm +@register_model_view(Cable, 'bulk_edit', path='edit', detail=False) class CableBulkEditView(generic.BulkEditView): queryset = Cable.objects.prefetch_related( 'terminations__termination', 'terminations___device', 'terminations___rack', 'terminations___location', @@ -3303,6 +3528,7 @@ class CableBulkEditView(generic.BulkEditView): form = forms.CableBulkEditForm +@register_model_view(Cable, 'bulk_delete', path='delete', detail=False) class CableBulkDeleteView(generic.BulkDeleteView): queryset = Cable.objects.prefetch_related( 'terminations__termination', 'terminations___device', 'terminations___rack', 'terminations___location', @@ -3368,6 +3594,7 @@ class InterfaceConnectionsListView(generic.ObjectListView): # Virtual chassis # +@register_model_view(VirtualChassis, 'list', path='', detail=False) class VirtualChassisListView(generic.ObjectListView): queryset = VirtualChassis.objects.all() table = tables.VirtualChassisTable @@ -3387,6 +3614,7 @@ class VirtualChassisView(generic.ObjectView): } +@register_model_view(VirtualChassis, 'add', detail=False) class VirtualChassisCreateView(generic.ObjectEditView): queryset = VirtualChassis.objects.all() form = forms.VirtualChassisCreateForm @@ -3507,7 +3735,9 @@ class VirtualChassisAddMemberView(ObjectPermissionRequiredMixin, GetReturnURLMix membership_form.save() messages.success(request, mark_safe( - _('Added member {device}').format(url=device.get_absolute_url(), device=escape(device)) + _('Added member {device}').format( + url=device.get_absolute_url(), device=escape(device) + ) )) if '_addanother' in request.POST: @@ -3582,11 +3812,13 @@ class VirtualChassisRemoveMemberView(ObjectPermissionRequiredMixin, GetReturnURL }) +@register_model_view(VirtualChassis, 'bulk_import', detail=False) class VirtualChassisBulkImportView(generic.BulkImportView): queryset = VirtualChassis.objects.all() model_form = forms.VirtualChassisImportForm +@register_model_view(VirtualChassis, 'bulk_edit', path='edit', detail=False) class VirtualChassisBulkEditView(generic.BulkEditView): queryset = VirtualChassis.objects.all() filterset = filtersets.VirtualChassisFilterSet @@ -3594,6 +3826,7 @@ class VirtualChassisBulkEditView(generic.BulkEditView): form = forms.VirtualChassisBulkEditForm +@register_model_view(VirtualChassis, 'bulk_delete', path='delete', detail=False) class VirtualChassisBulkDeleteView(generic.BulkDeleteView): queryset = VirtualChassis.objects.all() filterset = filtersets.VirtualChassisFilterSet @@ -3604,6 +3837,7 @@ class VirtualChassisBulkDeleteView(generic.BulkDeleteView): # Power panels # +@register_model_view(PowerPanel, 'list', path='', detail=False) class PowerPanelListView(generic.ObjectListView): queryset = PowerPanel.objects.annotate( powerfeed_count=count_related(PowerFeed, 'power_panel') @@ -3623,6 +3857,7 @@ class PowerPanelView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(PowerPanel, 'add', detail=False) @register_model_view(PowerPanel, 'edit') class PowerPanelEditView(generic.ObjectEditView): queryset = PowerPanel.objects.all() @@ -3634,11 +3869,13 @@ class PowerPanelDeleteView(generic.ObjectDeleteView): queryset = PowerPanel.objects.all() +@register_model_view(PowerPanel, 'bulk_import', detail=False) class PowerPanelBulkImportView(generic.BulkImportView): queryset = PowerPanel.objects.all() model_form = forms.PowerPanelImportForm +@register_model_view(PowerPanel, 'bulk_edit', path='edit', detail=False) class PowerPanelBulkEditView(generic.BulkEditView): queryset = PowerPanel.objects.all() filterset = filtersets.PowerPanelFilterSet @@ -3646,6 +3883,7 @@ class PowerPanelBulkEditView(generic.BulkEditView): form = forms.PowerPanelBulkEditForm +@register_model_view(PowerPanel, 'bulk_delete', path='delete', detail=False) class PowerPanelBulkDeleteView(generic.BulkDeleteView): queryset = PowerPanel.objects.annotate( powerfeed_count=count_related(PowerFeed, 'power_panel') @@ -3663,6 +3901,7 @@ class PowerPanelContactsView(ObjectContactsView): # Power feeds # +@register_model_view(PowerFeed, 'list', path='', detail=False) class PowerFeedListView(generic.ObjectListView): queryset = PowerFeed.objects.all() filterset = filtersets.PowerFeedFilterSet @@ -3675,6 +3914,7 @@ class PowerFeedView(generic.ObjectView): queryset = PowerFeed.objects.all() +@register_model_view(PowerFeed, 'add', detail=False) @register_model_view(PowerFeed, 'edit') class PowerFeedEditView(generic.ObjectEditView): queryset = PowerFeed.objects.all() @@ -3686,11 +3926,13 @@ class PowerFeedDeleteView(generic.ObjectDeleteView): queryset = PowerFeed.objects.all() +@register_model_view(PowerFeed, 'bulk_import', detail=False) class PowerFeedBulkImportView(generic.BulkImportView): queryset = PowerFeed.objects.all() model_form = forms.PowerFeedImportForm +@register_model_view(PowerFeed, 'bulk_edit', path='edit', detail=False) class PowerFeedBulkEditView(generic.BulkEditView): queryset = PowerFeed.objects.all() filterset = filtersets.PowerFeedFilterSet @@ -3698,10 +3940,12 @@ class PowerFeedBulkEditView(generic.BulkEditView): form = forms.PowerFeedBulkEditForm +@register_model_view(PowerFeed, 'bulk_disconnect', path='disconnect', detail=False) class PowerFeedBulkDisconnectView(BulkDisconnectView): queryset = PowerFeed.objects.all() +@register_model_view(PowerFeed, 'bulk_delete', path='delete', detail=False) class PowerFeedBulkDeleteView(generic.BulkDeleteView): queryset = PowerFeed.objects.all() filterset = filtersets.PowerFeedFilterSet @@ -3712,7 +3956,11 @@ class PowerFeedBulkDeleteView(generic.BulkDeleteView): register_model_view(PowerFeed, 'trace', kwargs={'model': PowerFeed})(PathTraceView) -# VDC +# +# Virtual device contexts +# + +@register_model_view(VirtualDeviceContext, 'list', path='', detail=False) class VirtualDeviceContextListView(generic.ObjectListView): queryset = VirtualDeviceContext.objects.annotate( interface_count=count_related(Interface, 'vdcs'), @@ -3738,6 +3986,7 @@ class VirtualDeviceContextView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(VirtualDeviceContext, 'add', detail=False) @register_model_view(VirtualDeviceContext, 'edit') class VirtualDeviceContextEditView(generic.ObjectEditView): queryset = VirtualDeviceContext.objects.all() @@ -3749,11 +3998,13 @@ class VirtualDeviceContextDeleteView(generic.ObjectDeleteView): queryset = VirtualDeviceContext.objects.all() +@register_model_view(VirtualDeviceContext, 'bulk_import', detail=False) class VirtualDeviceContextBulkImportView(generic.BulkImportView): queryset = VirtualDeviceContext.objects.all() model_form = forms.VirtualDeviceContextImportForm +@register_model_view(VirtualDeviceContext, 'bulk_edit', path='edit', detail=False) class VirtualDeviceContextBulkEditView(generic.BulkEditView): queryset = VirtualDeviceContext.objects.all() filterset = filtersets.VirtualDeviceContextFilterSet @@ -3761,7 +4012,58 @@ class VirtualDeviceContextBulkEditView(generic.BulkEditView): form = forms.VirtualDeviceContextBulkEditForm +@register_model_view(VirtualDeviceContext, 'bulk_delete', path='delete', detail=False) class VirtualDeviceContextBulkDeleteView(generic.BulkDeleteView): queryset = VirtualDeviceContext.objects.all() filterset = filtersets.VirtualDeviceContextFilterSet table = tables.VirtualDeviceContextTable + + +# +# MAC addresses +# + +@register_model_view(MACAddress, 'list', path='', detail=False) +class MACAddressListView(generic.ObjectListView): + queryset = MACAddress.objects.all() + filterset = filtersets.MACAddressFilterSet + filterset_form = forms.MACAddressFilterForm + table = tables.MACAddressTable + + +@register_model_view(MACAddress) +class MACAddressView(generic.ObjectView): + queryset = MACAddress.objects.all() + + +@register_model_view(MACAddress, 'add', detail=False) +@register_model_view(MACAddress, 'edit') +class MACAddressEditView(generic.ObjectEditView): + queryset = MACAddress.objects.all() + form = forms.MACAddressForm + + +@register_model_view(MACAddress, 'delete') +class MACAddressDeleteView(generic.ObjectDeleteView): + queryset = MACAddress.objects.all() + + +@register_model_view(MACAddress, 'bulk_import', detail=False) +class MACAddressBulkImportView(generic.BulkImportView): + queryset = MACAddress.objects.all() + model_form = forms.MACAddressImportForm + + +@register_model_view(MACAddress, 'bulk_edit', path='edit', detail=False) +class MACAddressBulkEditView(generic.BulkEditView): + queryset = MACAddress.objects.all() + filterset = filtersets.MACAddressFilterSet + table = tables.MACAddressTable + form = forms.MACAddressBulkEditForm + + +@register_model_view(MACAddress, 'bulk_delete', path='delete', detail=False) +class MACAddressBulkDeleteView(generic.BulkDeleteView): + queryset = MACAddress.objects.all() + filterset = filtersets.MACAddressFilterSet + table = tables.MACAddressTable diff --git a/netbox/extras/api/nested_serializers.py b/netbox/extras/api/nested_serializers.py deleted file mode 100644 index 235cdd6d6..000000000 --- a/netbox/extras/api/nested_serializers.py +++ /dev/null @@ -1,135 +0,0 @@ -import warnings - -from rest_framework import serializers - -from extras import models -from netbox.api.serializers import NestedTagSerializer, WritableNestedSerializer - -__all__ = [ - 'NestedBookmarkSerializer', - 'NestedConfigContextSerializer', - 'NestedConfigTemplateSerializer', - 'NestedCustomFieldChoiceSetSerializer', - 'NestedCustomFieldSerializer', - 'NestedCustomLinkSerializer', - 'NestedEventRuleSerializer', - 'NestedExportTemplateSerializer', - 'NestedImageAttachmentSerializer', - 'NestedJournalEntrySerializer', - 'NestedSavedFilterSerializer', - 'NestedScriptSerializer', - 'NestedTagSerializer', # Defined in netbox.api.serializers - 'NestedWebhookSerializer', -] - -# TODO: Remove in v4.2 -warnings.warn( - "Dedicated nested serializers will be removed in NetBox v4.2. Use Serializer(nested=True) instead.", - DeprecationWarning -) - - -class NestedEventRuleSerializer(WritableNestedSerializer): - - class Meta: - model = models.EventRule - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedWebhookSerializer(WritableNestedSerializer): - - class Meta: - model = models.Webhook - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedCustomFieldSerializer(WritableNestedSerializer): - - class Meta: - model = models.CustomField - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedCustomFieldChoiceSetSerializer(WritableNestedSerializer): - - class Meta: - model = models.CustomFieldChoiceSet - fields = ['id', 'url', 'display_url', 'display', 'name', 'choices_count'] - - -class NestedCustomLinkSerializer(WritableNestedSerializer): - - class Meta: - model = models.CustomLink - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedConfigContextSerializer(WritableNestedSerializer): - - class Meta: - model = models.ConfigContext - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedConfigTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.ConfigTemplate - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedExportTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.ExportTemplate - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedSavedFilterSerializer(WritableNestedSerializer): - - class Meta: - model = models.SavedFilter - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug'] - - -class NestedBookmarkSerializer(WritableNestedSerializer): - - class Meta: - model = models.Bookmark - fields = ['id', 'url', 'display', 'object_id', 'object_type'] - - -class NestedImageAttachmentSerializer(WritableNestedSerializer): - - class Meta: - model = models.ImageAttachment - fields = ['id', 'url', 'display', 'name', 'image'] - - -class NestedJournalEntrySerializer(WritableNestedSerializer): - - class Meta: - model = models.JournalEntry - fields = ['id', 'url', 'display_url', 'display', 'created'] - - -class NestedScriptSerializer(WritableNestedSerializer): - url = serializers.HyperlinkedIdentityField( - view_name='extras-api:script-detail', - lookup_field='full_name', - lookup_url_kwarg='pk' - ) - display_url = serializers.HyperlinkedIdentityField( - view_name='extras:script', - lookup_field='full_name', - lookup_url_kwarg='pk' - ) - name = serializers.CharField(read_only=True) - display = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = models.Script - fields = ['id', 'url', 'display_url', 'display', 'name'] - - def get_display(self, obj): - return f'{obj.name} ({obj.module})' diff --git a/netbox/extras/constants.py b/netbox/extras/constants.py index 3bfe3b21b..994586aca 100644 --- a/netbox/extras/constants.py +++ b/netbox/extras/constants.py @@ -79,6 +79,7 @@ DEFAULT_DASHBOARD = [ 'feed_url': 'http://netbox.dev/rss/', 'max_entries': 10, 'cache_timeout': 14400, + 'requires_internet': True, } }, { diff --git a/netbox/extras/dashboard/widgets.py b/netbox/extras/dashboard/widgets.py index c56e4cd7d..6bb7f59fb 100644 --- a/netbox/extras/dashboard/widgets.py +++ b/netbox/extras/dashboard/widgets.py @@ -275,6 +275,7 @@ class RSSFeedWidget(DashboardWidget): default_config = { 'max_entries': 10, 'cache_timeout': 3600, # seconds + 'requires_internet': True, } description = _('Embed an RSS feed from an external website.') template_name = 'extras/dashboard/widgets/rssfeed.html' @@ -285,6 +286,10 @@ class RSSFeedWidget(DashboardWidget): feed_url = forms.URLField( label=_('Feed URL') ) + requires_internet = forms.BooleanField( + label=_('Requires external connection'), + required=False, + ) max_entries = forms.IntegerField( min_value=1, max_value=1000, @@ -309,6 +314,11 @@ class RSSFeedWidget(DashboardWidget): return f'dashboard_rss_{url_checksum}' def get_feed(self): + if self.config['requires_internet'] and settings.ISOLATED_DEPLOYMENT: + return { + 'isolated_deployment': True, + } + # Fetch RSS content from cache if available if feed_content := cache.get(self.cache_key): return { diff --git a/netbox/extras/events.py b/netbox/extras/events.py index f13a3b48f..95170e18d 100644 --- a/netbox/extras/events.py +++ b/netbox/extras/events.py @@ -90,6 +90,10 @@ def process_event_rules(event_rules, object_type, event_type, data, username=Non if not event_rule.eval_conditions(data): continue + # Compile event data + event_data = event_rule.action_data or {} + event_data.update(data) + # Webhooks if event_rule.action_type == EventRuleActionChoices.WEBHOOK: @@ -102,7 +106,7 @@ def process_event_rules(event_rules, object_type, event_type, data, username=Non "event_rule": event_rule, "model_name": object_type.model, "event_type": event_type, - "data": data, + "data": event_data, "snapshots": snapshots, "timestamp": timezone.now().isoformat(), "username": username, @@ -130,7 +134,7 @@ def process_event_rules(event_rules, object_type, event_type, data, username=Non instance=event_rule.action_object, name=script.name, user=user, - data=data + data=event_data ) # Notification groups @@ -138,8 +142,8 @@ def process_event_rules(event_rules, object_type, event_type, data, username=Non # Bulk-create notifications for all members of the notification group event_rule.action_object.notify( object_type=object_type, - object_id=data['id'], - object_repr=data.get('display'), + object_id=event_data['id'], + object_repr=event_data.get('display'), event_type=event_type ) diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index 258df8264..655a5d6ca 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -223,7 +223,7 @@ class EventRuleImportForm(NetBoxModelImportForm): from extras.scripts import get_module_and_script module_name, script_name = action_object.split('.', 1) try: - module, script = get_module_and_script(module_name, script_name) + script = get_module_and_script(module_name, script_name)[1] except ObjectDoesNotExist: raise forms.ValidationError(_("Script {name} not found").format(name=action_object)) self.instance.action_object = script diff --git a/netbox/extras/jobs.py b/netbox/extras/jobs.py index 64a7d6a69..10d76e3aa 100644 --- a/netbox/extras/jobs.py +++ b/netbox/extras/jobs.py @@ -1,14 +1,14 @@ import logging import traceback -from contextlib import nullcontext +from contextlib import ExitStack from django.db import transaction from django.utils.translation import gettext as _ from core.signals import clear_events from extras.models import Script as ScriptModel -from netbox.context_managers import event_tracking from netbox.jobs import JobRunner +from netbox.registry import registry from utilities.exceptions import AbortScript, AbortTransaction from .utils import is_report @@ -22,9 +22,7 @@ class ScriptJob(JobRunner): """ class Meta: - # An explicit job name is not set because it doesn't make sense in this context. Currently, there's no scenario - # where jobs other than this one are used. Therefore, it is hidden, resulting in a cleaner job table overview. - name = '' + name = 'Run Script' def run_script(self, script, request, data, commit): """ @@ -49,7 +47,6 @@ class ScriptJob(JobRunner): script.log_info(message=_("Database changes have been reverted automatically.")) if script.failed: logger.warning("Script failed") - raise except Exception as e: if type(e) is AbortScript: @@ -103,5 +100,7 @@ class ScriptJob(JobRunner): # Execute the script. If commit is True, wrap it with the event_tracking context manager to ensure we process # change logging, event rules, etc. - with event_tracking(request) if commit else nullcontext(): + with ExitStack() as stack: + for request_processor in registry['request_processors']: + stack.enter_context(request_processor(request)) self.run_script(script, request, data, commit) diff --git a/netbox/extras/management/commands/reindex.py b/netbox/extras/management/commands/reindex.py index 21442be93..5495bbf5f 100644 --- a/netbox/extras/management/commands/reindex.py +++ b/netbox/extras/management/commands/reindex.py @@ -53,7 +53,8 @@ class Command(BaseCommand): else: raise CommandError( - f"Invalid model: {label}. Model names must be in the format or .." + f"Invalid model: {label}. Model names must be in the format or " + f".." ) return indexers diff --git a/netbox/extras/management/commands/runscript.py b/netbox/extras/management/commands/runscript.py index d5fb435ad..847d89396 100644 --- a/netbox/extras/management/commands/runscript.py +++ b/netbox/extras/management/commands/runscript.py @@ -38,7 +38,7 @@ class Command(BaseCommand): data = {} module_name, script_name = script.split('.', 1) - module, script_obj = get_module_and_script(module_name, script_name) + script_obj = get_module_and_script(module_name, script_name)[1] script = script_obj.python_class # Take user from command line if provided and exists, other diff --git a/netbox/extras/migrations/0001_squashed.py b/netbox/extras/migrations/0001_squashed.py index 6f1f77e53..a2514fa5e 100644 --- a/netbox/extras/migrations/0001_squashed.py +++ b/netbox/extras/migrations/0001_squashed.py @@ -9,7 +9,6 @@ import utilities.validators class Migration(migrations.Migration): - initial = True dependencies = [ @@ -99,8 +98,22 @@ class Migration(migrations.Migration): fields=[ ('object_id', models.IntegerField(db_index=True)), ('id', models.BigAutoField(primary_key=True, serialize=False)), - ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_tagged_items', to='contenttypes.contenttype')), - ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_items', to='extras.tag')), + ( + 'content_type', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name='%(app_label)s_%(class)s_tagged_items', + to='contenttypes.contenttype', + ), + ), + ( + 'tag', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name='%(app_label)s_%(class)s_items', + to='extras.tag', + ), + ), ], ), migrations.CreateModel( @@ -116,9 +129,32 @@ class Migration(migrations.Migration): ('object_repr', models.CharField(editable=False, max_length=200)), ('prechange_data', models.JSONField(blank=True, editable=False, null=True)), ('postchange_data', models.JSONField(blank=True, editable=False, null=True)), - ('changed_object_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')), - ('related_object_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='changes', to=settings.AUTH_USER_MODEL)), + ( + 'changed_object_type', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype' + ), + ), + ( + 'related_object_type', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), + ), + ( + 'user', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='changes', + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ 'ordering': ['-time'], @@ -133,8 +169,16 @@ class Migration(migrations.Migration): ('created', models.DateTimeField(auto_now_add=True)), ('kind', models.CharField(default='info', max_length=30)), ('comments', models.TextField()), - ('assigned_object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), - ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ( + 'assigned_object_type', + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype'), + ), + ( + 'created_by', + models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL + ), + ), ], options={ 'verbose_name_plural': 'journal entries', @@ -151,8 +195,24 @@ class Migration(migrations.Migration): ('status', models.CharField(default='pending', max_length=30)), ('data', models.JSONField(blank=True, null=True)), ('job_id', models.UUIDField(unique=True)), - ('obj_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='job_results', to='contenttypes.contenttype')), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ( + 'obj_type', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name='job_results', + to='contenttypes.contenttype', + ), + ), + ( + 'user', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ 'ordering': ['obj_type', 'name', '-created'], @@ -163,12 +223,20 @@ class Migration(migrations.Migration): fields=[ ('id', models.BigAutoField(primary_key=True, serialize=False)), ('object_id', models.PositiveIntegerField()), - ('image', models.ImageField(height_field='image_height', upload_to=extras.utils.image_upload, width_field='image_width')), + ( + 'image', + models.ImageField( + height_field='image_height', upload_to=extras.utils.image_upload, width_field='image_width' + ), + ), ('image_height', models.PositiveSmallIntegerField()), ('image_width', models.PositiveSmallIntegerField()), ('name', models.CharField(blank=True, max_length=50)), ('created', models.DateTimeField(auto_now_add=True)), - ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), + ( + 'content_type', + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype'), + ), ], options={ 'ordering': ('name', 'pk'), @@ -184,7 +252,10 @@ class Migration(migrations.Migration): ('mime_type', models.CharField(blank=True, max_length=50)), ('file_extension', models.CharField(blank=True, max_length=15)), ('as_attachment', models.BooleanField(default=True)), - ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), + ( + 'content_type', + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype'), + ), ], options={ 'ordering': ['content_type', 'name'], @@ -201,7 +272,10 @@ class Migration(migrations.Migration): ('group_name', models.CharField(blank=True, max_length=50)), ('button_class', models.CharField(default='default', max_length=30)), ('new_window', models.BooleanField(default=False)), - ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), + ( + 'content_type', + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype'), + ), ], options={ 'ordering': ['group_name', 'weight', 'name'], @@ -221,8 +295,16 @@ class Migration(migrations.Migration): ('weight', models.PositiveSmallIntegerField(default=100)), ('validation_minimum', models.PositiveIntegerField(blank=True, null=True)), ('validation_maximum', models.PositiveIntegerField(blank=True, null=True)), - ('validation_regex', models.CharField(blank=True, max_length=500, validators=[utilities.validators.validate_regex])), - ('choices', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=100), blank=True, null=True, size=None)), + ( + 'validation_regex', + models.CharField(blank=True, max_length=500, validators=[utilities.validators.validate_regex]), + ), + ( + 'choices', + django.contrib.postgres.fields.ArrayField( + base_field=models.CharField(max_length=100), blank=True, null=True, size=None + ), + ), ('content_types', models.ManyToManyField(related_name='custom_fields', to='contenttypes.ContentType')), ], options={ diff --git a/netbox/extras/migrations/0002_squashed_0059.py b/netbox/extras/migrations/0002_squashed_0059.py index a403a0e19..b664b286e 100644 --- a/netbox/extras/migrations/0002_squashed_0059.py +++ b/netbox/extras/migrations/0002_squashed_0059.py @@ -2,7 +2,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('dcim', '0002_auto_20160622_1821'), ('extras', '0001_initial'), diff --git a/netbox/extras/migrations/0060_squashed_0086.py b/netbox/extras/migrations/0060_squashed_0086.py index 0d5d03008..3bde7480f 100644 --- a/netbox/extras/migrations/0060_squashed_0086.py +++ b/netbox/extras/migrations/0060_squashed_0086.py @@ -12,7 +12,6 @@ import utilities.json class Migration(migrations.Migration): - replaces = [ ('extras', '0060_customlink_button_class'), ('extras', '0061_extras_change_logging'), @@ -40,7 +39,7 @@ class Migration(migrations.Migration): ('extras', '0083_search'), ('extras', '0084_staging'), ('extras', '0085_synced_data'), - ('extras', '0086_configtemplate') + ('extras', '0086_configtemplate'), ] dependencies = [ @@ -114,7 +113,23 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='customfield', name='name', - field=models.CharField(max_length=50, unique=True, validators=[django.core.validators.RegexValidator(flags=re.RegexFlag['IGNORECASE'], message='Only alphanumeric characters and underscores are allowed.', regex='^[a-z0-9_]+$'), django.core.validators.RegexValidator(flags=re.RegexFlag['IGNORECASE'], inverse_match=True, message='Double underscores are not permitted in custom field names.', regex='__')]), + field=models.CharField( + max_length=50, + unique=True, + validators=[ + django.core.validators.RegexValidator( + flags=re.RegexFlag['IGNORECASE'], + message='Only alphanumeric characters and underscores are allowed.', + regex='^[a-z0-9_]+$', + ), + django.core.validators.RegexValidator( + flags=re.RegexFlag['IGNORECASE'], + inverse_match=True, + message='Double underscores are not permitted in custom field names.', + regex='__', + ), + ], + ), ), migrations.AlterField( model_name='customfield', @@ -134,7 +149,9 @@ class Migration(migrations.Migration): migrations.AddField( model_name='customfield', name='object_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype' + ), ), migrations.AddField( model_name='customlink', @@ -314,11 +331,16 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='exporttemplate', - constraint=models.UniqueConstraint(fields=('content_type', 'name'), name='extras_exporttemplate_unique_content_type_name'), + constraint=models.UniqueConstraint( + fields=('content_type', 'name'), name='extras_exporttemplate_unique_content_type_name' + ), ), migrations.AddConstraint( model_name='webhook', - constraint=models.UniqueConstraint(fields=('payload_url', 'type_create', 'type_update', 'type_delete'), name='extras_webhook_unique_payload_url_types'), + constraint=models.UniqueConstraint( + fields=('payload_url', 'type_create', 'type_update', 'type_delete'), + name='extras_webhook_unique_payload_url_types', + ), ), migrations.AddField( model_name='jobresult', @@ -328,7 +350,9 @@ class Migration(migrations.Migration): migrations.AddField( model_name='jobresult', name='interval', - field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]), + field=models.PositiveIntegerField( + blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)] + ), ), migrations.AddField( model_name='jobresult', @@ -379,7 +403,12 @@ class Migration(migrations.Migration): ('shared', models.BooleanField(default=True)), ('parameters', models.JSONField()), ('content_types', models.ManyToManyField(related_name='saved_filters', to='contenttypes.contenttype')), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ( + 'user', + models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL + ), + ), ], options={ 'ordering': ('weight', 'name'), @@ -400,7 +429,12 @@ class Migration(migrations.Migration): ('type', models.CharField(max_length=30)), ('value', extras.fields.CachedValueField()), ('weight', models.PositiveSmallIntegerField(default=1000)), - ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')), + ( + 'object_type', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype' + ), + ), ], options={ 'ordering': ('weight', 'object_type', 'object_id'), @@ -414,7 +448,12 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('name', models.CharField(max_length=100, unique=True)), ('description', models.CharField(blank=True, max_length=200)), - ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ( + 'user', + models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL + ), + ), ], options={ 'ordering': ('name',), @@ -429,8 +468,18 @@ class Migration(migrations.Migration): ('action', models.CharField(max_length=20)), ('object_id', models.PositiveBigIntegerField(blank=True, null=True)), ('data', models.JSONField(blank=True, null=True)), - ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='staged_changes', to='extras.branch')), - ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')), + ( + 'branch', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='staged_changes', to='extras.branch' + ), + ), + ( + 'object_type', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype' + ), + ), ], options={ 'ordering': ('pk',), @@ -439,7 +488,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='configcontext', name='data_file', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.datafile'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='core.datafile', + ), ), migrations.AddField( model_name='configcontext', @@ -449,7 +504,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='configcontext', name='data_source', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='core.datasource'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='core.datasource', + ), ), migrations.AddField( model_name='configcontext', @@ -464,7 +525,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='exporttemplate', name='data_file', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.datafile'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='core.datafile', + ), ), migrations.AddField( model_name='exporttemplate', @@ -474,7 +541,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='exporttemplate', name='data_source', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='core.datasource'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='core.datasource', + ), ), migrations.AddField( model_name='exporttemplate', @@ -498,8 +571,26 @@ class Migration(migrations.Migration): ('description', models.CharField(blank=True, max_length=200)), ('template_code', models.TextField()), ('environment_params', models.JSONField(blank=True, default=dict, null=True)), - ('data_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.datafile')), - ('data_source', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='core.datasource')), + ( + 'data_file', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='+', + to='core.datafile', + ), + ), + ( + 'data_source', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='core.datasource', + ), + ), ('auto_sync_enabled', models.BooleanField(default=False)), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], diff --git a/netbox/extras/migrations/0087_squashed_0098.py b/netbox/extras/migrations/0087_squashed_0098.py index bbe7f79f5..839f4cbe4 100644 --- a/netbox/extras/migrations/0087_squashed_0098.py +++ b/netbox/extras/migrations/0087_squashed_0098.py @@ -9,7 +9,6 @@ import utilities.json class Migration(migrations.Migration): - replaces = [ ('extras', '0087_dashboard'), ('extras', '0088_jobresult_webhooks'), @@ -22,7 +21,7 @@ class Migration(migrations.Migration): ('extras', '0095_bookmarks'), ('extras', '0096_customfieldchoiceset'), ('extras', '0097_customfield_remove_choices'), - ('extras', '0098_webhook_custom_field_data_webhook_tags') + ('extras', '0098_webhook_custom_field_data_webhook_tags'), ] dependencies = [ @@ -39,7 +38,14 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('layout', models.JSONField(default=list)), ('config', models.JSONField(default=dict)), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='dashboard', to=settings.AUTH_USER_MODEL)), + ( + 'user', + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + related_name='dashboard', + to=settings.AUTH_USER_MODEL, + ), + ), ], ), migrations.AddField( @@ -64,8 +70,7 @@ class Migration(migrations.Migration): ), migrations.CreateModel( name='ReportModule', - fields=[ - ], + fields=[], options={ 'proxy': True, 'ordering': ('file_root', 'file_path'), @@ -76,8 +81,7 @@ class Migration(migrations.Migration): ), migrations.CreateModel( name='ScriptModule', - fields=[ - ], + fields=[], options={ 'proxy': True, 'ordering': ('file_root', 'file_path'), @@ -108,7 +112,10 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('created', models.DateTimeField(auto_now_add=True)), ('object_id', models.PositiveBigIntegerField()), - ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype')), + ( + 'object_type', + models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'), + ), ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), ], options={ @@ -117,7 +124,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='bookmark', - constraint=models.UniqueConstraint(fields=('object_type', 'object_id', 'user'), name='extras_bookmark_unique_per_object_and_user'), + constraint=models.UniqueConstraint( + fields=('object_type', 'object_id', 'user'), name='extras_bookmark_unique_per_object_and_user' + ), ), migrations.CreateModel( name='CustomFieldChoiceSet', @@ -128,7 +137,17 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=100, unique=True)), ('description', models.CharField(blank=True, max_length=200)), ('base_choices', models.CharField(blank=True, max_length=50)), - ('extra_choices', django.contrib.postgres.fields.ArrayField(base_field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=100), size=2), blank=True, null=True, size=None)), + ( + 'extra_choices', + django.contrib.postgres.fields.ArrayField( + base_field=django.contrib.postgres.fields.ArrayField( + base_field=models.CharField(max_length=100), size=2 + ), + blank=True, + null=True, + size=None, + ), + ), ('order_alphabetically', models.BooleanField(default=False)), ], options={ @@ -138,7 +157,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='customfield', name='choice_set', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='choices_for', to='extras.customfieldchoiceset'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='choices_for', + to='extras.customfieldchoiceset', + ), ), migrations.RemoveField( model_name='customfield', diff --git a/netbox/extras/migrations/0099_cachedvalue_ordering.py b/netbox/extras/migrations/0099_cachedvalue_ordering.py index 242ffd983..36b91d59b 100644 --- a/netbox/extras/migrations/0099_cachedvalue_ordering.py +++ b/netbox/extras/migrations/0099_cachedvalue_ordering.py @@ -4,7 +4,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('extras', '0098_webhook_custom_field_data_webhook_tags'), ] diff --git a/netbox/extras/migrations/0100_customfield_ui_attrs.py b/netbox/extras/migrations/0100_customfield_ui_attrs.py index a4a713a86..b1a404d16 100644 --- a/netbox/extras/migrations/0100_customfield_ui_attrs.py +++ b/netbox/extras/migrations/0100_customfield_ui_attrs.py @@ -14,7 +14,6 @@ def update_ui_attrs(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('extras', '0099_cachedvalue_ordering'), ] @@ -30,10 +29,7 @@ class Migration(migrations.Migration): name='ui_visible', field=models.CharField(default='always', max_length=50), ), - migrations.RunPython( - code=update_ui_attrs, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=update_ui_attrs, reverse_code=migrations.RunPython.noop), migrations.RemoveField( model_name='customfield', name='ui_visibility', diff --git a/netbox/extras/migrations/0101_eventrule.py b/netbox/extras/migrations/0101_eventrule.py index 3d236c847..605307c27 100644 --- a/netbox/extras/migrations/0101_eventrule.py +++ b/netbox/extras/migrations/0101_eventrule.py @@ -8,8 +8,8 @@ from extras.choices import * def move_webhooks(apps, schema_editor): - Webhook = apps.get_model("extras", "Webhook") - EventRule = apps.get_model("extras", "EventRule") + Webhook = apps.get_model('extras', 'Webhook') + EventRule = apps.get_model('extras', 'EventRule') webhook_ct = ContentType.objects.get_for_model(Webhook).pk for webhook in Webhook.objects.all(): @@ -39,7 +39,6 @@ class Migration(migrations.Migration): ] operations = [ - # Create the EventRule model migrations.CreateModel( name='EventRule', @@ -93,12 +92,12 @@ class Migration(migrations.Migration): ), migrations.AddIndex( model_name='eventrule', - index=models.Index(fields=['action_object_type', 'action_object_id'], name='extras_even_action__d9e2af_idx'), + index=models.Index( + fields=['action_object_type', 'action_object_id'], name='extras_even_action__d9e2af_idx' + ), ), - # Replicate Webhook data migrations.RunPython(move_webhooks), - # Remove obsolete fields from Webhook migrations.RemoveConstraint( model_name='webhook', @@ -136,7 +135,6 @@ class Migration(migrations.Migration): model_name='webhook', name='type_update', ), - # Add description field to Webhook migrations.AddField( model_name='webhook', diff --git a/netbox/extras/migrations/0102_move_configrevision.py b/netbox/extras/migrations/0102_move_configrevision.py index 36eef1205..64ff8c9ad 100644 --- a/netbox/extras/migrations/0102_move_configrevision.py +++ b/netbox/extras/migrations/0102_move_configrevision.py @@ -13,7 +13,6 @@ def update_content_type(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('extras', '0101_eventrule'), ] @@ -32,8 +31,5 @@ class Migration(migrations.Migration): ), ], ), - migrations.RunPython( - code=update_content_type, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=update_content_type, reverse_code=migrations.RunPython.noop), ] diff --git a/netbox/extras/migrations/0103_gfk_indexes.py b/netbox/extras/migrations/0103_gfk_indexes.py index 2ccbdb2ff..f32b2e116 100644 --- a/netbox/extras/migrations/0103_gfk_indexes.py +++ b/netbox/extras/migrations/0103_gfk_indexes.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('extras', '0102_move_configrevision'), ] @@ -20,15 +19,21 @@ class Migration(migrations.Migration): ), migrations.AddIndex( model_name='journalentry', - index=models.Index(fields=['assigned_object_type', 'assigned_object_id'], name='extras_jour_assigne_76510f_idx'), + index=models.Index( + fields=['assigned_object_type', 'assigned_object_id'], name='extras_jour_assigne_76510f_idx' + ), ), migrations.AddIndex( model_name='objectchange', - index=models.Index(fields=['changed_object_type', 'changed_object_id'], name='extras_obje_changed_927fe5_idx'), + index=models.Index( + fields=['changed_object_type', 'changed_object_id'], name='extras_obje_changed_927fe5_idx' + ), ), migrations.AddIndex( model_name='objectchange', - index=models.Index(fields=['related_object_type', 'related_object_id'], name='extras_obje_related_bfcdef_idx'), + index=models.Index( + fields=['related_object_type', 'related_object_id'], name='extras_obje_related_bfcdef_idx' + ), ), migrations.AddIndex( model_name='stagedchange', diff --git a/netbox/extras/migrations/0105_customfield_min_max_values.py b/netbox/extras/migrations/0105_customfield_min_max_values.py index bcf3f97bd..71a0dcc68 100644 --- a/netbox/extras/migrations/0105_customfield_min_max_values.py +++ b/netbox/extras/migrations/0105_customfield_min_max_values.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('extras', '0104_stagedchange_remove_change_logging'), ] diff --git a/netbox/extras/migrations/0106_bookmark_user_cascade_deletion.py b/netbox/extras/migrations/0106_bookmark_user_cascade_deletion.py index d7bef2f0b..bc0e1bbd0 100644 --- a/netbox/extras/migrations/0106_bookmark_user_cascade_deletion.py +++ b/netbox/extras/migrations/0106_bookmark_user_cascade_deletion.py @@ -6,7 +6,6 @@ import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('extras', '0105_customfield_min_max_values'), diff --git a/netbox/extras/migrations/0107_cachedvalue_extras_cachedvalue_object.py b/netbox/extras/migrations/0107_cachedvalue_extras_cachedvalue_object.py index 15ce375a2..3f2907192 100644 --- a/netbox/extras/migrations/0107_cachedvalue_extras_cachedvalue_object.py +++ b/netbox/extras/migrations/0107_cachedvalue_extras_cachedvalue_object.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('extras', '0106_bookmark_user_cascade_deletion'), ] diff --git a/netbox/extras/migrations/0108_convert_reports_to_scripts.py b/netbox/extras/migrations/0108_convert_reports_to_scripts.py index b547c41c3..948bac754 100644 --- a/netbox/extras/migrations/0108_convert_reports_to_scripts.py +++ b/netbox/extras/migrations/0108_convert_reports_to_scripts.py @@ -12,16 +12,12 @@ def convert_reportmodule_jobs(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('extras', '0107_cachedvalue_extras_cachedvalue_object'), ] operations = [ - migrations.RunPython( - code=convert_reportmodule_jobs, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=convert_reportmodule_jobs, reverse_code=migrations.RunPython.noop), migrations.DeleteModel( name='Report', ), diff --git a/netbox/extras/migrations/0109_script_model.py b/netbox/extras/migrations/0109_script_model.py index 6bfd2c14c..706a776af 100644 --- a/netbox/extras/migrations/0109_script_model.py +++ b/netbox/extras/migrations/0109_script_model.py @@ -30,7 +30,7 @@ def get_python_name(scriptmodule): """ Return the Python name of a ScriptModule's file on disk. """ - path, filename = os.path.split(scriptmodule.file_path) + filename = os.path.split(scriptmodule.file_path)[0] return os.path.splitext(filename)[0] @@ -55,9 +55,10 @@ def get_module_scripts(scriptmodule): """ Return a dictionary mapping of name and script class inside the passed ScriptModule. """ + def get_name(cls): # For child objects in submodules use the full import path w/o the root module as the name - return cls.full_name.split(".", maxsplit=1)[1] + return cls.full_name.split('.', maxsplit=1)[1] loader = SourceFileLoader(get_python_name(scriptmodule), get_full_path(scriptmodule)) try: @@ -100,17 +101,13 @@ def update_scripts(apps, schema_editor): ) # Update all Jobs associated with this ScriptModule & script name to point to the new Script object - Job.objects.filter( - object_type_id=scriptmodule_ct.id, - object_id=module.pk, - name=script_name - ).update(object_type_id=script_ct.id, object_id=script.pk) + Job.objects.filter(object_type_id=scriptmodule_ct.id, object_id=module.pk, name=script_name).update( + object_type_id=script_ct.id, object_id=script.pk + ) # Update all Jobs associated with this ScriptModule & script name to point to the new Script object - Job.objects.filter( - object_type_id=reportmodule_ct.id, - object_id=module.pk, - name=script_name - ).update(object_type_id=script_ct.id, object_id=script.pk) + Job.objects.filter(object_type_id=reportmodule_ct.id, object_id=module.pk, name=script_name).update( + object_type_id=script_ct.id, object_id=script.pk + ) def update_event_rules(apps, schema_editor): @@ -128,16 +125,13 @@ def update_event_rules(apps, schema_editor): for eventrule in EventRule.objects.filter(action_object_type=scriptmodule_ct): name = eventrule.action_parameters.get('script_name') - obj, created = Script.objects.get_or_create( - module_id=eventrule.action_object_id, - name=name, - defaults={'is_executable': False} + obj, __ = Script.objects.get_or_create( + module_id=eventrule.action_object_id, name=name, defaults={'is_executable': False} ) EventRule.objects.filter(pk=eventrule.pk).update(action_object_type=script_ct, action_object_id=obj.id) class Migration(migrations.Migration): - dependencies = [ ('extras', '0108_convert_reports_to_scripts'), ] @@ -148,8 +142,16 @@ class Migration(migrations.Migration): fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('name', models.CharField(editable=False, max_length=79)), - ('module', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='scripts', to='extras.scriptmodule')), - ('is_executable', models.BooleanField(editable=False, default=True)) + ( + 'module', + models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.CASCADE, + related_name='scripts', + to='extras.scriptmodule', + ), + ), + ('is_executable', models.BooleanField(editable=False, default=True)), ], options={ 'ordering': ('module', 'name'), @@ -159,12 +161,6 @@ class Migration(migrations.Migration): model_name='script', constraint=models.UniqueConstraint(fields=('name', 'module'), name='extras_script_unique_name_module'), ), - migrations.RunPython( - code=update_scripts, - reverse_code=migrations.RunPython.noop - ), - migrations.RunPython( - code=update_event_rules, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=update_scripts, reverse_code=migrations.RunPython.noop), + migrations.RunPython(code=update_event_rules, reverse_code=migrations.RunPython.noop), ] diff --git a/netbox/extras/migrations/0110_remove_eventrule_action_parameters.py b/netbox/extras/migrations/0110_remove_eventrule_action_parameters.py index b7373bdce..494107643 100644 --- a/netbox/extras/migrations/0110_remove_eventrule_action_parameters.py +++ b/netbox/extras/migrations/0110_remove_eventrule_action_parameters.py @@ -2,7 +2,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('extras', '0109_script_model'), ] diff --git a/netbox/extras/migrations/0111_rename_content_types.py b/netbox/extras/migrations/0111_rename_content_types.py index acd6aef0f..a9f80b146 100644 --- a/netbox/extras/migrations/0111_rename_content_types.py +++ b/netbox/extras/migrations/0111_rename_content_types.py @@ -3,7 +3,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0010_gfk_indexes'), ('extras', '0110_remove_eventrule_action_parameters'), @@ -24,16 +23,19 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='customfield', name='object_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='core.objecttype'), - ), - migrations.RunSQL( - "ALTER TABLE IF EXISTS extras_customfield_content_types_id_seq RENAME TO extras_customfield_object_types_id_seq" + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='core.objecttype' + ), ), + migrations.RunSQL(( + 'ALTER TABLE IF EXISTS extras_customfield_content_types_id_seq ' + 'RENAME TO extras_customfield_object_types_id_seq' + )), # Pre-v2.10 sequence name (see #15605) - migrations.RunSQL( - "ALTER TABLE IF EXISTS extras_customfield_obj_type_id_seq RENAME TO extras_customfield_object_types_id_seq" - ), - + migrations.RunSQL(( + 'ALTER TABLE IF EXISTS extras_customfield_obj_type_id_seq ' + 'RENAME TO extras_customfield_object_types_id_seq' + )), # Custom links migrations.RenameField( model_name='customlink', @@ -46,9 +48,8 @@ class Migration(migrations.Migration): field=models.ManyToManyField(related_name='custom_links', to='core.objecttype'), ), migrations.RunSQL( - "ALTER TABLE extras_customlink_content_types_id_seq RENAME TO extras_customlink_object_types_id_seq" + 'ALTER TABLE extras_customlink_content_types_id_seq RENAME TO extras_customlink_object_types_id_seq' ), - # Event rules migrations.RenameField( model_name='eventrule', @@ -61,9 +62,8 @@ class Migration(migrations.Migration): field=models.ManyToManyField(related_name='event_rules', to='core.objecttype'), ), migrations.RunSQL( - "ALTER TABLE extras_eventrule_content_types_id_seq RENAME TO extras_eventrule_object_types_id_seq" + 'ALTER TABLE extras_eventrule_content_types_id_seq RENAME TO extras_eventrule_object_types_id_seq' ), - # Export templates migrations.RenameField( model_name='exporttemplate', @@ -76,9 +76,8 @@ class Migration(migrations.Migration): field=models.ManyToManyField(related_name='export_templates', to='core.objecttype'), ), migrations.RunSQL( - "ALTER TABLE extras_exporttemplate_content_types_id_seq RENAME TO extras_exporttemplate_object_types_id_seq" + 'ALTER TABLE extras_exporttemplate_content_types_id_seq RENAME TO extras_exporttemplate_object_types_id_seq' ), - # Saved filters migrations.RenameField( model_name='savedfilter', @@ -91,9 +90,8 @@ class Migration(migrations.Migration): field=models.ManyToManyField(related_name='saved_filters', to='core.objecttype'), ), migrations.RunSQL( - "ALTER TABLE extras_savedfilter_content_types_id_seq RENAME TO extras_savedfilter_object_types_id_seq" + 'ALTER TABLE extras_savedfilter_content_types_id_seq RENAME TO extras_savedfilter_object_types_id_seq' ), - # Image attachments migrations.RemoveIndex( model_name='imageattachment', diff --git a/netbox/extras/migrations/0112_tag_update_object_types.py b/netbox/extras/migrations/0112_tag_update_object_types.py index 87ec117a4..e863ba8c3 100644 --- a/netbox/extras/migrations/0112_tag_update_object_types.py +++ b/netbox/extras/migrations/0112_tag_update_object_types.py @@ -2,7 +2,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0010_gfk_indexes'), ('extras', '0111_rename_content_types'), diff --git a/netbox/extras/migrations/0113_customfield_rename_object_type.py b/netbox/extras/migrations/0113_customfield_rename_object_type.py index 73c4a2a61..9ad9fbbc4 100644 --- a/netbox/extras/migrations/0113_customfield_rename_object_type.py +++ b/netbox/extras/migrations/0113_customfield_rename_object_type.py @@ -2,7 +2,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('extras', '0112_tag_update_object_types'), ] diff --git a/netbox/extras/migrations/0114_customfield_add_comments.py b/netbox/extras/migrations/0114_customfield_add_comments.py index cd85db1ba..ad9e3d46f 100644 --- a/netbox/extras/migrations/0114_customfield_add_comments.py +++ b/netbox/extras/migrations/0114_customfield_add_comments.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('extras', '0113_customfield_rename_object_type'), ] diff --git a/netbox/extras/migrations/0115_convert_dashboard_widgets.py b/netbox/extras/migrations/0115_convert_dashboard_widgets.py index c85c83ecf..28f6eade9 100644 --- a/netbox/extras/migrations/0115_convert_dashboard_widgets.py +++ b/netbox/extras/migrations/0115_convert_dashboard_widgets.py @@ -16,14 +16,10 @@ def update_dashboard_widgets(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('extras', '0114_customfield_add_comments'), ] operations = [ - migrations.RunPython( - code=update_dashboard_widgets, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=update_dashboard_widgets, reverse_code=migrations.RunPython.noop), ] diff --git a/netbox/extras/migrations/0116_custom_link_button_color.py b/netbox/extras/migrations/0116_custom_link_button_color.py index 665d73017..ff47eab11 100644 --- a/netbox/extras/migrations/0116_custom_link_button_color.py +++ b/netbox/extras/migrations/0116_custom_link_button_color.py @@ -7,7 +7,6 @@ def update_link_buttons(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('extras', '0115_convert_dashboard_widgets'), ] @@ -18,8 +17,5 @@ class Migration(migrations.Migration): name='button_class', field=models.CharField(default='default', max_length=30), ), - migrations.RunPython( - code=update_link_buttons, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=update_link_buttons, reverse_code=migrations.RunPython.noop), ] diff --git a/netbox/extras/migrations/0117_move_objectchange.py b/netbox/extras/migrations/0117_move_objectchange.py index a69b5a711..62c7255e7 100644 --- a/netbox/extras/migrations/0117_move_objectchange.py +++ b/netbox/extras/migrations/0117_move_objectchange.py @@ -26,7 +26,6 @@ def update_dashboard_widgets(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('extras', '0116_custom_link_button_color'), ('core', '0011_move_objectchange'), @@ -44,81 +43,64 @@ class Migration(migrations.Migration): name='ObjectChange', table='core_objectchange', ), - # Rename PK sequence - migrations.RunSQL( - "ALTER TABLE extras_objectchange_id_seq" - " RENAME TO core_objectchange_id_seq" - ), - + migrations.RunSQL('ALTER TABLE extras_objectchange_id_seq' ' RENAME TO core_objectchange_id_seq'), # Rename indexes. Hashes generated by schema_editor._create_index_name() + migrations.RunSQL('ALTER INDEX extras_objectchange_pkey' ' RENAME TO core_objectchange_pkey'), migrations.RunSQL( - "ALTER INDEX extras_objectchange_pkey" - " RENAME TO core_objectchange_pkey" + 'ALTER INDEX extras_obje_changed_927fe5_idx' + ' RENAME TO core_objectchange_changed_object_type_id_cha_79a9ed1e' ), migrations.RunSQL( - "ALTER INDEX extras_obje_changed_927fe5_idx" - " RENAME TO core_objectchange_changed_object_type_id_cha_79a9ed1e" + 'ALTER INDEX extras_obje_related_bfcdef_idx' + ' RENAME TO core_objectchange_related_object_type_id_rel_a71d604a' ), migrations.RunSQL( - "ALTER INDEX extras_obje_related_bfcdef_idx" - " RENAME TO core_objectchange_related_object_type_id_rel_a71d604a" + 'ALTER INDEX extras_objectchange_changed_object_type_id_b755bb60' + ' RENAME TO core_objectchange_changed_object_type_id_2070ade6' ), migrations.RunSQL( - "ALTER INDEX extras_objectchange_changed_object_type_id_b755bb60" - " RENAME TO core_objectchange_changed_object_type_id_2070ade6" + 'ALTER INDEX extras_objectchange_related_object_type_id_fe6e521f' + ' RENAME TO core_objectchange_related_object_type_id_b80958af' ), migrations.RunSQL( - "ALTER INDEX extras_objectchange_related_object_type_id_fe6e521f" - " RENAME TO core_objectchange_related_object_type_id_b80958af" + 'ALTER INDEX extras_objectchange_request_id_4ae21e90' + ' RENAME TO core_objectchange_request_id_d9d160ac' ), migrations.RunSQL( - "ALTER INDEX extras_objectchange_request_id_4ae21e90" - " RENAME TO core_objectchange_request_id_d9d160ac" + 'ALTER INDEX extras_objectchange_time_224380ea' ' RENAME TO core_objectchange_time_800f60a5' ), migrations.RunSQL( - "ALTER INDEX extras_objectchange_time_224380ea" - " RENAME TO core_objectchange_time_800f60a5" + 'ALTER INDEX extras_objectchange_user_id_7fdf8186' ' RENAME TO core_objectchange_user_id_2b2142be' ), - migrations.RunSQL( - "ALTER INDEX extras_objectchange_user_id_7fdf8186" - " RENAME TO core_objectchange_user_id_2b2142be" - ), - # Rename constraints migrations.RunSQL( - "ALTER TABLE core_objectchange RENAME CONSTRAINT " - "extras_objectchange_changed_object_id_check TO " - "core_objectchange_changed_object_id_check" + 'ALTER TABLE core_objectchange RENAME CONSTRAINT ' + 'extras_objectchange_changed_object_id_check TO ' + 'core_objectchange_changed_object_id_check' ), migrations.RunSQL( - "ALTER TABLE core_objectchange RENAME CONSTRAINT " - "extras_objectchange_related_object_id_check TO " - "core_objectchange_related_object_id_check" + 'ALTER TABLE core_objectchange RENAME CONSTRAINT ' + 'extras_objectchange_related_object_id_check TO ' + 'core_objectchange_related_object_id_check' ), migrations.RunSQL( - "ALTER TABLE core_objectchange RENAME CONSTRAINT " - "extras_objectchange_changed_object_type__b755bb60_fk_django_co TO " - "core_objectchange_changed_object_type_id_2070ade6" + 'ALTER TABLE core_objectchange RENAME CONSTRAINT ' + 'extras_objectchange_changed_object_type__b755bb60_fk_django_co TO ' + 'core_objectchange_changed_object_type_id_2070ade6' ), migrations.RunSQL( - "ALTER TABLE core_objectchange RENAME CONSTRAINT " - "extras_objectchange_related_object_type__fe6e521f_fk_django_co TO " - "core_objectchange_related_object_type_id_b80958af" + 'ALTER TABLE core_objectchange RENAME CONSTRAINT ' + 'extras_objectchange_related_object_type__fe6e521f_fk_django_co TO ' + 'core_objectchange_related_object_type_id_b80958af' ), migrations.RunSQL( - "ALTER TABLE core_objectchange RENAME CONSTRAINT " - "extras_objectchange_user_id_7fdf8186_fk_auth_user_id TO " - "core_objectchange_user_id_2b2142be" + 'ALTER TABLE core_objectchange RENAME CONSTRAINT ' + 'extras_objectchange_user_id_7fdf8186_fk_auth_user_id TO ' + 'core_objectchange_user_id_2b2142be' ), ], ), - migrations.RunPython( - code=update_content_types, - reverse_code=migrations.RunPython.noop - ), - migrations.RunPython( - code=update_dashboard_widgets, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=update_content_types, reverse_code=migrations.RunPython.noop), + migrations.RunPython(code=update_dashboard_widgets, reverse_code=migrations.RunPython.noop), ] diff --git a/netbox/extras/migrations/0118_customfield_uniqueness.py b/netbox/extras/migrations/0118_customfield_uniqueness.py index b7693aa24..7571e975a 100644 --- a/netbox/extras/migrations/0118_customfield_uniqueness.py +++ b/netbox/extras/migrations/0118_customfield_uniqueness.py @@ -2,7 +2,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('extras', '0117_move_objectchange'), ] diff --git a/netbox/extras/migrations/0119_notifications.py b/netbox/extras/migrations/0119_notifications.py index c266f3b6c..2e6aefd20 100644 --- a/netbox/extras/migrations/0119_notifications.py +++ b/netbox/extras/migrations/0119_notifications.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('contenttypes', '0002_remove_content_type_name'), ('extras', '0118_customfield_uniqueness'), @@ -22,7 +21,10 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=100, unique=True)), ('description', models.CharField(blank=True, max_length=200)), ('groups', models.ManyToManyField(blank=True, related_name='notification_groups', to='users.group')), - ('users', models.ManyToManyField(blank=True, related_name='notification_groups', to=settings.AUTH_USER_MODEL)), + ( + 'users', + models.ManyToManyField(blank=True, related_name='notification_groups', to=settings.AUTH_USER_MODEL), + ), ], options={ 'verbose_name': 'notification group', @@ -36,8 +38,18 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('created', models.DateTimeField(auto_now_add=True)), ('object_id', models.PositiveBigIntegerField()), - ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subscriptions', to=settings.AUTH_USER_MODEL)), + ( + 'object_type', + models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'), + ), + ( + 'user', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name='subscriptions', + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ 'verbose_name': 'subscription', @@ -53,9 +65,19 @@ class Migration(migrations.Migration): ('read', models.DateTimeField(blank=True, null=True)), ('object_id', models.PositiveBigIntegerField()), ('event_type', models.CharField(max_length=50)), - ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype')), + ( + 'object_type', + models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'), + ), ('object_repr', models.CharField(editable=False, max_length=200)), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notifications', to=settings.AUTH_USER_MODEL)), + ( + 'user', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name='notifications', + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ 'verbose_name': 'notification', @@ -66,7 +88,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='notification', - constraint=models.UniqueConstraint(fields=('object_type', 'object_id', 'user'), name='extras_notification_unique_per_object_and_user'), + constraint=models.UniqueConstraint( + fields=('object_type', 'object_id', 'user'), name='extras_notification_unique_per_object_and_user' + ), ), migrations.AddIndex( model_name='subscription', @@ -74,6 +98,8 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='subscription', - constraint=models.UniqueConstraint(fields=('object_type', 'object_id', 'user'), name='extras_subscription_unique_per_object_and_user'), + constraint=models.UniqueConstraint( + fields=('object_type', 'object_id', 'user'), name='extras_subscription_unique_per_object_and_user' + ), ), ] diff --git a/netbox/extras/migrations/0120_eventrule_event_types.py b/netbox/extras/migrations/0120_eventrule_event_types.py index f62c83e4c..2bcc0a4e6 100644 --- a/netbox/extras/migrations/0120_eventrule_event_types.py +++ b/netbox/extras/migrations/0120_eventrule_event_types.py @@ -26,7 +26,6 @@ def set_event_types(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('extras', '0119_notifications'), ] @@ -36,16 +35,10 @@ class Migration(migrations.Migration): model_name='eventrule', name='event_types', field=django.contrib.postgres.fields.ArrayField( - base_field=models.CharField(max_length=50), - blank=True, - null=True, - size=None + base_field=models.CharField(max_length=50), blank=True, null=True, size=None ), ), - migrations.RunPython( - code=set_event_types, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=set_event_types, reverse_code=migrations.RunPython.noop), migrations.AlterField( model_name='eventrule', name='event_types', diff --git a/netbox/extras/migrations/0121_customfield_related_object_filter.py b/netbox/extras/migrations/0121_customfield_related_object_filter.py index d6e41fd7d..10eecd6cc 100644 --- a/netbox/extras/migrations/0121_customfield_related_object_filter.py +++ b/netbox/extras/migrations/0121_customfield_related_object_filter.py @@ -2,7 +2,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('extras', '0120_eventrule_event_types'), ] diff --git a/netbox/extras/migrations/0122_charfield_null_choices.py b/netbox/extras/migrations/0122_charfield_null_choices.py new file mode 100644 index 000000000..a32051cb1 --- /dev/null +++ b/netbox/extras/migrations/0122_charfield_null_choices.py @@ -0,0 +1,25 @@ +from django.db import migrations, models + + +def set_null_values(apps, schema_editor): + """ + Replace empty strings with null values. + """ + CustomFieldChoiceSet = apps.get_model('extras', 'CustomFieldChoiceSet') + + CustomFieldChoiceSet.objects.filter(base_choices='').update(base_choices=None) + + +class Migration(migrations.Migration): + dependencies = [ + ('extras', '0121_customfield_related_object_filter'), + ] + + operations = [ + migrations.AlterField( + model_name='customfieldchoiceset', + name='base_choices', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.RunPython(code=set_null_values, reverse_code=migrations.RunPython.noop), + ] diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index 8b7fc0cb6..e1ceaf7a6 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -760,6 +760,7 @@ class CustomFieldChoiceSet(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel max_length=50, choices=CustomFieldChoiceSetBaseChoices, blank=True, + null=True, help_text=_('Base set of predefined choices (optional)') ) extra_choices = ArrayField( diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index d8a274c89..d3e443b14 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -704,7 +704,10 @@ class JournalEntry(CustomFieldsMixin, CustomLinksMixin, TagsMixin, ExportTemplat def __str__(self): created = timezone.localtime(self.created) - return f"{created.date().isoformat()} {created.time().isoformat(timespec='minutes')} ({self.get_kind_display()})" + return ( + f"{created.date().isoformat()} {created.time().isoformat(timespec='minutes')} " + f"({self.get_kind_display()})" + ) def get_absolute_url(self): return reverse('extras:journalentry', args=[self.pk]) diff --git a/netbox/extras/tests/test_custom_validation.py b/netbox/extras/tests/test_custom_validation.py index 652bc241b..6eb90e5b0 100644 --- a/netbox/extras/tests/test_custom_validation.py +++ b/netbox/extras/tests/test_custom_validation.py @@ -191,7 +191,7 @@ class BulkImportCustomValidationTest(ModelViewTestCase): # Attempt to import providers without tags request = { - 'path': self._get_url('import'), + 'path': self._get_url('bulk_import'), 'data': post_data(data), } response = self.client.post(**request) @@ -207,7 +207,7 @@ class BulkImportCustomValidationTest(ModelViewTestCase): ) data['data'] = '\n'.join(csv_data) request = { - 'path': self._get_url('import'), + 'path': self._get_url('bulk_import'), 'data': post_data(data), } response = self.client.post(**request) diff --git a/netbox/extras/tests/test_customfields.py b/netbox/extras/tests/test_customfields.py index 2bc9b5acc..d36477da8 100644 --- a/netbox/extras/tests/test_customfields.py +++ b/netbox/extras/tests/test_customfields.py @@ -637,15 +637,51 @@ class CustomFieldAPITest(APITestCase): ) custom_fields = ( - CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='text_field', default='foo'), - CustomField(type=CustomFieldTypeChoices.TYPE_LONGTEXT, name='longtext_field', default='ABC'), - CustomField(type=CustomFieldTypeChoices.TYPE_INTEGER, name='integer_field', default=123), - CustomField(type=CustomFieldTypeChoices.TYPE_DECIMAL, name='decimal_field', default=123.45), - CustomField(type=CustomFieldTypeChoices.TYPE_BOOLEAN, name='boolean_field', default=False), - CustomField(type=CustomFieldTypeChoices.TYPE_DATE, name='date_field', default='2020-01-01'), - CustomField(type=CustomFieldTypeChoices.TYPE_DATETIME, name='datetime_field', default='2020-01-01T01:23:45'), - CustomField(type=CustomFieldTypeChoices.TYPE_URL, name='url_field', default='http://example.com/1'), - CustomField(type=CustomFieldTypeChoices.TYPE_JSON, name='json_field', default='{"x": "y"}'), + CustomField( + type=CustomFieldTypeChoices.TYPE_TEXT, + name='text_field', + default='foo' + ), + CustomField( + type=CustomFieldTypeChoices.TYPE_LONGTEXT, + name='longtext_field', + default='ABC' + ), + CustomField( + type=CustomFieldTypeChoices.TYPE_INTEGER, + name='integer_field', + default=123 + ), + CustomField( + type=CustomFieldTypeChoices.TYPE_DECIMAL, + name='decimal_field', + default=123.45 + ), + CustomField( + type=CustomFieldTypeChoices.TYPE_BOOLEAN, + name='boolean_field', + default=False) + , + CustomField( + type=CustomFieldTypeChoices.TYPE_DATE, + name='date_field', + default='2020-01-01' + ), + CustomField( + type=CustomFieldTypeChoices.TYPE_DATETIME, + name='datetime_field', + default='2020-01-01T01:23:45' + ), + CustomField( + type=CustomFieldTypeChoices.TYPE_URL, + name='url_field', + default='http://example.com/1' + ), + CustomField( + type=CustomFieldTypeChoices.TYPE_JSON, + name='json_field', + default='{"x": "y"}' + ), CustomField( type=CustomFieldTypeChoices.TYPE_SELECT, name='select_field', @@ -656,7 +692,7 @@ class CustomFieldAPITest(APITestCase): type=CustomFieldTypeChoices.TYPE_MULTISELECT, name='multiselect_field', default=['foo'], - choice_set=choice_set + choice_set=choice_set, ), CustomField( type=CustomFieldTypeChoices.TYPE_OBJECT, @@ -1273,14 +1309,23 @@ class CustomFieldImportTest(TestCase): Import a Site in CSV format, including a value for each CustomField. """ data = ( - ('name', 'slug', 'status', 'cf_text', 'cf_longtext', 'cf_integer', 'cf_decimal', 'cf_boolean', 'cf_date', 'cf_datetime', 'cf_url', 'cf_json', 'cf_select', 'cf_multiselect'), - ('Site 1', 'site-1', 'active', 'ABC', 'Foo', '123', '123.45', 'True', '2020-01-01', '2020-01-01 12:00:00', 'http://example.com/1', '{"foo": 123}', 'a', '"a,b"'), - ('Site 2', 'site-2', 'active', 'DEF', 'Bar', '456', '456.78', 'False', '2020-01-02', '2020-01-02 12:00:00', 'http://example.com/2', '{"bar": 456}', 'b', '"b,c"'), + ( + 'name', 'slug', 'status', 'cf_text', 'cf_longtext', 'cf_integer', 'cf_decimal', 'cf_boolean', 'cf_date', + 'cf_datetime', 'cf_url', 'cf_json', 'cf_select', 'cf_multiselect', + ), + ( + 'Site 1', 'site-1', 'active', 'ABC', 'Foo', '123', '123.45', 'True', '2020-01-01', + '2020-01-01 12:00:00', 'http://example.com/1', '{"foo": 123}', 'a', '"a,b"', + ), + ( + 'Site 2', 'site-2', 'active', 'DEF', 'Bar', '456', '456.78', 'False', '2020-01-02', + '2020-01-02 12:00:00', 'http://example.com/2', '{"bar": 456}', 'b', '"b,c"', + ), ('Site 3', 'site-3', 'active', '', '', '', '', '', '', '', '', '', '', ''), ) csv_data = '\n'.join(','.join(row) for row in data) - response = self.client.post(reverse('dcim:site_import'), { + response = self.client.post(reverse('dcim:site_bulk_import'), { 'data': csv_data, 'format': ImportFormatChoices.CSV, 'csv_delimiter': CSVDelimiterChoices.AUTO, @@ -1616,7 +1661,10 @@ class CustomFieldModelFilterTest(TestCase): self.assertEqual(self.filterset({'cf_cf6__lte': ['2016-06-27']}, self.queryset).qs.count(), 2) def test_filter_url_strict(self): - self.assertEqual(self.filterset({'cf_cf7': ['http://a.example.com', 'http://b.example.com']}, self.queryset).qs.count(), 2) + self.assertEqual( + self.filterset({'cf_cf7': ['http://a.example.com', 'http://b.example.com']}, self.queryset).qs.count(), + 2 + ) self.assertEqual(self.filterset({'cf_cf7__n': ['http://b.example.com']}, self.queryset).qs.count(), 2) self.assertEqual(self.filterset({'cf_cf7__ic': ['b']}, self.queryset).qs.count(), 1) self.assertEqual(self.filterset({'cf_cf7__nic': ['b']}, self.queryset).qs.count(), 2) @@ -1640,9 +1688,18 @@ class CustomFieldModelFilterTest(TestCase): def test_filter_object(self): manufacturer_ids = Manufacturer.objects.values_list('id', flat=True) - self.assertEqual(self.filterset({'cf_cf11': [manufacturer_ids[0], manufacturer_ids[1]]}, self.queryset).qs.count(), 2) + self.assertEqual( + self.filterset({'cf_cf11': [manufacturer_ids[0], manufacturer_ids[1]]}, self.queryset).qs.count(), + 2 + ) def test_filter_multiobject(self): manufacturer_ids = Manufacturer.objects.values_list('id', flat=True) - self.assertEqual(self.filterset({'cf_cf12': [manufacturer_ids[0], manufacturer_ids[1]]}, self.queryset).qs.count(), 2) - self.assertEqual(self.filterset({'cf_cf12': [manufacturer_ids[3]]}, self.queryset).qs.count(), 3) + self.assertEqual( + self.filterset({'cf_cf12': [manufacturer_ids[0], manufacturer_ids[1]]}, self.queryset).qs.count(), + 2 + ) + self.assertEqual( + self.filterset({'cf_cf12': [manufacturer_ids[3]]}, self.queryset).qs.count(), + 3 + ) diff --git a/netbox/extras/tests/test_event_rules.py b/netbox/extras/tests/test_event_rules.py index 7f7b0b81f..2565e5bde 100644 --- a/netbox/extras/tests/test_event_rules.py +++ b/netbox/extras/tests/test_event_rules.py @@ -50,21 +50,24 @@ class EventRuleTest(APITestCase): event_types=[OBJECT_CREATED], action_type=EventRuleActionChoices.WEBHOOK, action_object_type=webhook_type, - action_object_id=webhooks[0].id + action_object_id=webhooks[0].id, + action_data={"foo": 1}, ), EventRule( name='Event Rule 2', event_types=[OBJECT_UPDATED], action_type=EventRuleActionChoices.WEBHOOK, action_object_type=webhook_type, - action_object_id=webhooks[0].id + action_object_id=webhooks[0].id, + action_data={"foo": 2}, ), EventRule( name='Event Rule 3', event_types=[OBJECT_DELETED], action_type=EventRuleActionChoices.WEBHOOK, action_object_type=webhook_type, - action_object_id=webhooks[0].id + action_object_id=webhooks[0].id, + action_data={"foo": 3}, ), )) for event_rule in event_rules: @@ -134,6 +137,7 @@ class EventRuleTest(APITestCase): self.assertEqual(job.kwargs['event_type'], OBJECT_CREATED) self.assertEqual(job.kwargs['model_name'], 'site') self.assertEqual(job.kwargs['data']['id'], response.data['id']) + self.assertEqual(job.kwargs['data']['foo'], 1) self.assertEqual(len(job.kwargs['data']['tags']), len(response.data['tags'])) self.assertEqual(job.kwargs['snapshots']['postchange']['name'], 'Site 1') self.assertEqual(job.kwargs['snapshots']['postchange']['tags'], ['Bar', 'Foo']) @@ -184,6 +188,7 @@ class EventRuleTest(APITestCase): self.assertEqual(job.kwargs['event_type'], OBJECT_CREATED) self.assertEqual(job.kwargs['model_name'], 'site') self.assertEqual(job.kwargs['data']['id'], response.data[i]['id']) + self.assertEqual(job.kwargs['data']['foo'], 1) self.assertEqual(len(job.kwargs['data']['tags']), len(response.data[i]['tags'])) self.assertEqual(job.kwargs['snapshots']['postchange']['name'], response.data[i]['name']) self.assertEqual(job.kwargs['snapshots']['postchange']['tags'], ['Bar', 'Foo']) @@ -215,6 +220,7 @@ class EventRuleTest(APITestCase): self.assertEqual(job.kwargs['event_type'], OBJECT_UPDATED) self.assertEqual(job.kwargs['model_name'], 'site') self.assertEqual(job.kwargs['data']['id'], site.pk) + self.assertEqual(job.kwargs['data']['foo'], 2) self.assertEqual(len(job.kwargs['data']['tags']), len(response.data['tags'])) self.assertEqual(job.kwargs['snapshots']['prechange']['name'], 'Site 1') self.assertEqual(job.kwargs['snapshots']['prechange']['tags'], ['Bar', 'Foo']) @@ -271,6 +277,7 @@ class EventRuleTest(APITestCase): self.assertEqual(job.kwargs['event_type'], OBJECT_UPDATED) self.assertEqual(job.kwargs['model_name'], 'site') self.assertEqual(job.kwargs['data']['id'], data[i]['id']) + self.assertEqual(job.kwargs['data']['foo'], 2) self.assertEqual(len(job.kwargs['data']['tags']), len(response.data[i]['tags'])) self.assertEqual(job.kwargs['snapshots']['prechange']['name'], sites[i].name) self.assertEqual(job.kwargs['snapshots']['prechange']['tags'], ['Bar', 'Foo']) @@ -297,6 +304,7 @@ class EventRuleTest(APITestCase): self.assertEqual(job.kwargs['event_type'], OBJECT_DELETED) self.assertEqual(job.kwargs['model_name'], 'site') self.assertEqual(job.kwargs['data']['id'], site.pk) + self.assertEqual(job.kwargs['data']['foo'], 3) self.assertEqual(job.kwargs['snapshots']['prechange']['name'], 'Site 1') self.assertEqual(job.kwargs['snapshots']['prechange']['tags'], ['Bar', 'Foo']) @@ -330,6 +338,7 @@ class EventRuleTest(APITestCase): self.assertEqual(job.kwargs['event_type'], OBJECT_DELETED) self.assertEqual(job.kwargs['model_name'], 'site') self.assertEqual(job.kwargs['data']['id'], sites[i].pk) + self.assertEqual(job.kwargs['data']['foo'], 3) self.assertEqual(job.kwargs['snapshots']['prechange']['name'], sites[i].name) self.assertEqual(job.kwargs['snapshots']['prechange']['tags'], ['Bar', 'Foo']) @@ -358,6 +367,7 @@ class EventRuleTest(APITestCase): self.assertEqual(body['username'], 'testuser') self.assertEqual(body['request_id'], str(request_id)) self.assertEqual(body['data']['name'], 'Site 1') + self.assertEqual(body['data']['foo'], 1) return HttpResponse() diff --git a/netbox/extras/tests/test_filtersets.py b/netbox/extras/tests/test_filtersets.py index 9048d5fd9..cf914e665 100644 --- a/netbox/extras/tests/test_filtersets.py +++ b/netbox/extras/tests/test_filtersets.py @@ -1135,6 +1135,7 @@ class TagTestCase(TestCase, ChangeLoggedFilterSetTests): 'l2vpn', 'l2vpntermination', 'location', + 'macaddress', 'manufacturer', 'module', 'modulebay', @@ -1167,11 +1168,16 @@ class TagTestCase(TestCase, ChangeLoggedFilterSetTests): 'tunnelgroup', 'tunneltermination', 'virtualchassis', + 'virtualcircuit', + 'virtualcircuittermination', + 'virtualcircuittype', 'virtualdevicecontext', 'virtualdisk', 'virtualmachine', 'vlan', 'vlangroup', + 'vlantranslationpolicy', + 'vlantranslationrule', 'vminterface', 'vrf', 'webhook', diff --git a/netbox/extras/tests/test_models.py b/netbox/extras/tests/test_models.py index 188a06a3f..c90390dd1 100644 --- a/netbox/extras/tests/test_models.py +++ b/netbox/extras/tests/test_models.py @@ -274,7 +274,7 @@ class ConfigContextTest(TestCase): name="Cluster", group=cluster_group, type=cluster_type, - site=site, + scope=site, ) region_context = ConfigContext.objects.create( @@ -366,7 +366,7 @@ class ConfigContextTest(TestCase): """ site = Site.objects.first() cluster_type = ClusterType.objects.create(name="Cluster Type") - cluster = Cluster.objects.create(name="Cluster", type=cluster_type, site=site) + cluster = Cluster.objects.create(name="Cluster", type=cluster_type, scope=site) vm_role = DeviceRole.objects.first() # Create a ConfigContext associated with the site diff --git a/netbox/extras/urls.py b/netbox/extras/urls.py index b13af1db9..32633493f 100644 --- a/netbox/extras/urls.py +++ b/netbox/extras/urls.py @@ -7,128 +7,68 @@ from utilities.urls import get_model_urls app_name = 'extras' urlpatterns = [ - # Custom fields - path('custom-fields/', views.CustomFieldListView.as_view(), name='customfield_list'), - path('custom-fields/add/', views.CustomFieldEditView.as_view(), name='customfield_add'), - path('custom-fields/import/', views.CustomFieldBulkImportView.as_view(), name='customfield_import'), - path('custom-fields/edit/', views.CustomFieldBulkEditView.as_view(), name='customfield_bulk_edit'), - path('custom-fields/delete/', views.CustomFieldBulkDeleteView.as_view(), name='customfield_bulk_delete'), + path('custom-fields/', include(get_model_urls('extras', 'customfield', detail=False))), path('custom-fields//', include(get_model_urls('extras', 'customfield'))), - # Custom field choices - path('custom-field-choices/', views.CustomFieldChoiceSetListView.as_view(), name='customfieldchoiceset_list'), - path('custom-field-choices/add/', views.CustomFieldChoiceSetEditView.as_view(), name='customfieldchoiceset_add'), - path('custom-field-choices/import/', views.CustomFieldChoiceSetBulkImportView.as_view(), name='customfieldchoiceset_import'), - path('custom-field-choices/edit/', views.CustomFieldChoiceSetBulkEditView.as_view(), name='customfieldchoiceset_bulk_edit'), - path('custom-field-choices/delete/', views.CustomFieldChoiceSetBulkDeleteView.as_view(), name='customfieldchoiceset_bulk_delete'), + path('custom-field-choices/', include(get_model_urls('extras', 'customfieldchoiceset', detail=False))), path('custom-field-choices//', include(get_model_urls('extras', 'customfieldchoiceset'))), - # Custom links - path('custom-links/', views.CustomLinkListView.as_view(), name='customlink_list'), - path('custom-links/add/', views.CustomLinkEditView.as_view(), name='customlink_add'), - path('custom-links/import/', views.CustomLinkBulkImportView.as_view(), name='customlink_import'), - path('custom-links/edit/', views.CustomLinkBulkEditView.as_view(), name='customlink_bulk_edit'), - path('custom-links/delete/', views.CustomLinkBulkDeleteView.as_view(), name='customlink_bulk_delete'), + path('custom-links/', include(get_model_urls('extras', 'customlink', detail=False))), path('custom-links//', include(get_model_urls('extras', 'customlink'))), - # Export templates - path('export-templates/', views.ExportTemplateListView.as_view(), name='exporttemplate_list'), - path('export-templates/add/', views.ExportTemplateEditView.as_view(), name='exporttemplate_add'), - path('export-templates/import/', views.ExportTemplateBulkImportView.as_view(), name='exporttemplate_import'), - path('export-templates/edit/', views.ExportTemplateBulkEditView.as_view(), name='exporttemplate_bulk_edit'), - path('export-templates/delete/', views.ExportTemplateBulkDeleteView.as_view(), name='exporttemplate_bulk_delete'), - path('export-templates/sync/', views.ExportTemplateBulkSyncDataView.as_view(), name='exporttemplate_bulk_sync'), + path('export-templates/', include(get_model_urls('extras', 'exporttemplate', detail=False))), path('export-templates//', include(get_model_urls('extras', 'exporttemplate'))), - # Saved filters - path('saved-filters/', views.SavedFilterListView.as_view(), name='savedfilter_list'), - path('saved-filters/add/', views.SavedFilterEditView.as_view(), name='savedfilter_add'), - path('saved-filters/import/', views.SavedFilterBulkImportView.as_view(), name='savedfilter_import'), - path('saved-filters/edit/', views.SavedFilterBulkEditView.as_view(), name='savedfilter_bulk_edit'), - path('saved-filters/delete/', views.SavedFilterBulkDeleteView.as_view(), name='savedfilter_bulk_delete'), + path('saved-filters/', include(get_model_urls('extras', 'savedfilter', detail=False))), path('saved-filters//', include(get_model_urls('extras', 'savedfilter'))), - # Bookmarks - path('bookmarks/add/', views.BookmarkCreateView.as_view(), name='bookmark_add'), - path('bookmarks/delete/', views.BookmarkBulkDeleteView.as_view(), name='bookmark_bulk_delete'), + path('bookmarks/', include(get_model_urls('extras', 'bookmark', detail=False))), path('bookmarks//', include(get_model_urls('extras', 'bookmark'))), - # Notification groups - path('notification-groups/', views.NotificationGroupListView.as_view(), name='notificationgroup_list'), - path('notification-groups/add/', views.NotificationGroupEditView.as_view(), name='notificationgroup_add'), - path('notification-groups/import/', views.NotificationGroupBulkImportView.as_view(), name='notificationgroup_import'), - path('notification-groups/edit/', views.NotificationGroupBulkEditView.as_view(), name='notificationgroup_bulk_edit'), - path('notification-groups/delete/', views.NotificationGroupBulkDeleteView.as_view(), name='notificationgroup_bulk_delete'), + path('notification-groups/', include(get_model_urls('extras', 'notificationgroup', detail=False))), path('notification-groups//', include(get_model_urls('extras', 'notificationgroup'))), - # Notifications path('notifications/', views.NotificationsView.as_view(), name='notifications'), - path('notifications/delete/', views.NotificationBulkDeleteView.as_view(), name='notification_bulk_delete'), + path('notifications/', include(get_model_urls('extras', 'notification', detail=False))), path('notifications//', include(get_model_urls('extras', 'notification'))), - # Subscriptions - path('subscriptions/add/', views.SubscriptionCreateView.as_view(), name='subscription_add'), - path('subscriptions/delete/', views.SubscriptionBulkDeleteView.as_view(), name='subscription_bulk_delete'), + path('subscriptions/', include(get_model_urls('extras', 'subscription', detail=False))), path('subscriptions//', include(get_model_urls('extras', 'subscription'))), - # Webhooks - path('webhooks/', views.WebhookListView.as_view(), name='webhook_list'), - path('webhooks/add/', views.WebhookEditView.as_view(), name='webhook_add'), - path('webhooks/import/', views.WebhookBulkImportView.as_view(), name='webhook_import'), - path('webhooks/edit/', views.WebhookBulkEditView.as_view(), name='webhook_bulk_edit'), - path('webhooks/delete/', views.WebhookBulkDeleteView.as_view(), name='webhook_bulk_delete'), + path('webhooks/', include(get_model_urls('extras', 'webhook', detail=False))), path('webhooks//', include(get_model_urls('extras', 'webhook'))), - # Event rules - path('event-rules/', views.EventRuleListView.as_view(), name='eventrule_list'), - path('event-rules/add/', views.EventRuleEditView.as_view(), name='eventrule_add'), - path('event-rules/import/', views.EventRuleBulkImportView.as_view(), name='eventrule_import'), - path('event-rules/edit/', views.EventRuleBulkEditView.as_view(), name='eventrule_bulk_edit'), - path('event-rules/delete/', views.EventRuleBulkDeleteView.as_view(), name='eventrule_bulk_delete'), + path('event-rules/', include(get_model_urls('extras', 'eventrule', detail=False))), path('event-rules//', include(get_model_urls('extras', 'eventrule'))), - # Tags - path('tags/', views.TagListView.as_view(), name='tag_list'), - path('tags/add/', views.TagEditView.as_view(), name='tag_add'), - path('tags/import/', views.TagBulkImportView.as_view(), name='tag_import'), - path('tags/edit/', views.TagBulkEditView.as_view(), name='tag_bulk_edit'), - path('tags/delete/', views.TagBulkDeleteView.as_view(), name='tag_bulk_delete'), + path('tags/', include(get_model_urls('extras', 'tag', detail=False))), path('tags//', include(get_model_urls('extras', 'tag'))), - # Config contexts - path('config-contexts/', views.ConfigContextListView.as_view(), name='configcontext_list'), - path('config-contexts/add/', views.ConfigContextEditView.as_view(), name='configcontext_add'), - path('config-contexts/edit/', views.ConfigContextBulkEditView.as_view(), name='configcontext_bulk_edit'), - path('config-contexts/delete/', views.ConfigContextBulkDeleteView.as_view(), name='configcontext_bulk_delete'), - path('config-contexts/sync/', views.ConfigContextBulkSyncDataView.as_view(), name='configcontext_bulk_sync'), + path('config-contexts/', include(get_model_urls('extras', 'configcontext', detail=False))), path('config-contexts//', include(get_model_urls('extras', 'configcontext'))), - # Config templates - path('config-templates/', views.ConfigTemplateListView.as_view(), name='configtemplate_list'), - path('config-templates/add/', views.ConfigTemplateEditView.as_view(), name='configtemplate_add'), - path('config-templates/edit/', views.ConfigTemplateBulkEditView.as_view(), name='configtemplate_bulk_edit'), - path('config-templates/delete/', views.ConfigTemplateBulkDeleteView.as_view(), name='configtemplate_bulk_delete'), - path('config-templates/sync/', views.ConfigTemplateBulkSyncDataView.as_view(), name='configtemplate_bulk_sync'), + path('config-templates/', include(get_model_urls('extras', 'configtemplate', detail=False))), path('config-templates//', include(get_model_urls('extras', 'configtemplate'))), - # Image attachments - path('image-attachments/', views.ImageAttachmentListView.as_view(), name='imageattachment_list'), - path('image-attachments/add/', views.ImageAttachmentEditView.as_view(), name='imageattachment_add'), + path('image-attachments/', include(get_model_urls('extras', 'imageattachment', detail=False))), path('image-attachments//', include(get_model_urls('extras', 'imageattachment'))), - # Journal entries - path('journal-entries/', views.JournalEntryListView.as_view(), name='journalentry_list'), - path('journal-entries/add/', views.JournalEntryEditView.as_view(), name='journalentry_add'), - path('journal-entries/edit/', views.JournalEntryBulkEditView.as_view(), name='journalentry_bulk_edit'), - path('journal-entries/delete/', views.JournalEntryBulkDeleteView.as_view(), name='journalentry_bulk_delete'), - path('journal-entries/import/', views.JournalEntryBulkImportView.as_view(), name='journalentry_import'), + path('journal-entries/', include(get_model_urls('extras', 'journalentry', detail=False))), path('journal-entries//', include(get_model_urls('extras', 'journalentry'))), # User dashboard path('dashboard/reset/', views.DashboardResetView.as_view(), name='dashboard_reset'), path('dashboard/widgets/add/', views.DashboardWidgetAddView.as_view(), name='dashboardwidget_add'), - path('dashboard/widgets//configure/', views.DashboardWidgetConfigView.as_view(), name='dashboardwidget_config'), - path('dashboard/widgets//delete/', views.DashboardWidgetDeleteView.as_view(), name='dashboardwidget_delete'), + path( + 'dashboard/widgets//configure/', + views.DashboardWidgetConfigView.as_view(), + name='dashboardwidget_config' + ), + path( + 'dashboard/widgets//delete/', + views.DashboardWidgetDeleteView.as_view(), + name='dashboardwidget_delete' + ), # Scripts path('scripts/', views.ScriptListView.as_view(), name='script_list'), diff --git a/netbox/extras/utils.py b/netbox/extras/utils.py index 28d2e13f0..efe7ada5b 100644 --- a/netbox/extras/utils.py +++ b/netbox/extras/utils.py @@ -33,7 +33,7 @@ def image_upload(instance, filename): # Rename the file to the provided name, if any. Attempt to preserve the file extension. extension = filename.rsplit('.')[-1].lower() - if instance.name and extension in ['bmp', 'gif', 'jpeg', 'jpg', 'png']: + if instance.name and extension in ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'webp']: filename = '.'.join([instance.name, extension]) elif instance.name: filename = instance.name diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 321842260..9cb9dd54a 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -42,6 +42,7 @@ from .tables import ReportResultsTable, ScriptResultsTable # Custom fields # +@register_model_view(CustomField, 'list', path='', detail=False) class CustomFieldListView(generic.ObjectListView): queryset = CustomField.objects.select_related('choice_set') filterset = filtersets.CustomFieldFilterSet @@ -69,6 +70,7 @@ class CustomFieldView(generic.ObjectView): } +@register_model_view(CustomField, 'add', detail=False) @register_model_view(CustomField, 'edit') class CustomFieldEditView(generic.ObjectEditView): queryset = CustomField.objects.select_related('choice_set') @@ -80,11 +82,13 @@ class CustomFieldDeleteView(generic.ObjectDeleteView): queryset = CustomField.objects.select_related('choice_set') +@register_model_view(CustomField, 'bulk_import', detail=False) class CustomFieldBulkImportView(generic.BulkImportView): queryset = CustomField.objects.select_related('choice_set') model_form = forms.CustomFieldImportForm +@register_model_view(CustomField, 'bulk_edit', path='edit', detail=False) class CustomFieldBulkEditView(generic.BulkEditView): queryset = CustomField.objects.select_related('choice_set') filterset = filtersets.CustomFieldFilterSet @@ -92,6 +96,7 @@ class CustomFieldBulkEditView(generic.BulkEditView): form = forms.CustomFieldBulkEditForm +@register_model_view(CustomField, 'bulk_delete', path='delete', detail=False) class CustomFieldBulkDeleteView(generic.BulkDeleteView): queryset = CustomField.objects.select_related('choice_set') filterset = filtersets.CustomFieldFilterSet @@ -102,6 +107,7 @@ class CustomFieldBulkDeleteView(generic.BulkDeleteView): # Custom field choices # +@register_model_view(CustomFieldChoiceSet, 'list', path='', detail=False) class CustomFieldChoiceSetListView(generic.ObjectListView): queryset = CustomFieldChoiceSet.objects.all() filterset = filtersets.CustomFieldChoiceSetFilterSet @@ -133,6 +139,7 @@ class CustomFieldChoiceSetView(generic.ObjectView): } +@register_model_view(CustomFieldChoiceSet, 'add', detail=False) @register_model_view(CustomFieldChoiceSet, 'edit') class CustomFieldChoiceSetEditView(generic.ObjectEditView): queryset = CustomFieldChoiceSet.objects.all() @@ -144,11 +151,13 @@ class CustomFieldChoiceSetDeleteView(generic.ObjectDeleteView): queryset = CustomFieldChoiceSet.objects.all() +@register_model_view(CustomFieldChoiceSet, 'bulk_import', detail=False) class CustomFieldChoiceSetBulkImportView(generic.BulkImportView): queryset = CustomFieldChoiceSet.objects.all() model_form = forms.CustomFieldChoiceSetImportForm +@register_model_view(CustomFieldChoiceSet, 'bulk_edit', path='edit', detail=False) class CustomFieldChoiceSetBulkEditView(generic.BulkEditView): queryset = CustomFieldChoiceSet.objects.all() filterset = filtersets.CustomFieldChoiceSetFilterSet @@ -156,6 +165,7 @@ class CustomFieldChoiceSetBulkEditView(generic.BulkEditView): form = forms.CustomFieldChoiceSetBulkEditForm +@register_model_view(CustomFieldChoiceSet, 'bulk_delete', path='delete', detail=False) class CustomFieldChoiceSetBulkDeleteView(generic.BulkDeleteView): queryset = CustomFieldChoiceSet.objects.all() filterset = filtersets.CustomFieldChoiceSetFilterSet @@ -166,6 +176,7 @@ class CustomFieldChoiceSetBulkDeleteView(generic.BulkDeleteView): # Custom links # +@register_model_view(CustomLink, 'list', path='', detail=False) class CustomLinkListView(generic.ObjectListView): queryset = CustomLink.objects.all() filterset = filtersets.CustomLinkFilterSet @@ -178,6 +189,7 @@ class CustomLinkView(generic.ObjectView): queryset = CustomLink.objects.all() +@register_model_view(CustomLink, 'add', detail=False) @register_model_view(CustomLink, 'edit') class CustomLinkEditView(generic.ObjectEditView): queryset = CustomLink.objects.all() @@ -189,11 +201,13 @@ class CustomLinkDeleteView(generic.ObjectDeleteView): queryset = CustomLink.objects.all() +@register_model_view(CustomLink, 'bulk_import', detail=False) class CustomLinkBulkImportView(generic.BulkImportView): queryset = CustomLink.objects.all() model_form = forms.CustomLinkImportForm +@register_model_view(CustomLink, 'bulk_edit', path='edit', detail=False) class CustomLinkBulkEditView(generic.BulkEditView): queryset = CustomLink.objects.all() filterset = filtersets.CustomLinkFilterSet @@ -201,6 +215,7 @@ class CustomLinkBulkEditView(generic.BulkEditView): form = forms.CustomLinkBulkEditForm +@register_model_view(CustomLink, 'bulk_delete', path='delete', detail=False) class CustomLinkBulkDeleteView(generic.BulkDeleteView): queryset = CustomLink.objects.all() filterset = filtersets.CustomLinkFilterSet @@ -211,6 +226,7 @@ class CustomLinkBulkDeleteView(generic.BulkDeleteView): # Export templates # +@register_model_view(ExportTemplate, 'list', path='', detail=False) class ExportTemplateListView(generic.ObjectListView): queryset = ExportTemplate.objects.all() filterset = filtersets.ExportTemplateFilterSet @@ -228,6 +244,7 @@ class ExportTemplateView(generic.ObjectView): queryset = ExportTemplate.objects.all() +@register_model_view(ExportTemplate, 'add', detail=False) @register_model_view(ExportTemplate, 'edit') class ExportTemplateEditView(generic.ObjectEditView): queryset = ExportTemplate.objects.all() @@ -239,11 +256,13 @@ class ExportTemplateDeleteView(generic.ObjectDeleteView): queryset = ExportTemplate.objects.all() +@register_model_view(ExportTemplate, 'bulk_import', detail=False) class ExportTemplateBulkImportView(generic.BulkImportView): queryset = ExportTemplate.objects.all() model_form = forms.ExportTemplateImportForm +@register_model_view(ExportTemplate, 'bulk_edit', path='edit', detail=False) class ExportTemplateBulkEditView(generic.BulkEditView): queryset = ExportTemplate.objects.all() filterset = filtersets.ExportTemplateFilterSet @@ -251,12 +270,14 @@ class ExportTemplateBulkEditView(generic.BulkEditView): form = forms.ExportTemplateBulkEditForm +@register_model_view(ExportTemplate, 'bulk_delete', path='delete', detail=False) class ExportTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ExportTemplate.objects.all() filterset = filtersets.ExportTemplateFilterSet table = tables.ExportTemplateTable +@register_model_view(ExportTemplate, 'bulk_sync', path='sync', detail=False) class ExportTemplateBulkSyncDataView(generic.BulkSyncDataView): queryset = ExportTemplate.objects.all() @@ -283,6 +304,7 @@ class SavedFilterMixin: ) +@register_model_view(SavedFilter, 'list', path='', detail=False) class SavedFilterListView(SavedFilterMixin, generic.ObjectListView): filterset = filtersets.SavedFilterFilterSet filterset_form = forms.SavedFilterFilterForm @@ -294,6 +316,7 @@ class SavedFilterView(SavedFilterMixin, generic.ObjectView): queryset = SavedFilter.objects.all() +@register_model_view(SavedFilter, 'add', detail=False) @register_model_view(SavedFilter, 'edit') class SavedFilterEditView(SavedFilterMixin, generic.ObjectEditView): queryset = SavedFilter.objects.all() @@ -310,11 +333,13 @@ class SavedFilterDeleteView(SavedFilterMixin, generic.ObjectDeleteView): queryset = SavedFilter.objects.all() +@register_model_view(SavedFilter, 'bulk_import', detail=False) class SavedFilterBulkImportView(SavedFilterMixin, generic.BulkImportView): queryset = SavedFilter.objects.all() model_form = forms.SavedFilterImportForm +@register_model_view(SavedFilter, 'bulk_edit', path='edit', detail=False) class SavedFilterBulkEditView(SavedFilterMixin, generic.BulkEditView): queryset = SavedFilter.objects.all() filterset = filtersets.SavedFilterFilterSet @@ -322,6 +347,7 @@ class SavedFilterBulkEditView(SavedFilterMixin, generic.BulkEditView): form = forms.SavedFilterBulkEditForm +@register_model_view(SavedFilter, 'bulk_delete', path='delete', detail=False) class SavedFilterBulkDeleteView(SavedFilterMixin, generic.BulkDeleteView): queryset = SavedFilter.objects.all() filterset = filtersets.SavedFilterFilterSet @@ -332,6 +358,7 @@ class SavedFilterBulkDeleteView(SavedFilterMixin, generic.BulkDeleteView): # Bookmarks # +@register_model_view(Bookmark, 'add', detail=False) class BookmarkCreateView(generic.ObjectEditView): form = forms.BookmarkForm @@ -350,6 +377,7 @@ class BookmarkDeleteView(generic.ObjectDeleteView): return Bookmark.objects.filter(user=request.user) +@register_model_view(Bookmark, 'bulk_delete', path='delete', detail=False) class BookmarkBulkDeleteView(generic.BulkDeleteView): table = tables.BookmarkTable @@ -361,6 +389,7 @@ class BookmarkBulkDeleteView(generic.BulkDeleteView): # Notification groups # +@register_model_view(NotificationGroup, 'list', path='', detail=False) class NotificationGroupListView(generic.ObjectListView): queryset = NotificationGroup.objects.all() filterset = filtersets.NotificationGroupFilterSet @@ -373,6 +402,7 @@ class NotificationGroupView(generic.ObjectView): queryset = NotificationGroup.objects.all() +@register_model_view(NotificationGroup, 'add', detail=False) @register_model_view(NotificationGroup, 'edit') class NotificationGroupEditView(generic.ObjectEditView): queryset = NotificationGroup.objects.all() @@ -384,11 +414,13 @@ class NotificationGroupDeleteView(generic.ObjectDeleteView): queryset = NotificationGroup.objects.all() +@register_model_view(NotificationGroup, 'bulk_import', detail=False) class NotificationGroupBulkImportView(generic.BulkImportView): queryset = NotificationGroup.objects.all() model_form = forms.NotificationGroupImportForm +@register_model_view(NotificationGroup, 'bulk_edit', path='edit', detail=False) class NotificationGroupBulkEditView(generic.BulkEditView): queryset = NotificationGroup.objects.all() filterset = filtersets.NotificationGroupFilterSet @@ -396,6 +428,7 @@ class NotificationGroupBulkEditView(generic.BulkEditView): form = forms.NotificationGroupBulkEditForm +@register_model_view(NotificationGroup, 'bulk_delete', path='delete', detail=False) class NotificationGroupBulkDeleteView(generic.BulkDeleteView): queryset = NotificationGroup.objects.all() filterset = filtersets.NotificationGroupFilterSet @@ -459,6 +492,7 @@ class NotificationDeleteView(generic.ObjectDeleteView): return Notification.objects.filter(user=request.user) +@register_model_view(Notification, 'bulk_delete', path='delete', detail=False) class NotificationBulkDeleteView(generic.BulkDeleteView): table = tables.NotificationTable @@ -470,6 +504,7 @@ class NotificationBulkDeleteView(generic.BulkDeleteView): # Subscriptions # +@register_model_view(Subscription, 'add', detail=False) class SubscriptionCreateView(generic.ObjectEditView): form = forms.SubscriptionForm @@ -488,6 +523,7 @@ class SubscriptionDeleteView(generic.ObjectDeleteView): return Subscription.objects.filter(user=request.user) +@register_model_view(Subscription, 'bulk_delete', path='delete', detail=False) class SubscriptionBulkDeleteView(generic.BulkDeleteView): table = tables.SubscriptionTable @@ -499,6 +535,7 @@ class SubscriptionBulkDeleteView(generic.BulkDeleteView): # Webhooks # +@register_model_view(Webhook, 'list', path='', detail=False) class WebhookListView(generic.ObjectListView): queryset = Webhook.objects.all() filterset = filtersets.WebhookFilterSet @@ -511,6 +548,7 @@ class WebhookView(generic.ObjectView): queryset = Webhook.objects.all() +@register_model_view(Webhook, 'add', detail=False) @register_model_view(Webhook, 'edit') class WebhookEditView(generic.ObjectEditView): queryset = Webhook.objects.all() @@ -522,11 +560,13 @@ class WebhookDeleteView(generic.ObjectDeleteView): queryset = Webhook.objects.all() +@register_model_view(Webhook, 'bulk_import', detail=False) class WebhookBulkImportView(generic.BulkImportView): queryset = Webhook.objects.all() model_form = forms.WebhookImportForm +@register_model_view(Webhook, 'bulk_edit', path='edit', detail=False) class WebhookBulkEditView(generic.BulkEditView): queryset = Webhook.objects.all() filterset = filtersets.WebhookFilterSet @@ -534,6 +574,7 @@ class WebhookBulkEditView(generic.BulkEditView): form = forms.WebhookBulkEditForm +@register_model_view(Webhook, 'bulk_delete', path='delete', detail=False) class WebhookBulkDeleteView(generic.BulkDeleteView): queryset = Webhook.objects.all() filterset = filtersets.WebhookFilterSet @@ -544,6 +585,7 @@ class WebhookBulkDeleteView(generic.BulkDeleteView): # Event Rules # +@register_model_view(EventRule, 'list', path='', detail=False) class EventRuleListView(generic.ObjectListView): queryset = EventRule.objects.all() filterset = filtersets.EventRuleFilterSet @@ -556,6 +598,7 @@ class EventRuleView(generic.ObjectView): queryset = EventRule.objects.all() +@register_model_view(EventRule, 'add', detail=False) @register_model_view(EventRule, 'edit') class EventRuleEditView(generic.ObjectEditView): queryset = EventRule.objects.all() @@ -567,11 +610,13 @@ class EventRuleDeleteView(generic.ObjectDeleteView): queryset = EventRule.objects.all() +@register_model_view(EventRule, 'bulk_import', detail=False) class EventRuleBulkImportView(generic.BulkImportView): queryset = EventRule.objects.all() model_form = forms.EventRuleImportForm +@register_model_view(EventRule, 'bulk_edit', path='edit', detail=False) class EventRuleBulkEditView(generic.BulkEditView): queryset = EventRule.objects.all() filterset = filtersets.EventRuleFilterSet @@ -579,6 +624,7 @@ class EventRuleBulkEditView(generic.BulkEditView): form = forms.EventRuleBulkEditForm +@register_model_view(EventRule, 'bulk_delete', path='delete', detail=False) class EventRuleBulkDeleteView(generic.BulkDeleteView): queryset = EventRule.objects.all() filterset = filtersets.EventRuleFilterSet @@ -589,6 +635,7 @@ class EventRuleBulkDeleteView(generic.BulkDeleteView): # Tags # +@register_model_view(Tag, 'list', path='', detail=False) class TagListView(generic.ObjectListView): queryset = Tag.objects.annotate( items=count_related(TaggedItem, 'tag') @@ -624,6 +671,7 @@ class TagView(generic.ObjectView): } +@register_model_view(Tag, 'add', detail=False) @register_model_view(Tag, 'edit') class TagEditView(generic.ObjectEditView): queryset = Tag.objects.all() @@ -635,11 +683,13 @@ class TagDeleteView(generic.ObjectDeleteView): queryset = Tag.objects.all() +@register_model_view(Tag, 'bulk_import', detail=False) class TagBulkImportView(generic.BulkImportView): queryset = Tag.objects.all() model_form = forms.TagImportForm +@register_model_view(Tag, 'bulk_edit', path='edit', detail=False) class TagBulkEditView(generic.BulkEditView): queryset = Tag.objects.annotate( items=count_related(TaggedItem, 'tag') @@ -648,6 +698,7 @@ class TagBulkEditView(generic.BulkEditView): form = forms.TagBulkEditForm +@register_model_view(Tag, 'bulk_delete', path='delete', detail=False) class TagBulkDeleteView(generic.BulkDeleteView): queryset = Tag.objects.annotate( items=count_related(TaggedItem, 'tag') @@ -659,6 +710,7 @@ class TagBulkDeleteView(generic.BulkDeleteView): # Config contexts # +@register_model_view(ConfigContext, 'list', path='', detail=False) class ConfigContextListView(generic.ObjectListView): queryset = ConfigContext.objects.all() filterset = filtersets.ConfigContextFilterSet @@ -711,30 +763,34 @@ class ConfigContextView(generic.ObjectView): } +@register_model_view(ConfigContext, 'add', detail=False) @register_model_view(ConfigContext, 'edit') class ConfigContextEditView(generic.ObjectEditView): queryset = ConfigContext.objects.all() form = forms.ConfigContextForm -class ConfigContextBulkEditView(generic.BulkEditView): - queryset = ConfigContext.objects.all() - filterset = filtersets.ConfigContextFilterSet - table = tables.ConfigContextTable - form = forms.ConfigContextBulkEditForm - - @register_model_view(ConfigContext, 'delete') class ConfigContextDeleteView(generic.ObjectDeleteView): queryset = ConfigContext.objects.all() +@register_model_view(ConfigContext, 'bulk_edit', path='edit', detail=False) +class ConfigContextBulkEditView(generic.BulkEditView): + queryset = ConfigContext.objects.all() + filterset = filtersets.ConfigContextFilterSet + table = tables.ConfigContextTable + form = forms.ConfigContextBulkEditForm + + +@register_model_view(ConfigContext, 'bulk_delete', path='delete', detail=False) class ConfigContextBulkDeleteView(generic.BulkDeleteView): queryset = ConfigContext.objects.all() filterset = filtersets.ConfigContextFilterSet table = tables.ConfigContextTable +@register_model_view(ConfigContext, 'bulk_sync', path='sync', detail=False) class ConfigContextBulkSyncDataView(generic.BulkSyncDataView): queryset = ConfigContext.objects.all() @@ -768,6 +824,7 @@ class ObjectConfigContextView(generic.ObjectView): # Config templates # +@register_model_view(ConfigTemplate, 'list', path='', detail=False) class ConfigTemplateListView(generic.ObjectListView): queryset = ConfigTemplate.objects.annotate( device_count=count_related(Device, 'config_template'), @@ -790,6 +847,7 @@ class ConfigTemplateView(generic.ObjectView): queryset = ConfigTemplate.objects.all() +@register_model_view(ConfigTemplate, 'add', detail=False) @register_model_view(ConfigTemplate, 'edit') class ConfigTemplateEditView(generic.ObjectEditView): queryset = ConfigTemplate.objects.all() @@ -801,11 +859,13 @@ class ConfigTemplateDeleteView(generic.ObjectDeleteView): queryset = ConfigTemplate.objects.all() +@register_model_view(ConfigTemplate, 'bulk_import', detail=False) class ConfigTemplateBulkImportView(generic.BulkImportView): queryset = ConfigTemplate.objects.all() model_form = forms.ConfigTemplateImportForm +@register_model_view(ConfigTemplate, 'bulk_edit', path='edit', detail=False) class ConfigTemplateBulkEditView(generic.BulkEditView): queryset = ConfigTemplate.objects.all() filterset = filtersets.ConfigTemplateFilterSet @@ -813,12 +873,14 @@ class ConfigTemplateBulkEditView(generic.BulkEditView): form = forms.ConfigTemplateBulkEditForm +@register_model_view(ConfigTemplate, 'bulk_delete', path='delete', detail=False) class ConfigTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ConfigTemplate.objects.all() filterset = filtersets.ConfigTemplateFilterSet table = tables.ConfigTemplateTable +@register_model_view(ConfigTemplate, 'bulk_sync', path='sync', detail=False) class ConfigTemplateBulkSyncDataView(generic.BulkSyncDataView): queryset = ConfigTemplate.objects.all() @@ -827,6 +889,7 @@ class ConfigTemplateBulkSyncDataView(generic.BulkSyncDataView): # Image attachments # +@register_model_view(ImageAttachment, 'list', path='', detail=False) class ImageAttachmentListView(generic.ObjectListView): queryset = ImageAttachment.objects.all() filterset = filtersets.ImageAttachmentFilterSet @@ -837,6 +900,7 @@ class ImageAttachmentListView(generic.ObjectListView): } +@register_model_view(ImageAttachment, 'add', detail=False) @register_model_view(ImageAttachment, 'edit') class ImageAttachmentEditView(generic.ObjectEditView): queryset = ImageAttachment.objects.all() @@ -871,14 +935,15 @@ class ImageAttachmentDeleteView(generic.ObjectDeleteView): # Journal entries # +@register_model_view(JournalEntry, 'list', path='', detail=False) class JournalEntryListView(generic.ObjectListView): queryset = JournalEntry.objects.all() filterset = filtersets.JournalEntryFilterSet filterset_form = forms.JournalEntryFilterForm table = tables.JournalEntryTable actions = { - 'import': {'add'}, 'export': {'view'}, + 'bulk_import': {'add'}, 'bulk_edit': {'change'}, 'bulk_delete': {'delete'}, } @@ -889,6 +954,7 @@ class JournalEntryView(generic.ObjectView): queryset = JournalEntry.objects.all() +@register_model_view(JournalEntry, 'add', detail=False) @register_model_view(JournalEntry, 'edit') class JournalEntryEditView(generic.ObjectEditView): queryset = JournalEntry.objects.all() @@ -917,6 +983,13 @@ class JournalEntryDeleteView(generic.ObjectDeleteView): return reverse(viewname, kwargs={'pk': obj.pk}) +@register_model_view(JournalEntry, 'bulk_import', detail=False) +class JournalEntryBulkImportView(generic.BulkImportView): + queryset = JournalEntry.objects.all() + model_form = forms.JournalEntryImportForm + + +@register_model_view(JournalEntry, 'bulk_edit', path='edit', detail=False) class JournalEntryBulkEditView(generic.BulkEditView): queryset = JournalEntry.objects.all() filterset = filtersets.JournalEntryFilterSet @@ -924,17 +997,13 @@ class JournalEntryBulkEditView(generic.BulkEditView): form = forms.JournalEntryBulkEditForm +@register_model_view(JournalEntry, 'bulk_delete', path='delete', detail=False) class JournalEntryBulkDeleteView(generic.BulkDeleteView): queryset = JournalEntry.objects.all() filterset = filtersets.JournalEntryFilterSet table = tables.JournalEntryTable -class JournalEntryBulkImportView(generic.BulkImportView): - queryset = JournalEntry.objects.all() - model_form = forms.JournalEntryImportForm - - # # Dashboard & widgets # @@ -1141,12 +1210,14 @@ class ScriptView(BaseScriptView): script_class = self._get_script_class(script) if not script_class: return render(request, 'extras/script.html', { + 'object': script, 'script': script, }) form = script_class.as_form(initial=normalize_querydict(request.GET)) return render(request, 'extras/script.html', { + 'object': script, 'script': script, 'script_class': script_class, 'form': form, @@ -1162,6 +1233,7 @@ class ScriptView(BaseScriptView): script_class = self._get_script_class(script) if not script_class: return render(request, 'extras/script.html', { + 'object': script, 'script': script, }) @@ -1180,12 +1252,13 @@ class ScriptView(BaseScriptView): data=form.cleaned_data, request=copy_safe_request(request), job_timeout=script.python_class.job_timeout, - commit=form.cleaned_data.pop('_commit') + commit=form.cleaned_data.pop('_commit'), ) return redirect('extras:script_result', job_pk=job.pk) return render(request, 'extras/script.html', { + 'object': script, 'script': script, 'script_class': script.python_class(), 'form': form, diff --git a/netbox/ipam/api/nested_serializers.py b/netbox/ipam/api/nested_serializers.py deleted file mode 100644 index 8b10f29df..000000000 --- a/netbox/ipam/api/nested_serializers.py +++ /dev/null @@ -1,204 +0,0 @@ -import warnings - -from drf_spectacular.utils import extend_schema_serializer -from rest_framework import serializers - -from ipam import models -from netbox.api.fields import RelatedObjectCountField -from netbox.api.serializers import WritableNestedSerializer -from .field_serializers import IPAddressField -from .serializers_.nested import NestedIPAddressSerializer - -__all__ = [ - 'NestedAggregateSerializer', - 'NestedASNSerializer', - 'NestedASNRangeSerializer', - 'NestedFHRPGroupSerializer', - 'NestedFHRPGroupAssignmentSerializer', - 'NestedIPAddressSerializer', - 'NestedIPRangeSerializer', - 'NestedPrefixSerializer', - 'NestedRIRSerializer', - 'NestedRoleSerializer', - 'NestedRouteTargetSerializer', - 'NestedServiceSerializer', - 'NestedServiceTemplateSerializer', - 'NestedVLANGroupSerializer', - 'NestedVLANSerializer', - 'NestedVRFSerializer', -] - -# TODO: Remove in v4.2 -warnings.warn( - "Dedicated nested serializers will be removed in NetBox v4.2. Use Serializer(nested=True) instead.", - DeprecationWarning -) - - -# -# ASN ranges -# - -class NestedASNRangeSerializer(WritableNestedSerializer): - - class Meta: - model = models.ASNRange - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -# -# ASNs -# - -class NestedASNSerializer(WritableNestedSerializer): - - class Meta: - model = models.ASN - fields = ['id', 'url', 'display_url', 'display', 'asn'] - - -# -# VRFs -# - -@extend_schema_serializer( - exclude_fields=('prefix_count',), -) -class NestedVRFSerializer(WritableNestedSerializer): - prefix_count = RelatedObjectCountField('prefixes') - - class Meta: - model = models.VRF - fields = ['id', 'url', 'display_url', 'display', 'name', 'rd', 'prefix_count'] - - -# -# Route targets -# - -class NestedRouteTargetSerializer(WritableNestedSerializer): - - class Meta: - model = models.RouteTarget - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -# -# RIRs/aggregates -# - -@extend_schema_serializer( - exclude_fields=('aggregate_count',), -) -class NestedRIRSerializer(WritableNestedSerializer): - aggregate_count = RelatedObjectCountField('aggregates') - - class Meta: - model = models.RIR - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'aggregate_count'] - - -class NestedAggregateSerializer(WritableNestedSerializer): - family = serializers.IntegerField(read_only=True) - - class Meta: - model = models.Aggregate - fields = ['id', 'url', 'display_url', 'display', 'family', 'prefix'] - - -# -# FHRP groups -# - -class NestedFHRPGroupSerializer(WritableNestedSerializer): - - class Meta: - model = models.FHRPGroup - fields = ['id', 'url', 'display_url', 'display', 'protocol', 'group_id'] - - -class NestedFHRPGroupAssignmentSerializer(WritableNestedSerializer): - group = NestedFHRPGroupSerializer() - - class Meta: - model = models.FHRPGroupAssignment - fields = ['id', 'url', 'display_url', 'display', 'group', 'interface_type', 'interface_id', 'priority'] - - -# -# VLANs -# - -@extend_schema_serializer( - exclude_fields=('prefix_count', 'vlan_count'), -) -class NestedRoleSerializer(WritableNestedSerializer): - prefix_count = RelatedObjectCountField('prefixes') - vlan_count = RelatedObjectCountField('vlans') - - class Meta: - model = models.Role - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'prefix_count', 'vlan_count'] - - -@extend_schema_serializer( - exclude_fields=('vlan_count',), -) -class NestedVLANGroupSerializer(WritableNestedSerializer): - vlan_count = RelatedObjectCountField('vlans') - - class Meta: - model = models.VLANGroup - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'vlan_count'] - - -class NestedVLANSerializer(WritableNestedSerializer): - - class Meta: - model = models.VLAN - fields = ['id', 'url', 'display_url', 'display', 'vid', 'name'] - - -# -# Prefixes -# - -class NestedPrefixSerializer(WritableNestedSerializer): - family = serializers.IntegerField(read_only=True) - _depth = serializers.IntegerField(read_only=True) - - class Meta: - model = models.Prefix - fields = ['id', 'url', 'display_url', 'display', 'family', 'prefix', '_depth'] - - -# -# IP ranges -# - -class NestedIPRangeSerializer(WritableNestedSerializer): - family = serializers.IntegerField(read_only=True) - start_address = IPAddressField() - end_address = IPAddressField() - - class Meta: - model = models.IPRange - fields = ['id', 'url', 'display_url', 'display', 'family', 'start_address', 'end_address'] - - -# -# Services -# - -class NestedServiceTemplateSerializer(WritableNestedSerializer): - - class Meta: - model = models.ServiceTemplate - fields = ['id', 'url', 'display_url', 'display', 'name', 'protocol', 'ports'] - - -class NestedServiceSerializer(WritableNestedSerializer): - - class Meta: - model = models.Service - fields = ['id', 'url', 'display_url', 'display', 'name', 'protocol', 'ports'] diff --git a/netbox/ipam/api/serializers_/ip.py b/netbox/ipam/api/serializers_/ip.py index 535ffcec1..bfc7ac546 100644 --- a/netbox/ipam/api/serializers_/ip.py +++ b/netbox/ipam/api/serializers_/ip.py @@ -2,7 +2,7 @@ from django.contrib.contenttypes.models import ContentType from drf_spectacular.utils import extend_schema_field from rest_framework import serializers -from dcim.api.serializers_.sites import SiteSerializer +from dcim.constants import LOCATION_SCOPE_TYPES from ipam.choices import * from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS from ipam.models import Aggregate, IPAddress, IPRange, Prefix @@ -45,8 +45,17 @@ class AggregateSerializer(NetBoxModelSerializer): class PrefixSerializer(NetBoxModelSerializer): family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True) - site = SiteSerializer(nested=True, required=False, allow_null=True) vrf = VRFSerializer(nested=True, required=False, allow_null=True) + scope_type = ContentTypeField( + queryset=ContentType.objects.filter( + model__in=LOCATION_SCOPE_TYPES + ), + allow_null=True, + required=False, + default=None + ) + scope_id = serializers.IntegerField(allow_null=True, required=False, default=None) + scope = serializers.SerializerMethodField(read_only=True) tenant = TenantSerializer(nested=True, required=False, allow_null=True) vlan = VLANSerializer(nested=True, required=False, allow_null=True) status = ChoiceField(choices=PrefixStatusChoices, required=False) @@ -58,12 +67,20 @@ class PrefixSerializer(NetBoxModelSerializer): class Meta: model = Prefix fields = [ - 'id', 'url', 'display_url', 'display', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', - 'role', 'is_pool', 'mark_utilized', 'description', 'comments', 'tags', 'custom_fields', - 'created', 'last_updated', 'children', '_depth', + 'id', 'url', 'display_url', 'display', 'family', 'prefix', 'vrf', 'scope_type', 'scope_id', 'scope', + 'tenant', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'description', 'comments', 'tags', + 'custom_fields', 'created', 'last_updated', 'children', '_depth', ] brief_fields = ('id', 'url', 'display', 'family', 'prefix', 'description', '_depth') + @extend_schema_field(serializers.JSONField(allow_null=True)) + def get_scope(self, obj): + if obj.scope_id is None: + return None + serializer = get_serializer_for_model(obj.scope) + context = {'request': self.context['request']} + return serializer(obj.scope, nested=True, context=context).data + class PrefixLengthSerializer(serializers.Serializer): diff --git a/netbox/ipam/api/serializers_/nested.py b/netbox/ipam/api/serializers_/nested.py index 5297565bb..b56b15984 100644 --- a/netbox/ipam/api/serializers_/nested.py +++ b/netbox/ipam/api/serializers_/nested.py @@ -6,6 +6,7 @@ from ..field_serializers import IPAddressField __all__ = ( 'NestedIPAddressSerializer', + 'NestedVLANSerializer', ) @@ -16,3 +17,10 @@ class NestedIPAddressSerializer(WritableNestedSerializer): class Meta: model = models.IPAddress fields = ['id', 'url', 'display_url', 'display', 'family', 'address'] + + +class NestedVLANSerializer(WritableNestedSerializer): + + class Meta: + model = models.VLAN + fields = ['id', 'url', 'display', 'vid', 'name', 'description'] diff --git a/netbox/ipam/api/serializers_/vlans.py b/netbox/ipam/api/serializers_/vlans.py index 608fcf0b4..9b5501dc5 100644 --- a/netbox/ipam/api/serializers_/vlans.py +++ b/netbox/ipam/api/serializers_/vlans.py @@ -5,12 +5,13 @@ from rest_framework import serializers from dcim.api.serializers_.sites import SiteSerializer from ipam.choices import * from ipam.constants import VLANGROUP_SCOPE_TYPES -from ipam.models import VLAN, VLANGroup +from ipam.models import VLAN, VLANGroup, VLANTranslationPolicy, VLANTranslationRule from netbox.api.fields import ChoiceField, ContentTypeField, IntegerRangeSerializer, RelatedObjectCountField from netbox.api.serializers import NetBoxModelSerializer from tenancy.api.serializers_.tenants import TenantSerializer from utilities.api import get_serializer_for_model from vpn.api.serializers_.l2vpn import L2VPNTerminationSerializer +from .nested import NestedVLANSerializer from .roles import RoleSerializer __all__ = ( @@ -18,6 +19,8 @@ __all__ = ( 'CreateAvailableVLANSerializer', 'VLANGroupSerializer', 'VLANSerializer', + 'VLANTranslationPolicySerializer', + 'VLANTranslationRuleSerializer', ) @@ -62,6 +65,8 @@ class VLANSerializer(NetBoxModelSerializer): tenant = TenantSerializer(nested=True, required=False, allow_null=True) status = ChoiceField(choices=VLANStatusChoices, required=False) role = RoleSerializer(nested=True, required=False, allow_null=True) + qinq_role = ChoiceField(choices=VLANQinQRoleChoices, required=False) + qinq_svlan = NestedVLANSerializer(required=False, allow_null=True, default=None) l2vpn_termination = L2VPNTerminationSerializer(nested=True, read_only=True, allow_null=True) # Related object counts @@ -71,8 +76,8 @@ class VLANSerializer(NetBoxModelSerializer): model = VLAN fields = [ 'id', 'url', 'display_url', 'display', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', - 'description', 'comments', 'l2vpn_termination', 'tags', 'custom_fields', 'created', 'last_updated', - 'prefix_count', + 'description', 'qinq_role', 'qinq_svlan', 'comments', 'l2vpn_termination', 'tags', 'custom_fields', + 'created', 'last_updated', 'prefix_count', ] brief_fields = ('id', 'url', 'display', 'vid', 'name', 'description') @@ -110,3 +115,19 @@ class CreateAvailableVLANSerializer(NetBoxModelSerializer): def validate(self, data): # Bypass model validation since we don't have a VID yet return data + + +class VLANTranslationRuleSerializer(NetBoxModelSerializer): + + class Meta: + model = VLANTranslationRule + fields = ['id', 'url', 'display', 'policy', 'local_vid', 'remote_vid', 'description'] + + +class VLANTranslationPolicySerializer(NetBoxModelSerializer): + rules = VLANTranslationRuleSerializer(many=True, read_only=True) + + class Meta: + model = VLANTranslationPolicy + fields = ['id', 'url', 'display', 'name', 'description', 'display', 'rules'] + brief_fields = ('id', 'url', 'display', 'name', 'description') diff --git a/netbox/ipam/api/urls.py b/netbox/ipam/api/urls.py index bae9d8048..ea76025ec 100644 --- a/netbox/ipam/api/urls.py +++ b/netbox/ipam/api/urls.py @@ -21,6 +21,8 @@ router.register('fhrp-groups', views.FHRPGroupViewSet) router.register('fhrp-group-assignments', views.FHRPGroupAssignmentViewSet) router.register('vlan-groups', views.VLANGroupViewSet) router.register('vlans', views.VLANViewSet) +router.register('vlan-translation-policies', views.VLANTranslationPolicyViewSet) +router.register('vlan-translation-rules', views.VLANTranslationRuleViewSet) router.register('service-templates', views.ServiceTemplateViewSet) router.register('services', views.ServiceViewSet) diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index ffd4d5b7d..783d13523 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -143,6 +143,18 @@ class VLANViewSet(NetBoxModelViewSet): filterset_class = filtersets.VLANFilterSet +class VLANTranslationPolicyViewSet(NetBoxModelViewSet): + queryset = VLANTranslationPolicy.objects.all() + serializer_class = serializers.VLANTranslationPolicySerializer + filterset_class = filtersets.VLANTranslationPolicyFilterSet + + +class VLANTranslationRuleViewSet(NetBoxModelViewSet): + queryset = VLANTranslationRule.objects.all() + serializer_class = serializers.VLANTranslationRuleSerializer + filterset_class = filtersets.VLANTranslationRuleFilterSet + + class ServiceTemplateViewSet(NetBoxModelViewSet): queryset = ServiceTemplate.objects.all() serializer_class = serializers.ServiceTemplateSerializer diff --git a/netbox/ipam/apps.py b/netbox/ipam/apps.py index c118d5464..ae88d69a9 100644 --- a/netbox/ipam/apps.py +++ b/netbox/ipam/apps.py @@ -1,5 +1,7 @@ from django.apps import AppConfig +from netbox import denormalized + class IPAMConfig(AppConfig): name = "ipam" @@ -8,6 +10,16 @@ class IPAMConfig(AppConfig): def ready(self): from netbox.models.features import register_models from . import signals, search # noqa: F401 + from .models import Prefix # Register models register_models(*self.get_models()) + + # Register denormalized fields + denormalized.register(Prefix, '_site', { + '_region': 'region', + '_site_group': 'group', + }) + denormalized.register(Prefix, '_location', { + '_site': 'site', + }) diff --git a/netbox/ipam/choices.py b/netbox/ipam/choices.py index 017fd0430..51b65a6da 100644 --- a/netbox/ipam/choices.py +++ b/netbox/ipam/choices.py @@ -157,6 +157,17 @@ class VLANStatusChoices(ChoiceSet): ] +class VLANQinQRoleChoices(ChoiceSet): + + ROLE_SERVICE = 'svlan' + ROLE_CUSTOMER = 'cvlan' + + CHOICES = [ + (ROLE_SERVICE, _('Service'), 'blue'), + (ROLE_CUSTOMER, _('Customer'), 'orange'), + ] + + # # Services # diff --git a/netbox/ipam/fields.py b/netbox/ipam/fields.py index 20341005d..a82976326 100644 --- a/netbox/ipam/fields.py +++ b/netbox/ipam/fields.py @@ -105,6 +105,8 @@ IPAddressField.register_lookup(lookups.NetIn) IPAddressField.register_lookup(lookups.NetHostContained) IPAddressField.register_lookup(lookups.NetFamily) IPAddressField.register_lookup(lookups.NetMaskLength) +IPAddressField.register_lookup(lookups.Host) +IPAddressField.register_lookup(lookups.Inet) class ASNField(models.BigIntegerField): diff --git a/netbox/ipam/filtersets.py b/netbox/ipam/filtersets.py index 894219c64..81cbd2ef8 100644 --- a/netbox/ipam/filtersets.py +++ b/netbox/ipam/filtersets.py @@ -1,5 +1,6 @@ import django_filters import netaddr +from dcim.base_filtersets import ScopedFilterSet from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError from django.db.models import Q @@ -37,6 +38,8 @@ __all__ = ( 'ServiceTemplateFilterSet', 'VLANFilterSet', 'VLANGroupFilterSet', + 'VLANTranslationPolicyFilterSet', + 'VLANTranslationRuleFilterSet', 'VRFFilterSet', ) @@ -211,8 +214,10 @@ class ASNRangeFilterSet(OrganizationalModelFilterSet, TenancyFilterSet): def search(self, queryset, name, value): if not value.strip(): return queryset - qs_filter = Q(description__icontains=value) - return queryset.filter(qs_filter) + return queryset.filter( + Q(name__icontains=value) | + Q(description__icontains=value) + ) class ASNFilterSet(OrganizationalModelFilterSet, TenancyFilterSet): @@ -271,7 +276,7 @@ class RoleFilterSet(OrganizationalModelFilterSet): fields = ('id', 'name', 'slug', 'description', 'weight') -class PrefixFilterSet(NetBoxModelFilterSet, TenancyFilterSet): +class PrefixFilterSet(NetBoxModelFilterSet, ScopedFilterSet, TenancyFilterSet): family = django_filters.NumberFilter( field_name='prefix', lookup_expr='family' @@ -332,42 +337,6 @@ class PrefixFilterSet(NetBoxModelFilterSet, TenancyFilterSet): to_field_name='rd', label=_('VRF (RD)'), ) - region_id = TreeNodeMultipleChoiceFilter( - queryset=Region.objects.all(), - field_name='site__region', - lookup_expr='in', - label=_('Region (ID)'), - ) - region = TreeNodeMultipleChoiceFilter( - queryset=Region.objects.all(), - field_name='site__region', - lookup_expr='in', - to_field_name='slug', - label=_('Region (slug)'), - ) - site_group_id = TreeNodeMultipleChoiceFilter( - queryset=SiteGroup.objects.all(), - field_name='site__group', - lookup_expr='in', - label=_('Site group (ID)'), - ) - site_group = TreeNodeMultipleChoiceFilter( - queryset=SiteGroup.objects.all(), - field_name='site__group', - lookup_expr='in', - to_field_name='slug', - label=_('Site group (slug)'), - ) - site_id = django_filters.ModelMultipleChoiceFilter( - queryset=Site.objects.all(), - label=_('Site (ID)'), - ) - site = django_filters.ModelMultipleChoiceFilter( - field_name='site__slug', - queryset=Site.objects.all(), - to_field_name='slug', - label=_('Site (slug)'), - ) vlan_id = django_filters.ModelMultipleChoiceFilter( queryset=VLAN.objects.all(), label=_('VLAN (ID)'), @@ -393,7 +362,7 @@ class PrefixFilterSet(NetBoxModelFilterSet, TenancyFilterSet): class Meta: model = Prefix - fields = ('id', 'is_pool', 'mark_utilized', 'description') + fields = ('id', 'scope_id', 'is_pool', 'mark_utilized', 'description') def search(self, queryset, name, value): if not value.strip(): @@ -1024,6 +993,17 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet): queryset=VirtualMachine.objects.all(), method='get_for_virtualmachine' ) + qinq_role = django_filters.MultipleChoiceFilter( + choices=VLANQinQRoleChoices + ) + qinq_svlan_id = django_filters.ModelMultipleChoiceFilter( + queryset=VLAN.objects.all(), + label=_('Q-in-Q SVLAN (ID)'), + ) + qinq_svlan_vid = MultiValueNumberFilter( + field_name='qinq_svlan__vid', + label=_('Q-in-Q SVLAN number (1-4094)'), + ) l2vpn_id = django_filters.ModelMultipleChoiceFilter( field_name='l2vpn_terminations__l2vpn', queryset=L2VPN.objects.all(), @@ -1078,7 +1058,7 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet): return queryset.filter( Q(interfaces_as_tagged=value) | Q(interfaces_as_untagged=value) - ) + ).distinct() def filter_vminterface_id(self, queryset, name, value): if value is None: @@ -1086,7 +1066,54 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet): return queryset.filter( Q(vminterfaces_as_tagged=value) | Q(vminterfaces_as_untagged=value) + ).distinct() + + +class VLANTranslationPolicyFilterSet(NetBoxModelFilterSet): + + class Meta: + model = VLANTranslationPolicy + fields = ('id', 'name', 'description') + + def search(self, queryset, name, value): + if not value.strip(): + return queryset + qs_filter = ( + Q(name__icontains=value) | + Q(description__icontains=value) ) + return queryset.filter(qs_filter) + + +class VLANTranslationRuleFilterSet(NetBoxModelFilterSet): + policy_id = django_filters.ModelMultipleChoiceFilter( + queryset=VLANTranslationPolicy.objects.all(), + label=_('VLAN Translation Policy (ID)'), + ) + policy = django_filters.ModelMultipleChoiceFilter( + field_name='policy__name', + queryset=VLANTranslationPolicy.objects.all(), + to_field_name='name', + label=_('VLAN Translation Policy (name)'), + ) + + class Meta: + model = VLANTranslationRule + fields = ('id', 'policy_id', 'policy', 'local_vid', 'remote_vid', 'description') + + def search(self, queryset, name, value): + if not value.strip(): + return queryset + qs_filter = ( + Q(policy__name__icontains=value) + ) + try: + int_value = int(value.strip()) + qs_filter |= Q(local_vid=int_value) + qs_filter |= Q(remote_vid=int_value) + except ValueError: + pass + return queryset.filter(qs_filter) class ServiceTemplateFilterSet(NetBoxModelFilterSet): diff --git a/netbox/ipam/forms/bulk_edit.py b/netbox/ipam/forms/bulk_edit.py index f4a7eabb7..7f3216cfd 100644 --- a/netbox/ipam/forms/bulk_edit.py +++ b/netbox/ipam/forms/bulk_edit.py @@ -1,22 +1,24 @@ from django import forms from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ObjectDoesNotExist from django.utils.translation import gettext_lazy as _ -from dcim.models import Location, Rack, Region, Site, SiteGroup +from dcim.forms.mixins import ScopedBulkEditForm +from dcim.models import Region, Site, SiteGroup from ipam.choices import * from ipam.constants import * from ipam.models import * from ipam.models import ASN from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant -from utilities.forms import add_blank_choice +from utilities.forms import add_blank_choice, get_field_value from utilities.forms.fields import ( CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField, NumericRangeArrayField, ) from utilities.forms.rendering import FieldSet -from utilities.forms.widgets import BulkEditNullBooleanSelect -from virtualization.models import Cluster, ClusterGroup +from utilities.forms.widgets import BulkEditNullBooleanSelect, HTMXSelect +from utilities.templatetags.builtins.filters import bettertitle __all__ = ( 'AggregateBulkEditForm', @@ -33,6 +35,8 @@ __all__ = ( 'ServiceTemplateBulkEditForm', 'VLANBulkEditForm', 'VLANGroupBulkEditForm', + 'VLANTranslationPolicyBulkEditForm', + 'VLANTranslationRuleBulkEditForm', 'VRFBulkEditForm', ) @@ -202,26 +206,7 @@ class RoleBulkEditForm(NetBoxModelBulkEditForm): nullable_fields = ('description',) -class PrefixBulkEditForm(NetBoxModelBulkEditForm): - region = DynamicModelChoiceField( - label=_('Region'), - queryset=Region.objects.all(), - required=False - ) - site_group = DynamicModelChoiceField( - label=_('Site group'), - queryset=SiteGroup.objects.all(), - required=False - ) - site = DynamicModelChoiceField( - label=_('Site'), - queryset=Site.objects.all(), - required=False, - query_params={ - 'region_id': '$region', - 'group_id': '$site_group', - } - ) +class PrefixBulkEditForm(ScopedBulkEditForm, NetBoxModelBulkEditForm): vlan_group = DynamicModelChoiceField( queryset=VLANGroup.objects.all(), required=False, @@ -281,12 +266,12 @@ class PrefixBulkEditForm(NetBoxModelBulkEditForm): model = Prefix fieldsets = ( FieldSet('tenant', 'status', 'role', 'description'), - FieldSet('region', 'site_group', 'site', name=_('Site')), FieldSet('vrf', 'prefix_length', 'is_pool', 'mark_utilized', name=_('Addressing')), + FieldSet('scope_type', 'scope', name=_('Scope')), FieldSet('vlan_group', 'vlan', name=_('VLAN Assignment')), ) nullable_fields = ( - 'site', 'vlan', 'vrf', 'tenant', 'role', 'description', 'comments', + 'vlan', 'vrf', 'tenant', 'role', 'scope', 'description', 'comments', ) @@ -429,62 +414,17 @@ class VLANGroupBulkEditForm(NetBoxModelBulkEditForm): required=False ) scope_type = ContentTypeChoiceField( - label=_('Scope type'), queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES), - required=False - ) - scope_id = forms.IntegerField( + widget=HTMXSelect(method='post', attrs={'hx-select': '#form_fields'}), required=False, - widget=forms.HiddenInput() + label=_('Scope type') ) - region = DynamicModelChoiceField( - label=_('Region'), - queryset=Region.objects.all(), - required=False - ) - sitegroup = DynamicModelChoiceField( - queryset=SiteGroup.objects.all(), + scope = DynamicModelChoiceField( + label=_('Scope'), + queryset=Site.objects.none(), # Initial queryset required=False, - label=_('Site group') - ) - site = DynamicModelChoiceField( - label=_('Site'), - queryset=Site.objects.all(), - required=False, - query_params={ - 'region_id': '$region', - 'group_id': '$sitegroup', - } - ) - location = DynamicModelChoiceField( - label=_('Location'), - queryset=Location.objects.all(), - required=False, - query_params={ - 'site_id': '$site', - } - ) - rack = DynamicModelChoiceField( - label=_('Rack'), - queryset=Rack.objects.all(), - required=False, - query_params={ - 'site_id': '$site', - 'location_id': '$location', - } - ) - clustergroup = DynamicModelChoiceField( - queryset=ClusterGroup.objects.all(), - required=False, - label=_('Cluster group') - ) - cluster = DynamicModelChoiceField( - label=_('Cluster'), - queryset=Cluster.objects.all(), - required=False, - query_params={ - 'group_id': '$clustergroup', - } + disabled=True, + selector=True ) vid_ranges = NumericRangeArrayField( label=_('VLAN ID ranges'), @@ -494,24 +434,23 @@ class VLANGroupBulkEditForm(NetBoxModelBulkEditForm): model = VLANGroup fieldsets = ( FieldSet('site', 'vid_ranges', 'description'), - FieldSet( - 'scope_type', 'region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster', name=_('Scope') - ), + FieldSet('scope_type', 'scope', name=_('Scope')), ) - nullable_fields = ('description',) + nullable_fields = ('description', 'scope') - def clean(self): - super().clean() + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) - # Assign scope based on scope_type - if self.cleaned_data.get('scope_type'): - scope_field = self.cleaned_data['scope_type'].model - if scope_obj := self.cleaned_data.get(scope_field): - self.cleaned_data['scope_id'] = scope_obj.pk - self.changed_data.append('scope_id') - else: - self.cleaned_data.pop('scope_type') - self.changed_data.remove('scope_type') + if scope_type_id := get_field_value(self, 'scope_type'): + try: + scope_type = ContentType.objects.get(pk=scope_type_id) + model = scope_type.model_class() + self.fields['scope'].queryset = model.objects.all() + self.fields['scope'].widget.attrs['selector'] = model._meta.label_lower + self.fields['scope'].disabled = False + self.fields['scope'].label = _(bettertitle(model._meta.verbose_name)) + except ObjectDoesNotExist: + pass class VLANBulkEditForm(NetBoxModelBulkEditForm): @@ -562,18 +501,62 @@ class VLANBulkEditForm(NetBoxModelBulkEditForm): max_length=200, required=False ) + qinq_role = forms.ChoiceField( + label=_('Q-in-Q role'), + choices=add_blank_choice(VLANQinQRoleChoices), + required=False + ) + qinq_svlan = DynamicModelChoiceField( + label=_('Q-in-Q SVLAN'), + queryset=VLAN.objects.all(), + required=False, + query_params={ + 'qinq_role': VLANQinQRoleChoices.ROLE_SERVICE, + } + ) comments = CommentField() model = VLAN fieldsets = ( FieldSet('status', 'role', 'tenant', 'description'), + FieldSet('qinq_role', 'qinq_svlan', name=_('Q-in-Q')), FieldSet('region', 'site_group', 'site', 'group', name=_('Site & Group')), ) nullable_fields = ( - 'site', 'group', 'tenant', 'role', 'description', 'comments', + 'site', 'group', 'tenant', 'role', 'description', 'qinq_role', 'qinq_svlan', 'comments', ) +class VLANTranslationPolicyBulkEditForm(NetBoxModelBulkEditForm): + description = forms.CharField( + label=_('Description'), + max_length=200, + required=False + ) + + model = VLANTranslationPolicy + fieldsets = ( + FieldSet('description'), + ) + nullable_fields = ('description',) + + +class VLANTranslationRuleBulkEditForm(NetBoxModelBulkEditForm): + policy = DynamicModelChoiceField( + label=_('Policy'), + queryset=VLANTranslationPolicy.objects.all(), + selector=True + ) + local_vid = forms.IntegerField(required=False) + remote_vid = forms.IntegerField(required=False) + + model = VLANTranslationRule + fieldsets = ( + FieldSet('policy', 'local_vid', 'remote_vid'), + ) + fields = ('policy', 'local_vid', 'remote_vid') + + class ServiceTemplateBulkEditForm(NetBoxModelBulkEditForm): protocol = forms.ChoiceField( label=_('Protocol'), diff --git a/netbox/ipam/forms/bulk_import.py b/netbox/ipam/forms/bulk_import.py index dea250c79..c1f2dedd7 100644 --- a/netbox/ipam/forms/bulk_import.py +++ b/netbox/ipam/forms/bulk_import.py @@ -3,6 +3,7 @@ from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext_lazy as _ from dcim.models import Device, Interface, Site +from dcim.forms.mixins import ScopedImportForm from ipam.choices import * from ipam.constants import * from ipam.models import * @@ -29,6 +30,8 @@ __all__ = ( 'ServiceTemplateImportForm', 'VLANImportForm', 'VLANGroupImportForm', + 'VLANTranslationPolicyImportForm', + 'VLANTranslationRuleImportForm', 'VRFImportForm', ) @@ -152,7 +155,7 @@ class RoleImportForm(NetBoxModelImportForm): fields = ('name', 'slug', 'weight', 'description', 'tags') -class PrefixImportForm(NetBoxModelImportForm): +class PrefixImportForm(ScopedImportForm, NetBoxModelImportForm): vrf = CSVModelChoiceField( label=_('VRF'), queryset=VRF.objects.all(), @@ -167,13 +170,6 @@ class PrefixImportForm(NetBoxModelImportForm): to_field_name='name', help_text=_('Assigned tenant') ) - site = CSVModelChoiceField( - label=_('Site'), - queryset=Site.objects.all(), - required=False, - to_field_name='name', - help_text=_('Assigned site') - ) vlan_group = CSVModelChoiceField( label=_('VLAN group'), queryset=VLANGroup.objects.all(), @@ -204,9 +200,12 @@ class PrefixImportForm(NetBoxModelImportForm): class Meta: model = Prefix fields = ( - 'prefix', 'vrf', 'tenant', 'site', 'vlan_group', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', - 'description', 'comments', 'tags', + 'prefix', 'vrf', 'tenant', 'vlan_group', 'vlan', 'status', 'role', 'scope_type', 'scope_id', 'is_pool', + 'mark_utilized', 'description', 'comments', 'tags', ) + labels = { + 'scope_id': _('Scope ID'), + } def __init__(self, data=None, *args, **kwargs): super().__init__(data, *args, **kwargs) @@ -326,12 +325,17 @@ class IPAddressImportForm(NetBoxModelImportForm): help_text=_('Make this the primary IP for the assigned device'), required=False ) + is_oob = forms.BooleanField( + label=_('Is out-of-band'), + help_text=_('Designate this as the out-of-band IP address for the assigned device'), + required=False + ) class Meta: model = IPAddress fields = [ 'address', 'vrf', 'tenant', 'status', 'role', 'device', 'virtual_machine', 'interface', 'is_primary', - 'dns_name', 'description', 'comments', 'tags', + 'is_oob', 'dns_name', 'description', 'comments', 'tags', ] def __init__(self, data=None, *args, **kwargs): @@ -345,7 +349,7 @@ class IPAddressImportForm(NetBoxModelImportForm): **{f"device__{self.fields['device'].to_field_name}": data['device']} ) - # Limit interface queryset by assigned device + # Limit interface queryset by assigned VM elif data.get('virtual_machine'): self.fields['interface'].queryset = VMInterface.objects.filter( **{f"virtual_machine__{self.fields['virtual_machine'].to_field_name}": data['virtual_machine']} @@ -358,16 +362,29 @@ class IPAddressImportForm(NetBoxModelImportForm): virtual_machine = self.cleaned_data.get('virtual_machine') interface = self.cleaned_data.get('interface') is_primary = self.cleaned_data.get('is_primary') + is_oob = self.cleaned_data.get('is_oob') - # Validate is_primary + # Validate is_primary and is_oob if is_primary and not device and not virtual_machine: raise forms.ValidationError({ "is_primary": _("No device or virtual machine specified; cannot set as primary IP") }) + if is_oob and not device: + raise forms.ValidationError({ + "is_oob": _("No device specified; cannot set as out-of-band IP") + }) + if is_oob and virtual_machine: + raise forms.ValidationError({ + "is_oob": _("Cannot set out-of-band IP for virtual machines") + }) if is_primary and not interface: raise forms.ValidationError({ "is_primary": _("No interface specified; cannot set as primary IP") }) + if is_oob and not interface: + raise forms.ValidationError({ + "is_oob": _("No interface specified; cannot set as out-of-band IP") + }) def save(self, *args, **kwargs): @@ -386,6 +403,12 @@ class IPAddressImportForm(NetBoxModelImportForm): parent.primary_ip6 = ipaddress parent.save() + # Set as OOB for device + if self.cleaned_data.get('is_oob'): + parent = self.cleaned_data.get('device') + parent.oob_ip = ipaddress + parent.save() + return ipaddress @@ -458,10 +481,46 @@ class VLANImportForm(NetBoxModelImportForm): to_field_name='name', help_text=_('Functional role') ) + qinq_role = CSVChoiceField( + label=_('Q-in-Q role'), + choices=VLANQinQRoleChoices, + required=False, + help_text=_('Operational status') + ) + qinq_svlan = CSVModelChoiceField( + label=_('Q-in-Q SVLAN'), + queryset=VLAN.objects.all(), + required=False, + to_field_name='vid', + help_text=_("Service VLAN (for Q-in-Q/802.1ad customer VLANs)") + ) class Meta: model = VLAN - fields = ('site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'comments', 'tags') + fields = ( + 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'qinq_role', 'qinq_svlan', + 'comments', 'tags', + ) + + +class VLANTranslationPolicyImportForm(NetBoxModelImportForm): + + class Meta: + model = VLANTranslationPolicy + fields = ('name', 'description', 'tags') + + +class VLANTranslationRuleImportForm(NetBoxModelImportForm): + policy = CSVModelChoiceField( + label=_('Policy'), + queryset=VLANTranslationPolicy.objects.all(), + to_field_name='name', + help_text=_('VLAN translation policy') + ) + + class Meta: + model = VLANTranslationRule + fields = ('policy', 'local_vid', 'remote_vid') class ServiceTemplateImportForm(NetBoxModelImportForm): diff --git a/netbox/ipam/forms/filtersets.py b/netbox/ipam/forms/filtersets.py index a32694321..3f951512b 100644 --- a/netbox/ipam/forms/filtersets.py +++ b/netbox/ipam/forms/filtersets.py @@ -28,6 +28,8 @@ __all__ = ( 'ServiceTemplateFilterForm', 'VLANFilterForm', 'VLANGroupFilterForm', + 'VLANTranslationPolicyFilterForm', + 'VLANTranslationRuleFilterForm', 'VRFFilterForm', ) @@ -170,7 +172,7 @@ class PrefixFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): ), FieldSet('vlan_id', name=_('VLAN Assignment')), FieldSet('vrf_id', 'present_in_vrf_id', name=_('VRF')), - FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), + FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Scope')), FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) mask_length__lte = forms.IntegerField( @@ -224,12 +226,13 @@ class PrefixFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, - null_option='None', - query_params={ - 'region_id': '$region_id' - }, label=_('Site') ) + location_id = DynamicModelMultipleChoiceField( + queryset=Location.objects.all(), + required=False, + label=_('Location') + ) role_id = DynamicModelMultipleChoiceField( queryset=Role.objects.all(), required=False, @@ -460,12 +463,50 @@ class VLANGroupFilterForm(NetBoxModelFilterSetForm): tag = TagFilterField(model) +class VLANTranslationPolicyFilterForm(NetBoxModelFilterSetForm): + model = VLANTranslationPolicy + fieldsets = ( + FieldSet('q', 'filter_id', 'tag'), + FieldSet('name', name=_('Attributes')), + ) + name = forms.CharField( + required=False, + label=_('Name') + ) + tag = TagFilterField(model) + + +class VLANTranslationRuleFilterForm(NetBoxModelFilterSetForm): + model = VLANTranslationRule + fieldsets = ( + FieldSet('q', 'filter_id', 'tag'), + FieldSet('policy_id', 'local_vid', 'remote_vid', name=_('Attributes')), + ) + tag = TagFilterField(model) + policy_id = DynamicModelMultipleChoiceField( + queryset=VLANTranslationPolicy.objects.all(), + required=False, + label=_('VLAN Translation Policy') + ) + local_vid = forms.IntegerField( + min_value=1, + required=False, + label=_('Local VLAN ID') + ) + remote_vid = forms.IntegerField( + min_value=1, + required=False, + label=_('Remote VLAN ID') + ) + + class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = VLAN fieldsets = ( FieldSet('q', 'filter_id', 'tag'), FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')), FieldSet('group_id', 'status', 'role_id', 'vid', 'l2vpn_id', name=_('Attributes')), + FieldSet('qinq_role', 'qinq_svlan_id', name=_('Q-in-Q/802.1ad')), FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')), ) selector_fields = ('filter_id', 'q', 'site_id') @@ -512,6 +553,17 @@ class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): required=False, label=_('VLAN ID') ) + qinq_role = forms.MultipleChoiceField( + label=_('Q-in-Q role'), + choices=VLANQinQRoleChoices, + required=False + ) + qinq_svlan_id = DynamicModelMultipleChoiceField( + queryset=VLAN.objects.all(), + required=False, + null_option='None', + label=_('Q-in-Q SVLAN') + ) l2vpn_id = DynamicModelMultipleChoiceField( queryset=L2VPN.objects.all(), required=False, diff --git a/netbox/ipam/forms/model_forms.py b/netbox/ipam/forms/model_forms.py index 156e7c435..c381f99c9 100644 --- a/netbox/ipam/forms/model_forms.py +++ b/netbox/ipam/forms/model_forms.py @@ -4,6 +4,7 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.utils.translation import gettext_lazy as _ from dcim.models import Device, Interface, Site +from dcim.forms.mixins import ScopedForm from ipam.choices import * from ipam.constants import * from ipam.formfields import IPNetworkFormField @@ -41,6 +42,8 @@ __all__ = ( 'ServiceTemplateForm', 'VLANForm', 'VLANGroupForm', + 'VLANTranslationPolicyForm', + 'VLANTranslationRuleForm', 'VRFForm', ) @@ -106,7 +109,8 @@ class RIRForm(NetBoxModelForm): class AggregateForm(TenancyForm, NetBoxModelForm): rir = DynamicModelChoiceField( queryset=RIR.objects.all(), - label=_('RIR') + label=_('RIR'), + quick_add=True ) comments = CommentField() @@ -129,6 +133,7 @@ class ASNRangeForm(TenancyForm, NetBoxModelForm): rir = DynamicModelChoiceField( queryset=RIR.objects.all(), label=_('RIR'), + quick_add=True ) slug = SlugField() fieldsets = ( @@ -147,6 +152,7 @@ class ASNForm(TenancyForm, NetBoxModelForm): rir = DynamicModelChoiceField( queryset=RIR.objects.all(), label=_('RIR'), + quick_add=True ) sites = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), @@ -195,19 +201,12 @@ class RoleForm(NetBoxModelForm): ] -class PrefixForm(TenancyForm, NetBoxModelForm): +class PrefixForm(TenancyForm, ScopedForm, NetBoxModelForm): vrf = DynamicModelChoiceField( queryset=VRF.objects.all(), required=False, label=_('VRF') ) - site = DynamicModelChoiceField( - label=_('Site'), - queryset=Site.objects.all(), - required=False, - selector=True, - null_option='None' - ) vlan = DynamicModelChoiceField( queryset=VLAN.objects.all(), required=False, @@ -220,7 +219,8 @@ class PrefixForm(TenancyForm, NetBoxModelForm): role = DynamicModelChoiceField( label=_('Role'), queryset=Role.objects.all(), - required=False + required=False, + quick_add=True ) comments = CommentField() @@ -228,15 +228,16 @@ class PrefixForm(TenancyForm, NetBoxModelForm): FieldSet( 'prefix', 'status', 'vrf', 'role', 'is_pool', 'mark_utilized', 'description', 'tags', name=_('Prefix') ), - FieldSet('site', 'vlan', name=_('Site/VLAN Assignment')), + FieldSet('scope_type', 'scope', name=_('Scope')), + FieldSet('vlan', name=_('VLAN Assignment')), FieldSet('tenant_group', 'tenant', name=_('Tenancy')), ) class Meta: model = Prefix fields = [ - 'prefix', 'vrf', 'site', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'tenant_group', 'tenant', - 'description', 'comments', 'tags', + 'prefix', 'vrf', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'scope_type', 'tenant_group', + 'tenant', 'description', 'comments', 'tags', ] @@ -249,7 +250,8 @@ class IPRangeForm(TenancyForm, NetBoxModelForm): role = DynamicModelChoiceField( label=_('Role'), queryset=Role.objects.all(), - required=False + required=False, + quick_add=True ) comments = CommentField() @@ -309,6 +311,10 @@ class IPAddressForm(TenancyForm, NetBoxModelForm): required=False, label=_('Make this the primary IP for the device/VM') ) + oob_for_parent = forms.BooleanField( + required=False, + label=_('Make this the out-of-band IP for the device') + ) comments = CommentField() fieldsets = ( @@ -320,7 +326,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm): FieldSet('vminterface', name=_('Virtual Machine')), FieldSet('fhrpgroup', name=_('FHRP Group')), ), - 'primary_for_parent', name=_('Assignment') + 'primary_for_parent', 'oob_for_parent', name=_('Assignment') ), FieldSet('nat_inside', name=_('NAT IP (Inside)')), ) @@ -328,8 +334,8 @@ class IPAddressForm(TenancyForm, NetBoxModelForm): class Meta: model = IPAddress fields = [ - 'address', 'vrf', 'status', 'role', 'dns_name', 'primary_for_parent', 'nat_inside', 'tenant_group', - 'tenant', 'description', 'comments', 'tags', + 'address', 'vrf', 'status', 'role', 'dns_name', 'primary_for_parent', 'oob_for_parent', 'nat_inside', + 'tenant_group', 'tenant', 'description', 'comments', 'tags', ] def __init__(self, *args, **kwargs): @@ -348,7 +354,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm): super().__init__(*args, **kwargs) - # Initialize primary_for_parent if IP address is already assigned + # Initialize parent object & fields if IP address is already assigned if self.instance.pk and self.instance.assigned_object: parent = getattr(self.instance.assigned_object, 'parent_object', None) if parent and ( @@ -357,6 +363,9 @@ class IPAddressForm(TenancyForm, NetBoxModelForm): ): self.initial['primary_for_parent'] = True + if parent and getattr(parent, 'oob_ip_id', None) == self.instance.pk: + self.initial['oob_for_parent'] = True + if type(instance.assigned_object) is Interface: self.fields['interface'].widget.add_query_params({ 'device_id': instance.assigned_object.device.pk, @@ -385,10 +394,15 @@ class IPAddressForm(TenancyForm, NetBoxModelForm): }) elif selected_objects: assigned_object = self.cleaned_data[selected_objects[0]] - if self.instance.pk and self.instance.assigned_object and self.cleaned_data['primary_for_parent'] and assigned_object != self.instance.assigned_object: - raise ValidationError( - _("Cannot reassign IP address while it is designated as the primary IP for the parent object") - ) + if self.instance.pk and self.instance.assigned_object and assigned_object != self.instance.assigned_object: + if self.cleaned_data['primary_for_parent']: + raise ValidationError( + _("Cannot reassign primary IP address for the parent device/VM") + ) + if self.cleaned_data['oob_for_parent']: + raise ValidationError( + _("Cannot reassign out-of-Band IP address for the parent device") + ) self.instance.assigned_object = assigned_object else: self.instance.assigned_object = None @@ -400,6 +414,16 @@ class IPAddressForm(TenancyForm, NetBoxModelForm): 'primary_for_parent', _("Only IP addresses assigned to an interface can be designated as primary IPs.") ) + # OOB IP assignment is only available if device interface has been assigned. + interface = self.cleaned_data.get('interface') + if self.cleaned_data.get('oob_for_parent') and not interface: + self.add_error( + 'oob_for_parent', _( + "Only IP addresses assigned to a device interface can be designated as the out-of-band IP for a " + "device." + ) + ) + def save(self, *args, **kwargs): ipaddress = super().save(*args, **kwargs) @@ -421,6 +445,17 @@ class IPAddressForm(TenancyForm, NetBoxModelForm): parent.primary_ip6 = None parent.save() + # Assign/clear this IPAddress as the OOB for the associated Device + if type(interface) is Interface: + parent = interface.parent_object + parent.snapshot() + if self.cleaned_data['oob_for_parent']: + parent.oob_ip = ipaddress + parent.save() + elif parent.oob_ip == ipaddress: + parent.oob_ip = None + parent.save() + return ipaddress @@ -642,15 +677,55 @@ class VLANForm(TenancyForm, NetBoxModelForm): role = DynamicModelChoiceField( label=_('Role'), queryset=Role.objects.all(), - required=False + required=False, + quick_add=True + ) + qinq_svlan = DynamicModelChoiceField( + label=_('Q-in-Q SVLAN'), + queryset=VLAN.objects.all(), + required=False, + query_params={ + 'qinq_role': VLANQinQRoleChoices.ROLE_SERVICE, + } ) comments = CommentField() class Meta: model = VLAN fields = [ - 'site', 'group', 'vid', 'name', 'status', 'role', 'tenant_group', 'tenant', 'description', 'comments', - 'tags', + 'site', 'group', 'vid', 'name', 'status', 'role', 'tenant_group', 'tenant', 'qinq_role', 'qinq_svlan', + 'description', 'comments', 'tags', + ] + + +class VLANTranslationPolicyForm(NetBoxModelForm): + + fieldsets = ( + FieldSet('name', 'description', 'tags', name=_('VLAN Translation Policy')), + ) + + class Meta: + model = VLANTranslationPolicy + fields = [ + 'name', 'description', 'tags', + ] + + +class VLANTranslationRuleForm(NetBoxModelForm): + policy = DynamicModelChoiceField( + label=_('Policy'), + queryset=VLANTranslationPolicy.objects.all(), + selector=True + ) + + fieldsets = ( + FieldSet('policy', 'local_vid', 'remote_vid', 'description', 'tags', name=_('VLAN Translation Rule')), + ) + + class Meta: + model = VLANTranslationRule + fields = [ + 'policy', 'local_vid', 'remote_vid', 'description', 'tags', ] diff --git a/netbox/ipam/graphql/filters.py b/netbox/ipam/graphql/filters.py index 5f6602416..1b0e0133b 100644 --- a/netbox/ipam/graphql/filters.py +++ b/netbox/ipam/graphql/filters.py @@ -19,6 +19,8 @@ __all__ = ( 'ServiceTemplateFilter', 'VLANFilter', 'VLANGroupFilter', + 'VLANTranslationPolicyFilter', + 'VLANTranslationRuleFilter', 'VRFFilter', ) @@ -113,6 +115,18 @@ class VLANGroupFilter(BaseFilterMixin): pass +@strawberry_django.filter(models.VLANTranslationPolicy, lookups=True) +@autotype_decorator(filtersets.VLANTranslationPolicyFilterSet) +class VLANTranslationPolicyFilter(BaseFilterMixin): + pass + + +@strawberry_django.filter(models.VLANTranslationRule, lookups=True) +@autotype_decorator(filtersets.VLANTranslationRuleFilterSet) +class VLANTranslationRuleFilter(BaseFilterMixin): + pass + + @strawberry_django.filter(models.VRF, lookups=True) @autotype_decorator(filtersets.VRFFilterSet) class VRFFilter(BaseFilterMixin): diff --git a/netbox/ipam/graphql/schema.py b/netbox/ipam/graphql/schema.py index 072f8cbcd..5fcf78ea9 100644 --- a/netbox/ipam/graphql/schema.py +++ b/netbox/ipam/graphql/schema.py @@ -53,5 +53,11 @@ class IPAMQuery: vlan_group: VLANGroupType = strawberry_django.field() vlan_group_list: List[VLANGroupType] = strawberry_django.field() + vlan_translation_policy: VLANTranslationPolicyType = strawberry_django.field() + vlan_translation_policy_list: List[VLANTranslationPolicyType] = strawberry_django.field() + + vlan_translation_rule: VLANTranslationRuleType = strawberry_django.field() + vlan_translation_rule_list: List[VLANTranslationRuleType] = strawberry_django.field() + vrf: VRFType = strawberry_django.field() vrf_list: List[VRFType] = strawberry_django.field() diff --git a/netbox/ipam/graphql/types.py b/netbox/ipam/graphql/types.py index 46d45816e..e6ecca984 100644 --- a/netbox/ipam/graphql/types.py +++ b/netbox/ipam/graphql/types.py @@ -27,6 +27,8 @@ __all__ = ( 'ServiceTemplateType', 'VLANType', 'VLANGroupType', + 'VLANTranslationPolicyType', + 'VLANTranslationRuleType', 'VRFType', ) @@ -152,17 +154,25 @@ class IPRangeType(NetBoxObjectType): @strawberry_django.type( models.Prefix, - fields='__all__', + exclude=('scope_type', 'scope_id', '_location', '_region', '_site', '_site_group'), filters=PrefixFilter ) class PrefixType(NetBoxObjectType, BaseIPAddressFamilyType): prefix: str - site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] | None vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None vlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None role: Annotated["RoleType", strawberry.lazy('ipam.graphql.types')] | None + @strawberry_django.field + def scope(self) -> Annotated[Union[ + Annotated["LocationType", strawberry.lazy('dcim.graphql.types')], + Annotated["RegionType", strawberry.lazy('dcim.graphql.types')], + Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')], + Annotated["SiteType", strawberry.lazy('dcim.graphql.types')], + ], strawberry.union("PrefixScopeType")] | None: + return self.scope + @strawberry_django.type( models.RIR, @@ -226,7 +236,7 @@ class ServiceTemplateType(NetBoxObjectType): @strawberry_django.type( models.VLAN, - fields='__all__', + exclude=('qinq_svlan',), filters=VLANFilter ) class VLANType(NetBoxObjectType): @@ -242,6 +252,10 @@ class VLANType(NetBoxObjectType): interfaces_as_tagged: List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]] vminterfaces_as_tagged: List[Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')]] + @strawberry_django.field + def qinq_svlan(self) -> Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None: + return self.qinq_svlan + @strawberry_django.type( models.VLANGroup, @@ -266,6 +280,27 @@ class VLANGroupType(OrganizationalObjectType): return self.scope +@strawberry_django.type( + models.VLANTranslationPolicy, + fields='__all__', + filters=VLANTranslationPolicyFilter +) +class VLANTranslationPolicyType(NetBoxObjectType): + rules: List[Annotated["VLANTranslationRuleType", strawberry.lazy('ipam.graphql.types')]] + + +@strawberry_django.type( + models.VLANTranslationRule, + fields='__all__', + filters=VLANTranslationRuleFilter +) +class VLANTranslationRuleType(NetBoxObjectType): + policy: Annotated[ + "VLANTranslationPolicyType", + strawberry.lazy('ipam.graphql.types') + ] = strawberry_django.field(select_related=["policy"]) + + @strawberry_django.type( models.VRF, fields='__all__', diff --git a/netbox/ipam/lookups.py b/netbox/ipam/lookups.py index c6abb5a26..c493b7876 100644 --- a/netbox/ipam/lookups.py +++ b/netbox/ipam/lookups.py @@ -108,8 +108,8 @@ class NetIn(Lookup): return self.rhs def as_sql(self, qn, connection): - lhs, lhs_params = self.process_lhs(qn, connection) - rhs, rhs_params = self.process_rhs(qn, connection) + lhs = self.process_lhs(qn, connection)[0] + rhs_params = self.process_rhs(qn, connection)[1] with_mask, without_mask = [], [] for address in rhs_params[0]: if '/' in address: diff --git a/netbox/ipam/migrations/0001_squashed.py b/netbox/ipam/migrations/0001_squashed.py index bef36e698..896d7c4c9 100644 --- a/netbox/ipam/migrations/0001_squashed.py +++ b/netbox/ipam/migrations/0001_squashed.py @@ -9,7 +9,6 @@ import taggit.managers class Migration(migrations.Migration): - initial = True dependencies = [ @@ -50,7 +49,23 @@ class Migration(migrations.Migration): ('status', models.CharField(default='active', max_length=50)), ('role', models.CharField(blank=True, max_length=50)), ('assigned_object_id', models.PositiveIntegerField(blank=True, null=True)), - ('dns_name', models.CharField(blank=True, max_length=255, validators=[django.core.validators.RegexValidator(code='invalid', message='Only alphanumeric characters, asterisks, hyphens, periods, and underscores are allowed in DNS names', regex='^([0-9A-Za-z_-]+|\\*)(\\.[0-9A-Za-z_-]+)*\\.?$')])), + ( + 'dns_name', + models.CharField( + blank=True, + max_length=255, + validators=[ + django.core.validators.RegexValidator( + code='invalid', + message=( + 'Only alphanumeric characters, asterisks, hyphens, periods, and underscores are ' + 'allowed in DNS names' + ), + regex='^([0-9A-Za-z_-]+|\\*)(\\.[0-9A-Za-z_-]+)*\\.?$', + ) + ], + ), + ), ('description', models.CharField(blank=True, max_length=200)), ], options={ @@ -73,7 +88,11 @@ class Migration(migrations.Migration): ], options={ 'verbose_name_plural': 'prefixes', - 'ordering': (django.db.models.expressions.OrderBy(django.db.models.expressions.F('vrf'), nulls_first=True), 'prefix', 'pk'), + 'ordering': ( + django.db.models.expressions.OrderBy(django.db.models.expressions.F('vrf'), nulls_first=True), + 'prefix', + 'pk', + ), }, ), migrations.CreateModel( @@ -135,10 +154,25 @@ class Migration(migrations.Migration): ('rd', models.CharField(blank=True, max_length=21, null=True, unique=True)), ('enforce_unique', models.BooleanField(default=True)), ('description', models.CharField(blank=True, max_length=200)), - ('export_targets', models.ManyToManyField(blank=True, related_name='exporting_vrfs', to='ipam.RouteTarget')), - ('import_targets', models.ManyToManyField(blank=True, related_name='importing_vrfs', to='ipam.RouteTarget')), + ( + 'export_targets', + models.ManyToManyField(blank=True, related_name='exporting_vrfs', to='ipam.RouteTarget'), + ), + ( + 'import_targets', + models.ManyToManyField(blank=True, related_name='importing_vrfs', to='ipam.RouteTarget'), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), - ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vrfs', to='tenancy.tenant')), + ( + 'tenant', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='vrfs', + to='tenancy.tenant', + ), + ), ], options={ 'verbose_name': 'VRF', @@ -157,7 +191,21 @@ class Migration(migrations.Migration): ('slug', models.SlugField(max_length=100)), ('scope_id', models.PositiveBigIntegerField(blank=True, null=True)), ('description', models.CharField(blank=True, max_length=200)), - ('scope_type', models.ForeignKey(blank=True, limit_choices_to=models.Q(('model__in', ('region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster'))), null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), + ( + 'scope_type', + models.ForeignKey( + blank=True, + limit_choices_to=models.Q( + ( + 'model__in', + ('region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster'), + ) + ), + null=True, + on_delete=django.db.models.deletion.CASCADE, + to='contenttypes.contenttype', + ), + ), ], options={ 'verbose_name': 'VLAN group', @@ -172,15 +220,59 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), - ('vid', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4094)])), + ( + 'vid', + models.PositiveSmallIntegerField( + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(4094), + ] + ), + ), ('name', models.CharField(max_length=64)), ('status', models.CharField(default='active', max_length=50)), ('description', models.CharField(blank=True, max_length=200)), - ('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vlans', to='ipam.vlangroup')), - ('role', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vlans', to='ipam.role')), - ('site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vlans', to='dcim.site')), + ( + 'group', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='vlans', + to='ipam.vlangroup', + ), + ), + ( + 'role', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='vlans', + to='ipam.role', + ), + ), + ( + 'site', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='vlans', + to='dcim.site', + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), - ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vlans', to='tenancy.tenant')), + ( + 'tenant', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='vlans', + to='tenancy.tenant', + ), + ), ], options={ 'verbose_name': 'VLAN', @@ -197,9 +289,29 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(primary_key=True, serialize=False)), ('name', models.CharField(max_length=100)), ('protocol', models.CharField(max_length=50)), - ('ports', django.contrib.postgres.fields.ArrayField(base_field=models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65535)]), size=None)), + ( + 'ports', + django.contrib.postgres.fields.ArrayField( + base_field=models.PositiveIntegerField( + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(65535), + ] + ), + size=None, + ), + ), ('description', models.CharField(blank=True, max_length=200)), - ('device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='services', to='dcim.device')), + ( + 'device', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='services', + to='dcim.device', + ), + ), ('ipaddresses', models.ManyToManyField(blank=True, related_name='services', to='ipam.IPAddress')), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], diff --git a/netbox/ipam/migrations/0002_squashed_0046.py b/netbox/ipam/migrations/0002_squashed_0046.py index 06bcd8741..6c03753d8 100644 --- a/netbox/ipam/migrations/0002_squashed_0046.py +++ b/netbox/ipam/migrations/0002_squashed_0046.py @@ -4,7 +4,6 @@ import taggit.managers class Migration(migrations.Migration): - dependencies = [ ('dcim', '0003_auto_20160628_1721'), ('virtualization', '0001_virtualization'), @@ -66,7 +65,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='service', name='virtual_machine', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='services', to='virtualization.virtualmachine'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='services', + to='virtualization.virtualmachine', + ), ), migrations.AddField( model_name='routetarget', @@ -76,17 +81,35 @@ class Migration(migrations.Migration): migrations.AddField( model_name='routetarget', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='route_targets', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='route_targets', + to='tenancy.tenant', + ), ), migrations.AddField( model_name='prefix', name='role', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='prefixes', to='ipam.role'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='prefixes', + to='ipam.role', + ), ), migrations.AddField( model_name='prefix', name='site', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='prefixes', to='dcim.site'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='prefixes', + to='dcim.site', + ), ), migrations.AddField( model_name='prefix', @@ -96,27 +119,64 @@ class Migration(migrations.Migration): migrations.AddField( model_name='prefix', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='prefixes', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='prefixes', + to='tenancy.tenant', + ), ), migrations.AddField( model_name='prefix', name='vlan', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='prefixes', to='ipam.vlan'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='prefixes', + to='ipam.vlan', + ), ), migrations.AddField( model_name='prefix', name='vrf', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='prefixes', to='ipam.vrf'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='prefixes', + to='ipam.vrf', + ), ), migrations.AddField( model_name='ipaddress', name='assigned_object_type', - field=models.ForeignKey(blank=True, limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'dcim'), ('model', 'interface')), models.Q(('app_label', 'virtualization'), ('model', 'vminterface')), _connector='OR')), null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + limit_choices_to=models.Q( + models.Q( + models.Q(('app_label', 'dcim'), ('model', 'interface')), + models.Q(('app_label', 'virtualization'), ('model', 'vminterface')), + _connector='OR', + ) + ), + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.AddField( model_name='ipaddress', name='nat_inside', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='nat_outside', to='ipam.ipaddress'), + field=models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='nat_outside', + to='ipam.ipaddress', + ), ), migrations.AddField( model_name='ipaddress', @@ -126,17 +186,31 @@ class Migration(migrations.Migration): migrations.AddField( model_name='ipaddress', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='ip_addresses', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='ip_addresses', + to='tenancy.tenant', + ), ), migrations.AddField( model_name='ipaddress', name='vrf', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='ip_addresses', to='ipam.vrf'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='ip_addresses', + to='ipam.vrf', + ), ), migrations.AddField( model_name='aggregate', name='rir', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='aggregates', to='ipam.rir'), + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='aggregates', to='ipam.rir' + ), ), migrations.AddField( model_name='aggregate', @@ -146,7 +220,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='aggregate', name='tenant', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='aggregates', to='tenancy.tenant'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='aggregates', + to='tenancy.tenant', + ), ), migrations.AlterUniqueTogether( name='vlangroup', diff --git a/netbox/ipam/migrations/0047_squashed_0053.py b/netbox/ipam/migrations/0047_squashed_0053.py index 470261316..a05d0cb81 100644 --- a/netbox/ipam/migrations/0047_squashed_0053.py +++ b/netbox/ipam/migrations/0047_squashed_0053.py @@ -8,7 +8,6 @@ import utilities.json class Migration(migrations.Migration): - replaces = [ ('ipam', '0047_prefix_depth_children'), ('ipam', '0048_prefix_populate_depth_children'), @@ -16,7 +15,7 @@ class Migration(migrations.Migration): ('ipam', '0050_iprange'), ('ipam', '0051_extend_tag_support'), ('ipam', '0052_fhrpgroup'), - ('ipam', '0053_asn_model') + ('ipam', '0053_asn_model'), ] dependencies = [ @@ -47,17 +46,47 @@ class Migration(migrations.Migration): fields=[ ('created', models.DateField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('start_address', ipam.fields.IPAddressField()), ('end_address', ipam.fields.IPAddressField()), ('size', models.PositiveIntegerField(editable=False)), ('status', models.CharField(default='active', max_length=50)), ('description', models.CharField(blank=True, max_length=200)), - ('role', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ip_ranges', to='ipam.role')), + ( + 'role', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='ip_ranges', + to='ipam.role', + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), - ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='ip_ranges', to='tenancy.tenant')), - ('vrf', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='ip_ranges', to='ipam.vrf')), + ( + 'tenant', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='ip_ranges', + to='tenancy.tenant', + ), + ), + ( + 'vrf', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='ip_ranges', + to='ipam.vrf', + ), + ), ], options={ 'verbose_name': 'IP range', @@ -85,7 +114,10 @@ class Migration(migrations.Migration): fields=[ ('created', models.DateField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('group_id', models.PositiveSmallIntegerField()), ('protocol', models.CharField(max_length=50)), @@ -102,7 +134,21 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='ipaddress', name='assigned_object_type', - field=models.ForeignKey(blank=True, limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'dcim'), ('model', 'interface')), models.Q(('app_label', 'ipam'), ('model', 'fhrpgroup')), models.Q(('app_label', 'virtualization'), ('model', 'vminterface')), _connector='OR')), null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype'), + field=models.ForeignKey( + blank=True, + limit_choices_to=models.Q( + models.Q( + models.Q(('app_label', 'dcim'), ('model', 'interface')), + models.Q(('app_label', 'ipam'), ('model', 'fhrpgroup')), + models.Q(('app_label', 'virtualization'), ('model', 'vminterface')), + _connector='OR', + ) + ), + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), ), migrations.CreateModel( name='FHRPGroupAssignment', @@ -111,9 +157,20 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('interface_id', models.PositiveIntegerField()), - ('priority', models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(255)])), + ( + 'priority', + models.PositiveSmallIntegerField( + validators=[ + django.core.validators.MinValueValidator(0), + django.core.validators.MaxValueValidator(255), + ] + ), + ), ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ipam.fhrpgroup')), - ('interface_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), + ( + 'interface_type', + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype'), + ), ], options={ 'verbose_name': 'FHRP group assignment', @@ -126,13 +183,28 @@ class Migration(migrations.Migration): fields=[ ('created', models.DateField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('asn', ipam.fields.ASNField(unique=True)), ('description', models.CharField(blank=True, max_length=200)), - ('rir', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='asns', to='ipam.rir')), + ( + 'rir', + models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='asns', to='ipam.rir'), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), - ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='asns', to='tenancy.tenant')), + ( + 'tenant', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='asns', + to='tenancy.tenant', + ), + ), ], options={ 'verbose_name': 'ASN', diff --git a/netbox/ipam/migrations/0054_squashed_0067.py b/netbox/ipam/migrations/0054_squashed_0067.py index 40073ca29..929a27fda 100644 --- a/netbox/ipam/migrations/0054_squashed_0067.py +++ b/netbox/ipam/migrations/0054_squashed_0067.py @@ -10,7 +10,6 @@ import utilities.json class Migration(migrations.Migration): - replaces = [ ('ipam', '0054_vlangroup_min_max_vids'), ('ipam', '0055_servicetemplate'), @@ -25,7 +24,7 @@ class Migration(migrations.Migration): ('ipam', '0064_clear_search_cache'), ('ipam', '0065_asnrange'), ('ipam', '0066_iprange_mark_utilized'), - ('ipam', '0067_ipaddress_index_host') + ('ipam', '0067_ipaddress_index_host'), ] dependencies = [ @@ -40,12 +39,24 @@ class Migration(migrations.Migration): migrations.AddField( model_name='vlangroup', name='max_vid', - field=models.PositiveSmallIntegerField(default=4094, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4094)]), + field=models.PositiveSmallIntegerField( + default=4094, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(4094), + ], + ), ), migrations.AddField( model_name='vlangroup', name='min_vid', - field=models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4094)]), + field=models.PositiveSmallIntegerField( + default=1, + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(4094), + ], + ), ), migrations.AlterField( model_name='aggregate', @@ -187,10 +198,24 @@ class Migration(migrations.Migration): fields=[ ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('protocol', models.CharField(max_length=50)), - ('ports', django.contrib.postgres.fields.ArrayField(base_field=models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65535)]), size=None)), + ( + 'ports', + django.contrib.postgres.fields.ArrayField( + base_field=models.PositiveIntegerField( + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(65535), + ] + ), + size=None, + ), + ), ('description', models.CharField(blank=True, max_length=200)), ('name', models.CharField(max_length=100, unique=True)), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), @@ -217,7 +242,13 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='ipaddress', name='nat_inside', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='nat_outside', to='ipam.ipaddress'), + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='nat_outside', + to='ipam.ipaddress', + ), ), migrations.CreateModel( name='L2VPN', @@ -225,16 +256,34 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('name', models.CharField(max_length=100, unique=True)), ('slug', models.SlugField(max_length=100, unique=True)), ('type', models.CharField(max_length=50)), ('identifier', models.BigIntegerField(blank=True, null=True)), ('description', models.CharField(blank=True, max_length=200)), - ('export_targets', models.ManyToManyField(blank=True, related_name='exporting_l2vpns', to='ipam.routetarget')), - ('import_targets', models.ManyToManyField(blank=True, related_name='importing_l2vpns', to='ipam.routetarget')), + ( + 'export_targets', + models.ManyToManyField(blank=True, related_name='exporting_l2vpns', to='ipam.routetarget'), + ), + ( + 'import_targets', + models.ManyToManyField(blank=True, related_name='importing_l2vpns', to='ipam.routetarget'), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), - ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='l2vpns', to='tenancy.tenant')), + ( + 'tenant', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='l2vpns', + to='tenancy.tenant', + ), + ), ], options={ 'verbose_name': 'L2VPN', @@ -247,10 +296,33 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('assigned_object_id', models.PositiveBigIntegerField()), - ('assigned_object_type', models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'dcim'), ('model', 'interface')), models.Q(('app_label', 'ipam'), ('model', 'vlan')), models.Q(('app_label', 'virtualization'), ('model', 'vminterface')), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')), - ('l2vpn', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='terminations', to='ipam.l2vpn')), + ( + 'assigned_object_type', + models.ForeignKey( + limit_choices_to=models.Q( + models.Q( + models.Q(('app_label', 'dcim'), ('model', 'interface')), + models.Q(('app_label', 'ipam'), ('model', 'vlan')), + models.Q(('app_label', 'virtualization'), ('model', 'vminterface')), + _connector='OR', + ) + ), + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), + ), + ( + 'l2vpn', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='terminations', to='ipam.l2vpn' + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], options={ @@ -260,7 +332,9 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='l2vpntermination', - constraint=models.UniqueConstraint(fields=('assigned_object_type', 'assigned_object_id'), name='ipam_l2vpntermination_assigned_object'), + constraint=models.UniqueConstraint( + fields=('assigned_object_type', 'assigned_object_id'), name='ipam_l2vpntermination_assigned_object' + ), ), migrations.AddField( model_name='fhrpgroup', @@ -281,7 +355,10 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='fhrpgroupassignment', - constraint=models.UniqueConstraint(fields=('interface_type', 'interface_id', 'group'), name='ipam_fhrpgroupassignment_unique_interface_group'), + constraint=models.UniqueConstraint( + fields=('interface_type', 'interface_id', 'group'), + name='ipam_fhrpgroupassignment_unique_interface_group', + ), ), migrations.AddConstraint( model_name='vlan', @@ -293,11 +370,15 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='vlangroup', - constraint=models.UniqueConstraint(fields=('scope_type', 'scope_id', 'name'), name='ipam_vlangroup_unique_scope_name'), + constraint=models.UniqueConstraint( + fields=('scope_type', 'scope_id', 'name'), name='ipam_vlangroup_unique_scope_name' + ), ), migrations.AddConstraint( model_name='vlangroup', - constraint=models.UniqueConstraint(fields=('scope_type', 'scope_id', 'slug'), name='ipam_vlangroup_unique_scope_slug'), + constraint=models.UniqueConstraint( + fields=('scope_type', 'scope_id', 'slug'), name='ipam_vlangroup_unique_scope_slug' + ), ), migrations.AddField( model_name='aggregate', @@ -365,15 +446,32 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('description', models.CharField(blank=True, max_length=200)), ('name', models.CharField(max_length=100, unique=True)), ('slug', models.SlugField(max_length=100, unique=True)), ('start', ipam.fields.ASNField()), ('end', ipam.fields.ASNField()), - ('rir', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='asn_ranges', to='ipam.rir')), + ( + 'rir', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='asn_ranges', to='ipam.rir' + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), - ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='asn_ranges', to='tenancy.tenant')), + ( + 'tenant', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='asn_ranges', + to='tenancy.tenant', + ), + ), ], options={ 'verbose_name': 'ASN range', @@ -388,6 +486,11 @@ class Migration(migrations.Migration): ), migrations.AddIndex( model_name='ipaddress', - index=models.Index(django.db.models.functions.comparison.Cast(ipam.lookups.Host('address'), output_field=ipam.fields.IPAddressField()), name='ipam_ipaddress_host'), + index=models.Index( + django.db.models.functions.comparison.Cast( + ipam.lookups.Host('address'), output_field=ipam.fields.IPAddressField() + ), + name='ipam_ipaddress_host', + ), ), ] diff --git a/netbox/ipam/migrations/0068_move_l2vpn.py b/netbox/ipam/migrations/0068_move_l2vpn.py index b1a059de1..9240240bc 100644 --- a/netbox/ipam/migrations/0068_move_l2vpn.py +++ b/netbox/ipam/migrations/0068_move_l2vpn.py @@ -15,7 +15,6 @@ def update_content_types(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('ipam', '0067_ipaddress_index_host'), ] @@ -57,8 +56,5 @@ class Migration(migrations.Migration): ), ], ), - migrations.RunPython( - code=update_content_types, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=update_content_types, reverse_code=migrations.RunPython.noop), ] diff --git a/netbox/ipam/migrations/0069_gfk_indexes.py b/netbox/ipam/migrations/0069_gfk_indexes.py index 75c016102..d7ce48e35 100644 --- a/netbox/ipam/migrations/0069_gfk_indexes.py +++ b/netbox/ipam/migrations/0069_gfk_indexes.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('ipam', '0068_move_l2vpn'), ] @@ -16,7 +15,9 @@ class Migration(migrations.Migration): ), migrations.AddIndex( model_name='ipaddress', - index=models.Index(fields=['assigned_object_type', 'assigned_object_id'], name='ipam_ipaddr_assigne_890ab8_idx'), + index=models.Index( + fields=['assigned_object_type', 'assigned_object_id'], name='ipam_ipaddr_assigne_890ab8_idx' + ), ), migrations.AddIndex( model_name='vlangroup', diff --git a/netbox/ipam/migrations/0070_vlangroup_vlan_id_ranges.py b/netbox/ipam/migrations/0070_vlangroup_vlan_id_ranges.py index b01941401..133173234 100644 --- a/netbox/ipam/migrations/0070_vlangroup_vlan_id_ranges.py +++ b/netbox/ipam/migrations/0070_vlangroup_vlan_id_ranges.py @@ -12,15 +12,12 @@ def set_vid_ranges(apps, schema_editor): """ VLANGroup = apps.get_model('ipam', 'VLANGroup') for group in VLANGroup.objects.all(): - group.vid_ranges = [ - NumericRange(group.min_vid, group.max_vid, bounds='[]') - ] + group.vid_ranges = [NumericRange(group.min_vid, group.max_vid, bounds='[]')] group._total_vlan_ids = group.max_vid - group.min_vid + 1 group.save() class Migration(migrations.Migration): - dependencies = [ ('ipam', '0069_gfk_indexes'), ] @@ -32,7 +29,7 @@ class Migration(migrations.Migration): field=django.contrib.postgres.fields.ArrayField( base_field=django.contrib.postgres.fields.ranges.IntegerRangeField(), default=ipam.models.vlans.default_vid_ranges, - size=None + size=None, ), ), migrations.AddField( @@ -40,10 +37,7 @@ class Migration(migrations.Migration): name='_total_vlan_ids', field=models.PositiveBigIntegerField(default=4094), ), - migrations.RunPython( - code=set_vid_ranges, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=set_vid_ranges, reverse_code=migrations.RunPython.noop), migrations.RemoveField( model_name='vlangroup', name='max_vid', diff --git a/netbox/ipam/migrations/0071_prefix_scope.py b/netbox/ipam/migrations/0071_prefix_scope.py new file mode 100644 index 000000000..2ab54d023 --- /dev/null +++ b/netbox/ipam/migrations/0071_prefix_scope.py @@ -0,0 +1,45 @@ +import django.db.models.deletion +from django.db import migrations, models + + +def copy_site_assignments(apps, schema_editor): + """ + Copy site ForeignKey values to the scope GFK. + """ + ContentType = apps.get_model('contenttypes', 'ContentType') + Prefix = apps.get_model('ipam', 'Prefix') + Site = apps.get_model('dcim', 'Site') + + Prefix.objects.filter(site__isnull=False).update( + scope_type=ContentType.objects.get_for_model(Site), scope_id=models.F('site_id') + ) + + +class Migration(migrations.Migration): + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('ipam', '0070_vlangroup_vlan_id_ranges'), + ] + + operations = [ + # Add the `scope` GenericForeignKey + migrations.AddField( + model_name='prefix', + name='scope_id', + field=models.PositiveBigIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='prefix', + name='scope_type', + field=models.ForeignKey( + blank=True, + limit_choices_to=models.Q(('model__in', ('region', 'sitegroup', 'site', 'location'))), + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='+', + to='contenttypes.contenttype', + ), + ), + # Copy over existing site assignments + migrations.RunPython(code=copy_site_assignments, reverse_code=migrations.RunPython.noop), + ] diff --git a/netbox/ipam/migrations/0072_prefix_cached_relations.py b/netbox/ipam/migrations/0072_prefix_cached_relations.py new file mode 100644 index 000000000..e4a789704 --- /dev/null +++ b/netbox/ipam/migrations/0072_prefix_cached_relations.py @@ -0,0 +1,61 @@ +import django.db.models.deletion +from django.db import migrations, models + + +def populate_denormalized_fields(apps, schema_editor): + """ + Copy site ForeignKey values to the scope GFK. + """ + Prefix = apps.get_model('ipam', 'Prefix') + + prefixes = Prefix.objects.filter(site__isnull=False).prefetch_related('site') + for prefix in prefixes: + prefix._region_id = prefix.site.region_id + prefix._site_group_id = prefix.site.group_id + prefix._site_id = prefix.site_id + # Note: Location cannot be set prior to migration + + Prefix.objects.bulk_update(prefixes, ['_region', '_site_group', '_site']) + + +class Migration(migrations.Migration): + dependencies = [ + ('dcim', '0193_poweroutlet_color'), + ('ipam', '0071_prefix_scope'), + ] + + operations = [ + migrations.AddField( + model_name='prefix', + name='_location', + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.location' + ), + ), + migrations.AddField( + model_name='prefix', + name='_region', + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.region' + ), + ), + migrations.AddField( + model_name='prefix', + name='_site', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.site'), + ), + migrations.AddField( + model_name='prefix', + name='_site_group', + field=models.ForeignKey( + blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.sitegroup' + ), + ), + # Populate denormalized FK values + migrations.RunPython(code=populate_denormalized_fields, reverse_code=migrations.RunPython.noop), + # Delete the site ForeignKey + migrations.RemoveField( + model_name='prefix', + name='site', + ), + ] diff --git a/netbox/ipam/migrations/0073_charfield_null_choices.py b/netbox/ipam/migrations/0073_charfield_null_choices.py new file mode 100644 index 000000000..cfb764b46 --- /dev/null +++ b/netbox/ipam/migrations/0073_charfield_null_choices.py @@ -0,0 +1,32 @@ +from django.db import migrations, models + + +def set_null_values(apps, schema_editor): + """ + Replace empty strings with null values. + """ + FHRPGroup = apps.get_model('ipam', 'FHRPGroup') + IPAddress = apps.get_model('ipam', 'IPAddress') + + FHRPGroup.objects.filter(auth_type='').update(auth_type=None) + IPAddress.objects.filter(role='').update(role=None) + + +class Migration(migrations.Migration): + dependencies = [ + ('ipam', '0072_prefix_cached_relations'), + ] + + operations = [ + migrations.AlterField( + model_name='fhrpgroup', + name='auth_type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='ipaddress', + name='role', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.RunPython(code=set_null_values, reverse_code=migrations.RunPython.noop), + ] diff --git a/netbox/ipam/migrations/0074_vlantranslationpolicy_vlantranslationrule.py b/netbox/ipam/migrations/0074_vlantranslationpolicy_vlantranslationrule.py new file mode 100644 index 000000000..5a13f18e6 --- /dev/null +++ b/netbox/ipam/migrations/0074_vlantranslationpolicy_vlantranslationrule.py @@ -0,0 +1,97 @@ +# Generated by Django 5.0.9 on 2024-10-11 19:45 + +import django.core.validators +import django.db.models.deletion +import taggit.managers +import utilities.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('extras', '0121_customfield_related_object_filter'), + ('ipam', '0073_charfield_null_choices'), + ] + + operations = [ + migrations.CreateModel( + name='VLANTranslationPolicy', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), + ('comments', models.TextField(blank=True)), + ('name', models.CharField(max_length=100, unique=True)), + ('description', models.CharField(blank=True, max_length=200)), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ], + options={ + 'verbose_name': 'VLAN translation policy', + 'verbose_name_plural': 'VLAN translation policies', + 'ordering': ('name',), + }, + ), + migrations.CreateModel( + name='VLANTranslationRule', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), + ( + 'local_vid', + models.PositiveSmallIntegerField( + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(4094), + ] + ), + ), + ( + 'remote_vid', + models.PositiveSmallIntegerField( + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(4094), + ] + ), + ), + ( + 'policy', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name='rules', + to='ipam.vlantranslationpolicy', + ), + ), + ('description', models.CharField(blank=True, max_length=200)), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ], + options={ + 'verbose_name': 'VLAN translation rule', + 'ordering': ( + 'policy', + 'local_vid', + ), + }, + ), + migrations.AddConstraint( + model_name='vlantranslationrule', + constraint=models.UniqueConstraint( + fields=('policy', 'local_vid'), name='ipam_vlantranslationrule_unique_policy_local_vid' + ), + ), + migrations.AddConstraint( + model_name='vlantranslationrule', + constraint=models.UniqueConstraint( + fields=('policy', 'remote_vid'), name='ipam_vlantranslationrule_unique_policy_remote_vid' + ), + ), + ] diff --git a/netbox/ipam/migrations/0075_vlan_qinq.py b/netbox/ipam/migrations/0075_vlan_qinq.py new file mode 100644 index 000000000..1e8f86c36 --- /dev/null +++ b/netbox/ipam/migrations/0075_vlan_qinq.py @@ -0,0 +1,35 @@ +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('ipam', '0074_vlantranslationpolicy_vlantranslationrule'), + ] + + operations = [ + migrations.AddField( + model_name='vlan', + name='qinq_role', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='vlan', + name='qinq_svlan', + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name='qinq_cvlans', + to='ipam.vlan', + ), + ), + migrations.AddConstraint( + model_name='vlan', + constraint=models.UniqueConstraint(fields=('qinq_svlan', 'vid'), name='ipam_vlan_unique_qinq_svlan_vid'), + ), + migrations.AddConstraint( + model_name='vlan', + constraint=models.UniqueConstraint(fields=('qinq_svlan', 'name'), name='ipam_vlan_unique_qinq_svlan_name'), + ), + ] diff --git a/netbox/ipam/migrations/0076_natural_ordering.py b/netbox/ipam/migrations/0076_natural_ordering.py new file mode 100644 index 000000000..f6c9e5ccb --- /dev/null +++ b/netbox/ipam/migrations/0076_natural_ordering.py @@ -0,0 +1,31 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('ipam', '0075_vlan_qinq'), + ('dcim', '0197_natural_sort_collation'), + ] + + operations = [ + migrations.AlterField( + model_name='asnrange', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='routetarget', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=21, unique=True), + ), + migrations.AlterField( + model_name='vlangroup', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + migrations.AlterField( + model_name='vrf', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + ] diff --git a/netbox/ipam/models/asns.py b/netbox/ipam/models/asns.py index eb47426b2..c1d251301 100644 --- a/netbox/ipam/models/asns.py +++ b/netbox/ipam/models/asns.py @@ -16,7 +16,8 @@ class ASNRange(OrganizationalModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), diff --git a/netbox/ipam/models/fhrp.py b/netbox/ipam/models/fhrp.py index 28bb37ef3..f5982853e 100644 --- a/netbox/ipam/models/fhrp.py +++ b/netbox/ipam/models/fhrp.py @@ -34,6 +34,7 @@ class FHRPGroup(PrimaryModel): max_length=50, choices=FHRPGroupAuthTypeChoices, blank=True, + null=True, verbose_name=_('authentication type') ) auth_key = models.CharField( diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py index a540b5810..e1a8d91e3 100644 --- a/netbox/ipam/models/ip.py +++ b/netbox/ipam/models/ip.py @@ -8,6 +8,7 @@ from django.utils.functional import cached_property from django.utils.translation import gettext_lazy as _ from core.models import ObjectType +from dcim.models.mixins import CachedScopeMixin from ipam.choices import * from ipam.constants import * from ipam.fields import IPNetworkField, IPAddressField @@ -197,23 +198,16 @@ class Role(OrganizationalModel): return self.name -class Prefix(ContactsMixin, GetAvailablePrefixesMixin, PrimaryModel): +class Prefix(ContactsMixin, GetAvailablePrefixesMixin, CachedScopeMixin, PrimaryModel): """ - A Prefix represents an IPv4 or IPv6 network, including mask length. Prefixes can optionally be assigned to Sites and - VRFs. A Prefix must be assigned a status and may optionally be assigned a used-define Role. A Prefix can also be - assigned to a VLAN where appropriate. + A Prefix represents an IPv4 or IPv6 network, including mask length. Prefixes can optionally be scoped to certain + areas and/or assigned to VRFs. A Prefix must be assigned a status and may optionally be assigned a used-define Role. + A Prefix can also be assigned to a VLAN where appropriate. """ prefix = IPNetworkField( verbose_name=_('prefix'), help_text=_('IPv4 or IPv6 network with mask') ) - site = models.ForeignKey( - to='dcim.Site', - on_delete=models.PROTECT, - related_name='prefixes', - blank=True, - null=True - ) vrf = models.ForeignKey( to='ipam.VRF', on_delete=models.PROTECT, @@ -275,7 +269,7 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, PrimaryModel): objects = PrefixQuerySet.as_manager() clone_fields = ( - 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'description', + 'scope_type', 'scope_id', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'mark_utilized', 'description', ) class Meta: @@ -323,6 +317,9 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, PrimaryModel): # Clear host bits from prefix self.prefix = self.prefix.cidr + # Cache objects associated with the terminating object (for filtering) + self.cache_related_objects() + super().save(*args, **kwargs) @property @@ -421,7 +418,9 @@ class Prefix(ContactsMixin, GetAvailablePrefixesMixin, PrimaryModel): available_ips = prefix - child_ips - netaddr.IPSet(child_ranges) # IPv6 /127's, pool, or IPv4 /31-/32 sets are fully usable - if (self.family == 6 and self.prefix.prefixlen >= 127) or self.is_pool or (self.family == 4 and self.prefix.prefixlen >= 31): + if (self.family == 6 and self.prefix.prefixlen >= 127) or self.is_pool or ( + self.family == 4 and self.prefix.prefixlen >= 31 + ): return available_ips if self.family == 4: @@ -564,15 +563,31 @@ class IPRange(ContactsMixin, PrimaryModel): }) # Check for overlapping ranges - overlapping_range = IPRange.objects.exclude(pk=self.pk).filter(vrf=self.vrf).filter( - Q(start_address__gte=self.start_address, start_address__lte=self.end_address) | # Starts inside - Q(end_address__gte=self.start_address, end_address__lte=self.end_address) | # Ends inside - Q(start_address__lte=self.start_address, end_address__gte=self.end_address) # Starts & ends outside - ).first() - if overlapping_range: + overlapping_ranges = ( + IPRange.objects.exclude(pk=self.pk) + .filter(vrf=self.vrf) + .filter( + # Starts inside + Q( + start_address__host__inet__gte=self.start_address.ip, + start_address__host__inet__lte=self.end_address.ip, + ) | + # Ends inside + Q( + end_address__host__inet__gte=self.start_address.ip, + end_address__host__inet__lte=self.end_address.ip, + ) | + # Starts & ends outside + Q( + start_address__host__inet__lte=self.start_address.ip, + end_address__host__inet__gte=self.end_address.ip, + ) + ) + ) + if overlapping_ranges.exists(): raise ValidationError( _("Defined addresses overlap with range {overlapping_range} in VRF {vrf}").format( - overlapping_range=overlapping_range, + overlapping_range=overlapping_ranges.first(), vrf=self.vrf )) @@ -722,6 +737,7 @@ class IPAddress(ContactsMixin, PrimaryModel): max_length=50, choices=IPAddressRoleChoices, blank=True, + null=True, help_text=_('The functional role of this IP') ) assigned_object_type = models.ForeignKey( @@ -868,10 +884,12 @@ class IPAddress(ContactsMixin, PrimaryModel): # can't use is_primary_ip as self.assigned_object might be changed is_primary = False - if self.family == 4 and hasattr(original_parent, 'primary_ip4') and original_parent.primary_ip4_id == self.pk: - is_primary = True - if self.family == 6 and hasattr(original_parent, 'primary_ip6') and original_parent.primary_ip6_id == self.pk: - is_primary = True + if self.family == 4 and hasattr(original_parent, 'primary_ip4'): + if original_parent.primary_ip4_id == self.pk: + is_primary = True + if self.family == 6 and hasattr(original_parent, 'primary_ip6'): + if original_parent.primary_ip6_id == self.pk: + is_primary = True if is_primary and (parent != original_parent): raise ValidationError( diff --git a/netbox/ipam/models/vlans.py b/netbox/ipam/models/vlans.py index 23f7c41c7..4c7f191c9 100644 --- a/netbox/ipam/models/vlans.py +++ b/netbox/ipam/models/vlans.py @@ -10,13 +10,15 @@ from dcim.models import Interface from ipam.choices import * from ipam.constants import * from ipam.querysets import VLANQuerySet, VLANGroupQuerySet -from netbox.models import OrganizationalModel, PrimaryModel +from netbox.models import OrganizationalModel, PrimaryModel, NetBoxModel from utilities.data import check_ranges_overlap, ranges_to_string from virtualization.models import VMInterface __all__ = ( 'VLAN', 'VLANGroup', + 'VLANTranslationPolicy', + 'VLANTranslationRule', ) @@ -33,7 +35,8 @@ class VLANGroup(OrganizationalModel): """ name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), @@ -93,16 +96,32 @@ class VLANGroup(OrganizationalModel): raise ValidationError(_("Cannot set scope_id without scope_type.")) # Validate VID ranges - if self.vid_ranges and check_ranges_overlap(self.vid_ranges): - raise ValidationError({'vid_ranges': _("Ranges cannot overlap.")}) for vid_range in self.vid_ranges: - if vid_range.lower > vid_range.upper: + lower_vid = vid_range.lower if vid_range.lower_inc else vid_range.lower + 1 + upper_vid = vid_range.upper if vid_range.upper_inc else vid_range.upper - 1 + if lower_vid < VLAN_VID_MIN: + raise ValidationError({ + 'vid_ranges': _("Starting VLAN ID in range ({value}) cannot be less than {minimum}").format( + value=lower_vid, minimum=VLAN_VID_MIN + ) + }) + if upper_vid > VLAN_VID_MAX: + raise ValidationError({ + 'vid_ranges': _("Ending VLAN ID in range ({value}) cannot exceed {maximum}").format( + value=upper_vid, maximum=VLAN_VID_MAX + ) + }) + if lower_vid > upper_vid: raise ValidationError({ 'vid_ranges': _( - "Maximum child VID must be greater than or equal to minimum child VID ({value})" - ).format(value=vid_range) + "Ending VLAN ID in range must be greater than or equal to the starting VLAN ID ({range})" + ).format(range=f'{lower_vid}-{upper_vid}') }) + # Check for overlapping VID ranges + if self.vid_ranges and check_ranges_overlap(self.vid_ranges): + raise ValidationError({'vid_ranges': _("Ranges cannot overlap.")}) + def save(self, *args, **kwargs): self._total_vlan_ids = 0 for vid_range in self.vid_ranges: @@ -202,6 +221,21 @@ class VLAN(PrimaryModel): null=True, help_text=_("The primary function of this VLAN") ) + qinq_svlan = models.ForeignKey( + to='self', + on_delete=models.PROTECT, + related_name='qinq_cvlans', + blank=True, + null=True + ) + qinq_role = models.CharField( + verbose_name=_('Q-in-Q role'), + max_length=50, + choices=VLANQinQRoleChoices, + blank=True, + null=True, + help_text=_("Customer/service VLAN designation (for Q-in-Q/IEEE 802.1ad)") + ) l2vpn_terminations = GenericRelation( to='vpn.L2VPNTermination', content_type_field='assigned_object_type', @@ -212,7 +246,7 @@ class VLAN(PrimaryModel): objects = VLANQuerySet.as_manager() clone_fields = [ - 'site', 'group', 'tenant', 'status', 'role', 'description', + 'site', 'group', 'tenant', 'status', 'role', 'description', 'qinq_role', 'qinq_svlan', ] class Meta: @@ -226,6 +260,14 @@ class VLAN(PrimaryModel): fields=('group', 'name'), name='%(app_label)s_%(class)s_unique_group_name' ), + models.UniqueConstraint( + fields=('qinq_svlan', 'vid'), + name='%(app_label)s_%(class)s_unique_qinq_svlan_vid' + ), + models.UniqueConstraint( + fields=('qinq_svlan', 'name'), + name='%(app_label)s_%(class)s_unique_qinq_svlan_name' + ), ) verbose_name = _('VLAN') verbose_name_plural = _('VLANs') @@ -253,9 +295,24 @@ class VLAN(PrimaryModel): ).format(ranges=ranges_to_string(self.group.vid_ranges), group=self.group) }) + # Only Q-in-Q customer VLANs may be assigned to a service VLAN + if self.qinq_svlan and self.qinq_role != VLANQinQRoleChoices.ROLE_CUSTOMER: + raise ValidationError({ + 'qinq_svlan': _("Only Q-in-Q customer VLANs maybe assigned to a service VLAN.") + }) + + # A Q-in-Q customer VLAN must be assigned to a service VLAN + if self.qinq_role == VLANQinQRoleChoices.ROLE_CUSTOMER and not self.qinq_svlan: + raise ValidationError({ + 'qinq_role': _("A Q-in-Q customer VLAN must be assigned to a service VLAN.") + }) + def get_status_color(self): return VLANStatusChoices.colors.get(self.status) + def get_qinq_role_color(self): + return VLANQinQRoleChoices.colors.get(self.qinq_role) + def get_interfaces(self): # Return all device interfaces assigned to this VLAN return Interface.objects.filter( @@ -273,3 +330,75 @@ class VLAN(PrimaryModel): @property def l2vpn_termination(self): return self.l2vpn_terminations.first() + + +class VLANTranslationPolicy(PrimaryModel): + name = models.CharField( + verbose_name=_('name'), + max_length=100, + unique=True, + ) + + class Meta: + verbose_name = _('VLAN translation policy') + verbose_name_plural = _('VLAN translation policies') + ordering = ('name',) + + def __str__(self): + return self.name + + +class VLANTranslationRule(NetBoxModel): + policy = models.ForeignKey( + to=VLANTranslationPolicy, + related_name='rules', + on_delete=models.CASCADE, + ) + description = models.CharField( + verbose_name=_('description'), + max_length=200, + blank=True + ) + local_vid = models.PositiveSmallIntegerField( + verbose_name=_('Local VLAN ID'), + validators=( + MinValueValidator(VLAN_VID_MIN), + MaxValueValidator(VLAN_VID_MAX) + ), + help_text=_("Numeric VLAN ID (1-4094)") + ) + remote_vid = models.PositiveSmallIntegerField( + verbose_name=_('Remote VLAN ID'), + validators=( + MinValueValidator(VLAN_VID_MIN), + MaxValueValidator(VLAN_VID_MAX) + ), + help_text=_("Numeric VLAN ID (1-4094)") + ) + prerequisite_models = ( + 'ipam.VLANTranslationPolicy', + ) + + clone_fields = ['policy'] + + class Meta: + verbose_name = _('VLAN translation rule') + ordering = ('policy', 'local_vid',) + constraints = ( + models.UniqueConstraint( + fields=('policy', 'local_vid'), + name='%(app_label)s_%(class)s_unique_policy_local_vid' + ), + models.UniqueConstraint( + fields=('policy', 'remote_vid'), + name='%(app_label)s_%(class)s_unique_policy_remote_vid' + ), + ) + + def __str__(self): + return f'{self.local_vid} -> {self.remote_vid} ({self.policy})' + + def to_objectchange(self, action): + objectchange = super().to_objectchange(action) + objectchange.related_object = self.policy + return objectchange diff --git a/netbox/ipam/models/vrfs.py b/netbox/ipam/models/vrfs.py index 26afb7927..6a8b8d649 100644 --- a/netbox/ipam/models/vrfs.py +++ b/netbox/ipam/models/vrfs.py @@ -18,7 +18,8 @@ class VRF(PrimaryModel): """ name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) rd = models.CharField( max_length=VRF_RD_MAX_LENGTH, @@ -74,7 +75,8 @@ class RouteTarget(PrimaryModel): verbose_name=_('name'), max_length=VRF_RD_MAX_LENGTH, # Same format options as VRF RD (RFC 4360 section 4) unique=True, - help_text=_('Route target value (formatted in accordance with RFC 4360)') + help_text=_('Route target value (formatted in accordance with RFC 4360)'), + db_collation="natural_sort" ) tenant = models.ForeignKey( to='tenancy.Tenant', diff --git a/netbox/ipam/querysets.py b/netbox/ipam/querysets.py index 771e9b3b9..77ab8194a 100644 --- a/netbox/ipam/querysets.py +++ b/netbox/ipam/querysets.py @@ -148,7 +148,7 @@ class VLANQuerySet(RestrictedQuerySet): # Find all relevant VLANGroups q = Q() - site = vm.site or vm.cluster.site + site = vm.site or vm.cluster._site if vm.cluster: # Add VLANGroups scoped to the assigned cluster (or its group) q |= Q( diff --git a/netbox/ipam/search.py b/netbox/ipam/search.py index 16a8eba3c..d200abacf 100644 --- a/netbox/ipam/search.py +++ b/netbox/ipam/search.py @@ -160,6 +160,27 @@ class VLANGroupIndex(SearchIndex): display_attrs = ('scope_type', 'description') +@register_search +class VLANTranslationPolicyIndex(SearchIndex): + model = models.VLANTranslationPolicy + fields = ( + ('name', 100), + ('description', 500), + ) + display_attrs = ('description',) + + +@register_search +class VLANTranslationRuleIndex(SearchIndex): + model = models.VLANTranslationRule + fields = ( + ('policy', 100), + ('local_vid', 200), + ('remote_vid', 200), + ) + display_attrs = ('policy', 'local_vid', 'remote_vid') + + @register_search class VRFIndex(SearchIndex): model = models.VRF diff --git a/netbox/ipam/tables/ip.py b/netbox/ipam/tables/ip.py index 8ec7a5967..dbbeb3454 100644 --- a/netbox/ipam/tables/ip.py +++ b/netbox/ipam/tables/ip.py @@ -6,6 +6,7 @@ from django_tables2.utils import Accessor from ipam.models import * from netbox.tables import NetBoxTable, columns from tenancy.tables import TenancyColumnsMixin, TenantColumn +from .template_code import * __all__ = ( 'AggregateTable', @@ -20,61 +21,6 @@ __all__ = ( AVAILABLE_LABEL = mark_safe('Available') -AGGREGATE_COPY_BUTTON = """ -{% copy_content record.pk prefix="aggregate_" %} -""" - -PREFIX_LINK = """ -{% if record.pk %} - {{ record.prefix }} -{% else %} - {{ record.prefix }} -{% endif %} -""" - -PREFIX_COPY_BUTTON = """ -{% copy_content record.pk prefix="prefix_" %} -""" - -PREFIX_LINK_WITH_DEPTH = """ -{% load helpers %} -{% if record.depth %} -
    - {% for i in record.depth|as_range %} - - {% endfor %} -
    -{% endif %} -""" + PREFIX_LINK - -IPADDRESS_LINK = """ -{% if record.pk %} - {{ record.address }} -{% elif perms.ipam.add_ipaddress %} - {% if record.0 <= 65536 %}{{ record.0 }}{% else %}Many{% endif %} IP{{ record.0|pluralize }} available -{% else %} - {% if record.0 <= 65536 %}{{ record.0 }}{% else %}Many{% endif %} IP{{ record.0|pluralize }} available -{% endif %} -""" - -IPADDRESS_COPY_BUTTON = """ -{% copy_content record.pk prefix="ipaddress_" %} -""" - -IPADDRESS_ASSIGN_LINK = """ -{{ record }} -""" - -VRF_LINK = """ -{% if value %} - {{ record.vrf }} -{% elif object.vrf %} - {{ object.vrf }} -{% else %} - Global -{% endif %} -""" - # # RIRs @@ -241,8 +187,11 @@ class PrefixTable(TenancyColumnsMixin, NetBoxTable): template_code=VRF_LINK, verbose_name=_('VRF') ) - site = tables.Column( - verbose_name=_('Site'), + scope_type = columns.ContentTypeColumn( + verbose_name=_('Scope Type'), + ) + scope = tables.Column( + verbose_name=_('Scope'), linkify=True ) vlan_group = tables.Column( @@ -285,11 +234,12 @@ class PrefixTable(TenancyColumnsMixin, NetBoxTable): model = Prefix fields = ( 'pk', 'id', 'prefix', 'prefix_flat', 'status', 'children', 'vrf', 'utilization', 'tenant', 'tenant_group', - 'site', 'vlan_group', 'vlan', 'role', 'is_pool', 'mark_utilized', 'description', 'comments', 'tags', - 'created', 'last_updated', + 'scope', 'scope_type', 'vlan_group', 'vlan', 'role', 'is_pool', 'mark_utilized', 'description', 'comments', + 'tags', 'created', 'last_updated', ) default_columns = ( - 'pk', 'prefix', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role', 'description', + 'pk', 'prefix', 'status', 'children', 'vrf', 'utilization', 'tenant', 'scope', 'vlan', 'role', + 'description', ) row_attrs = { 'class': lambda record: 'success' if not record.pk else '', diff --git a/netbox/ipam/tables/template_code.py b/netbox/ipam/tables/template_code.py new file mode 100644 index 000000000..fb969345e --- /dev/null +++ b/netbox/ipam/tables/template_code.py @@ -0,0 +1,88 @@ +AGGREGATE_COPY_BUTTON = """ +{% copy_content record.pk prefix="aggregate_" %} +""" + +PREFIX_LINK = """ +{% if record.pk %} + {{ record.prefix }} +{% else %} + {{ record.prefix }} +{% endif %} +""" + +PREFIX_COPY_BUTTON = """ +{% copy_content record.pk prefix="prefix_" %} +""" + +PREFIX_LINK_WITH_DEPTH = """ +{% load helpers %} +{% if record.depth %} +
    + {% for i in record.depth|as_range %} + + {% endfor %} +
    +{% endif %} +""" + PREFIX_LINK + +IPADDRESS_LINK = """ +{% if record.pk %} + {{ record.address }} +{% elif perms.ipam.add_ipaddress %} + {% if record.0 <= 65536 %}{{ record.0 }}{% else %}Many{% endif %} IP{{ record.0|pluralize }} available +{% else %} + {% if record.0 <= 65536 %}{{ record.0 }}{% else %}Many{% endif %} IP{{ record.0|pluralize }} available +{% endif %} +""" + +IPADDRESS_COPY_BUTTON = """ +{% copy_content record.pk prefix="ipaddress_" %} +""" + +IPADDRESS_ASSIGN_LINK = """ +{{ record }} +""" + +VRF_LINK = """ +{% if value %} + {{ record.vrf }} +{% elif object.vrf %} + {{ object.vrf }} +{% else %} + Global +{% endif %} +""" + +VLAN_LINK = """ +{% if record.pk %} + {{ record.vid }} +{% elif perms.ipam.add_vlan %} + {{ record.available }} VLAN{{ record.available|pluralize }} available +{% else %} + {{ record.available }} VLAN{{ record.available|pluralize }} available +{% endif %} +""" + +VLAN_PREFIXES = """ +{% for prefix in value.all %} + {{ prefix }}{% if not forloop.last %}
    {% endif %} +{% endfor %} +""" + +VLANGROUP_BUTTONS = """ +{% with next_vid=record.get_next_available_vid %} + {% if next_vid and perms.ipam.add_vlan %} + + + + {% endif %} +{% endwith %} +""" + +VLAN_MEMBER_TAGGED = """ +{% if record.untagged_vlan_id == object.pk %} + +{% else %} + +{% endif %} +""" diff --git a/netbox/ipam/tables/vlans.py b/netbox/ipam/tables/vlans.py index 5387ce24c..aa1900e41 100644 --- a/netbox/ipam/tables/vlans.py +++ b/netbox/ipam/tables/vlans.py @@ -8,6 +8,7 @@ from ipam.models import * from netbox.tables import NetBoxTable, columns from tenancy.tables import TenancyColumnsMixin, TenantColumn from virtualization.models import VMInterface +from .template_code import * __all__ = ( 'InterfaceVLANTable', @@ -16,44 +17,12 @@ __all__ = ( 'VLANMembersTable', 'VLANTable', 'VLANVirtualMachinesTable', + 'VLANTranslationPolicyTable', + 'VLANTranslationRuleTable', ) AVAILABLE_LABEL = mark_safe('Available') -VLAN_LINK = """ -{% if record.pk %} - {{ record.vid }} -{% elif perms.ipam.add_vlan %} - {{ record.available }} VLAN{{ record.available|pluralize }} available -{% else %} - {{ record.available }} VLAN{{ record.available|pluralize }} available -{% endif %} -""" - -VLAN_PREFIXES = """ -{% for prefix in value.all %} - {{ prefix }}{% if not forloop.last %}
    {% endif %} -{% endfor %} -""" - -VLANGROUP_BUTTONS = """ -{% with next_vid=record.get_next_available_vid %} - {% if next_vid and perms.ipam.add_vlan %} - - - - {% endif %} -{% endwith %} -""" - -VLAN_MEMBER_TAGGED = """ -{% if record.untagged_vlan_id == object.pk %} - -{% else %} - -{% endif %} -""" - # # VLAN groups @@ -130,6 +99,13 @@ class VLANTable(TenancyColumnsMixin, NetBoxTable): verbose_name=_('Role'), linkify=True ) + qinq_role = columns.ChoiceFieldColumn( + verbose_name=_('Q-in-Q role') + ) + qinq_svlan = tables.Column( + verbose_name=_('Q-in-Q SVLAN'), + linkify=True + ) l2vpn = tables.Column( accessor=tables.A('l2vpn_termination__l2vpn'), linkify=True, @@ -152,7 +128,7 @@ class VLANTable(TenancyColumnsMixin, NetBoxTable): model = VLAN fields = ( 'pk', 'id', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'tenant_group', 'status', 'role', - 'description', 'comments', 'tags', 'l2vpn', 'created', 'last_updated', + 'qinq_role', 'qinq_svlan', 'description', 'comments', 'tags', 'l2vpn', 'created', 'last_updated', ) default_columns = ('pk', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description') row_attrs = { @@ -244,3 +220,59 @@ class InterfaceVLANTable(NetBoxTable): def __init__(self, interface, *args, **kwargs): self.interface = interface super().__init__(*args, **kwargs) + + +# +# VLAN Translation +# + +class VLANTranslationPolicyTable(NetBoxTable): + name = tables.Column( + verbose_name=_('Name'), + linkify=True + ) + rule_count = columns.LinkedCountColumn( + viewname='ipam:vlantranslationrule_list', + url_params={'policy_id': 'pk'}, + verbose_name=_('Rules') + ) + description = tables.Column( + verbose_name=_('Description'), + ) + tags = columns.TagColumn( + url_name='ipam:vlantranslationpolicy_list' + ) + + class Meta(NetBoxTable.Meta): + model = VLANTranslationPolicy + fields = ( + 'pk', 'id', 'name', 'rule_count', 'description', 'tags', 'created', 'last_updated', + ) + default_columns = ('pk', 'name', 'rule_count', 'description') + + +class VLANTranslationRuleTable(NetBoxTable): + policy = tables.Column( + verbose_name=_('Policy'), + linkify=True + ) + local_vid = tables.Column( + verbose_name=_('Local VID'), + linkify=True + ) + remote_vid = tables.Column( + verbose_name=_('Remote VID'), + ) + description = tables.Column( + verbose_name=_('Description'), + ) + tags = columns.TagColumn( + url_name='ipam:vlantranslationrule_list' + ) + + class Meta(NetBoxTable.Meta): + model = VLANTranslationRule + fields = ( + 'pk', 'id', 'name', 'policy', 'local_vid', 'remote_vid', 'description', 'tags', 'created', 'last_updated', + ) + default_columns = ('pk', 'policy', 'local_vid', 'remote_vid', 'description') diff --git a/netbox/ipam/tests/test_api.py b/netbox/ipam/tests/test_api.py index 1d2cdf1b7..e9dcacc16 100644 --- a/netbox/ipam/tests/test_api.py +++ b/netbox/ipam/tests/test_api.py @@ -732,10 +732,19 @@ class FHRPGroupTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): - fhrp_groups = ( - FHRPGroup(protocol=FHRPGroupProtocolChoices.PROTOCOL_VRRP2, group_id=10, auth_type=FHRPGroupAuthTypeChoices.AUTHENTICATION_PLAINTEXT, auth_key='foobar123'), - FHRPGroup(protocol=FHRPGroupProtocolChoices.PROTOCOL_VRRP3, group_id=20, auth_type=FHRPGroupAuthTypeChoices.AUTHENTICATION_MD5, auth_key='foobar123'), + FHRPGroup( + protocol=FHRPGroupProtocolChoices.PROTOCOL_VRRP2, + group_id=10, + auth_type=FHRPGroupAuthTypeChoices.AUTHENTICATION_PLAINTEXT, + auth_key='foobar123', + ), + FHRPGroup( + protocol=FHRPGroupProtocolChoices.PROTOCOL_VRRP3, + group_id=20, + auth_type=FHRPGroupAuthTypeChoices.AUTHENTICATION_MD5, + auth_key='foobar123', + ), FHRPGroup(protocol=FHRPGroupProtocolChoices.PROTOCOL_HSRP, group_id=30), ) FHRPGroup.objects.bulk_create(fhrp_groups) @@ -980,6 +989,7 @@ class VLANTest(APIViewTestCases.APIViewTestCase): VLAN(name='VLAN 1', vid=1, group=vlan_groups[0]), VLAN(name='VLAN 2', vid=2, group=vlan_groups[0]), VLAN(name='VLAN 3', vid=3, group=vlan_groups[0]), + VLAN(name='SVLAN 1', vid=1001, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE), ) VLAN.objects.bulk_create(vlans) @@ -999,6 +1009,12 @@ class VLANTest(APIViewTestCases.APIViewTestCase): 'name': 'VLAN 6', 'group': vlan_groups[1].pk, }, + { + 'vid': 2001, + 'name': 'CVLAN 1', + 'qinq_role': VLANQinQRoleChoices.ROLE_CUSTOMER, + 'qinq_svlan': vlans[3].pk, + }, ] def test_delete_vlan_with_prefix(self): @@ -1020,6 +1036,112 @@ class VLANTest(APIViewTestCases.APIViewTestCase): self.assertTrue(content['detail'].startswith('Unable to delete object.')) +class VLANTranslationPolicyTest(APIViewTestCases.APIViewTestCase): + model = VLANTranslationPolicy + brief_fields = ['description', 'display', 'id', 'name', 'url',] + bulk_update_data = { + 'description': 'New description', + } + + @classmethod + def setUpTestData(cls): + + vlan_translation_policies = ( + VLANTranslationPolicy( + name='Policy 1', + description='foobar1', + ), + VLANTranslationPolicy( + name='Policy 2', + description='foobar2', + ), + VLANTranslationPolicy( + name='Policy 3', + description='foobar3', + ), + ) + VLANTranslationPolicy.objects.bulk_create(vlan_translation_policies) + + cls.create_data = [ + { + 'name': 'Policy 4', + 'description': 'foobar4', + }, + { + 'name': 'Policy 5', + 'description': 'foobar5', + }, + { + 'name': 'Policy 6', + 'description': 'foobar6', + }, + ] + + +class VLANTranslationRuleTest(APIViewTestCases.APIViewTestCase): + model = VLANTranslationRule + brief_fields = ['description', 'display', 'id', 'local_vid', 'policy', 'remote_vid', 'url'] + + @classmethod + def setUpTestData(cls): + + vlan_translation_policies = ( + VLANTranslationPolicy( + name='Policy 1', + description='foobar1', + ), + VLANTranslationPolicy( + name='Policy 2', + description='foobar2', + ), + ) + VLANTranslationPolicy.objects.bulk_create(vlan_translation_policies) + + vlan_translation_rules = ( + VLANTranslationRule( + policy=vlan_translation_policies[0], + local_vid=100, + remote_vid=200, + description='foo', + ), + VLANTranslationRule( + policy=vlan_translation_policies[0], + local_vid=101, + remote_vid=201, + description='bar', + ), + VLANTranslationRule( + policy=vlan_translation_policies[1], + local_vid=102, + remote_vid=202, + description='baz', + ), + ) + VLANTranslationRule.objects.bulk_create(vlan_translation_rules) + + cls.create_data = [ + { + 'policy': vlan_translation_policies[0].pk, + 'local_vid': 300, + 'remote_vid': 400, + }, + { + 'policy': vlan_translation_policies[0].pk, + 'local_vid': 301, + 'remote_vid': 401, + }, + { + 'policy': vlan_translation_policies[1].pk, + 'local_vid': 302, + 'remote_vid': 402, + }, + ] + + cls.bulk_update_data = { + 'policy': vlan_translation_policies[1].pk, + } + + class ServiceTemplateTest(APIViewTestCases.APIViewTestCase): model = ServiceTemplate brief_fields = ['description', 'display', 'id', 'name', 'ports', 'protocol', 'url'] diff --git a/netbox/ipam/tests/test_filtersets.py b/netbox/ipam/tests/test_filtersets.py index 4e38b1450..5455beb9c 100644 --- a/netbox/ipam/tests/test_filtersets.py +++ b/netbox/ipam/tests/test_filtersets.py @@ -496,8 +496,12 @@ class AggregateTestCase(TestCase, ChangeLoggedFilterSetTests): Tenant.objects.bulk_create(tenants) aggregates = ( - Aggregate(prefix='10.1.0.0/16', rir=rirs[0], tenant=tenants[0], date_added='2020-01-01', description='foobar1'), - Aggregate(prefix='10.2.0.0/16', rir=rirs[0], tenant=tenants[1], date_added='2020-01-02', description='foobar2'), + Aggregate( + prefix='10.1.0.0/16', rir=rirs[0], tenant=tenants[0], date_added='2020-01-01', description='foobar1' + ), + Aggregate( + prefix='10.2.0.0/16', rir=rirs[0], tenant=tenants[1], date_added='2020-01-02', description='foobar2' + ), Aggregate(prefix='10.3.0.0/16', rir=rirs[1], tenant=tenants[2], date_added='2020-01-03'), Aggregate(prefix='2001:db8:1::/48', rir=rirs[1], tenant=tenants[0], date_added='2020-01-04'), Aggregate(prefix='2001:db8:2::/48', rir=rirs[2], tenant=tenants[1], date_added='2020-01-05'), @@ -656,14 +660,80 @@ class PrefixTestCase(TestCase, ChangeLoggedFilterSetTests): Tenant.objects.bulk_create(tenants) prefixes = ( - Prefix(prefix='10.0.0.0/24', tenant=None, site=None, vrf=None, vlan=None, role=None, is_pool=True, mark_utilized=True, description='foobar1'), - Prefix(prefix='10.0.1.0/24', tenant=tenants[0], site=sites[0], vrf=vrfs[0], vlan=vlans[0], role=roles[0], description='foobar2'), - Prefix(prefix='10.0.2.0/24', tenant=tenants[1], site=sites[1], vrf=vrfs[1], vlan=vlans[1], role=roles[1], status=PrefixStatusChoices.STATUS_DEPRECATED), - Prefix(prefix='10.0.3.0/24', tenant=tenants[2], site=sites[2], vrf=vrfs[2], vlan=vlans[2], role=roles[2], status=PrefixStatusChoices.STATUS_RESERVED), - Prefix(prefix='2001:db8::/64', tenant=None, site=None, vrf=None, vlan=None, role=None, is_pool=True, mark_utilized=True), - Prefix(prefix='2001:db8:0:1::/64', tenant=tenants[0], site=sites[0], vrf=vrfs[0], vlan=vlans[0], role=roles[0]), - Prefix(prefix='2001:db8:0:2::/64', tenant=tenants[1], site=sites[1], vrf=vrfs[1], vlan=vlans[1], role=roles[1], status=PrefixStatusChoices.STATUS_DEPRECATED), - Prefix(prefix='2001:db8:0:3::/64', tenant=tenants[2], site=sites[2], vrf=vrfs[2], vlan=vlans[2], role=roles[2], status=PrefixStatusChoices.STATUS_RESERVED), + Prefix( + prefix='10.0.0.0/24', + tenant=None, + scope=None, + vrf=None, + vlan=None, + role=None, + is_pool=True, + mark_utilized=True, + description='foobar1', + ), + Prefix( + prefix='10.0.1.0/24', + tenant=tenants[0], + scope=sites[0], + vrf=vrfs[0], + vlan=vlans[0], + role=roles[0], + description='foobar2', + ), + Prefix( + prefix='10.0.2.0/24', + tenant=tenants[1], + scope=sites[1], + vrf=vrfs[1], + vlan=vlans[1], + role=roles[1], + status=PrefixStatusChoices.STATUS_DEPRECATED, + ), + Prefix( + prefix='10.0.3.0/24', + tenant=tenants[2], + scope=sites[2], + vrf=vrfs[2], + vlan=vlans[2], + role=roles[2], + status=PrefixStatusChoices.STATUS_RESERVED, + ), + Prefix( + prefix='2001:db8::/64', + tenant=None, + scope=None, + vrf=None, + vlan=None, + role=None, + is_pool=True, + mark_utilized=True, + ), + Prefix( + prefix='2001:db8:0:1::/64', + tenant=tenants[0], + scope=sites[0], + vrf=vrfs[0], + vlan=vlans[0], + role=roles[0] + ), + Prefix( + prefix='2001:db8:0:2::/64', + tenant=tenants[1], + scope=sites[1], + vrf=vrfs[1], + vlan=vlans[1], + role=roles[1], + status=PrefixStatusChoices.STATUS_DEPRECATED, + ), + Prefix( + prefix='2001:db8:0:3::/64', + tenant=tenants[2], + scope=sites[2], + vrf=vrfs[2], + vlan=vlans[2], + role=roles[2], + status=PrefixStatusChoices.STATUS_RESERVED, + ), Prefix(prefix='10.0.0.0/16'), Prefix(prefix='2001:db8::/32'), ) @@ -1365,7 +1435,10 @@ class FHRPGroupTestCase(TestCase, ChangeLoggedFilterSetTests): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_auth_type(self): - params = {'auth_type': [FHRPGroupAuthTypeChoices.AUTHENTICATION_PLAINTEXT, FHRPGroupAuthTypeChoices.AUTHENTICATION_MD5]} + params = {'auth_type': [ + FHRPGroupAuthTypeChoices.AUTHENTICATION_PLAINTEXT, + FHRPGroupAuthTypeChoices.AUTHENTICATION_MD5, + ]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_auth_key(self): @@ -1630,6 +1703,7 @@ class VLANTestCase(TestCase, ChangeLoggedFilterSetTests): Site(name='Site 4', slug='site-4', region=regions[0], group=site_groups[0]), Site(name='Site 5', slug='site-5', region=regions[1], group=site_groups[1]), Site(name='Site 6', slug='site-6', region=regions[2], group=site_groups[2]), + Site(name='Site 7', slug='site-7'), ) Site.objects.bulk_create(sites) @@ -1652,9 +1726,15 @@ class VLANTestCase(TestCase, ChangeLoggedFilterSetTests): device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1') role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') devices = ( - Device(name='Device 1', site=sites[0], location=locations[0], rack=racks[0], device_type=device_type, role=role), - Device(name='Device 2', site=sites[1], location=locations[1], rack=racks[1], device_type=device_type, role=role), - Device(name='Device 3', site=sites[2], location=locations[2], rack=racks[2], device_type=device_type, role=role), + Device( + name='Device 1', site=sites[0], location=locations[0], rack=racks[0], device_type=device_type, role=role + ), + Device( + name='Device 2', site=sites[1], location=locations[1], rack=racks[1], device_type=device_type, role=role + ), + Device( + name='Device 3', site=sites[2], location=locations[2], rack=racks[2], device_type=device_type, role=role + ), ) Device.objects.bulk_create(devices) @@ -1674,11 +1754,12 @@ class VLANTestCase(TestCase, ChangeLoggedFilterSetTests): cluster_type = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') clusters = ( - Cluster(name='Cluster 1', type=cluster_type, group=cluster_groups[0], site=sites[0]), - Cluster(name='Cluster 2', type=cluster_type, group=cluster_groups[1], site=sites[1]), - Cluster(name='Cluster 3', type=cluster_type, group=cluster_groups[2], site=sites[2]), + Cluster(name='Cluster 1', type=cluster_type, group=cluster_groups[0], scope=sites[0]), + Cluster(name='Cluster 2', type=cluster_type, group=cluster_groups[1], scope=sites[1]), + Cluster(name='Cluster 3', type=cluster_type, group=cluster_groups[2], scope=sites[2]), ) - Cluster.objects.bulk_create(clusters) + for cluster in clusters: + cluster.save() virtual_machines = ( VirtualMachine(name='Virtual Machine 1', cluster=clusters[0]), @@ -1771,22 +1852,98 @@ class VLANTestCase(TestCase, ChangeLoggedFilterSetTests): VLAN(vid=19, name='Cluster 1', group=groups[18]), VLAN(vid=20, name='Cluster 2', group=groups[19]), VLAN(vid=21, name='Cluster 3', group=groups[20]), - - VLAN(vid=101, name='VLAN 101', site=sites[3], group=groups[21], role=roles[0], tenant=tenants[0], status=VLANStatusChoices.STATUS_ACTIVE), - VLAN(vid=102, name='VLAN 102', site=sites[3], group=groups[21], role=roles[0], tenant=tenants[0], status=VLANStatusChoices.STATUS_ACTIVE), - VLAN(vid=201, name='VLAN 201', site=sites[4], group=groups[22], role=roles[1], tenant=tenants[1], status=VLANStatusChoices.STATUS_DEPRECATED), - VLAN(vid=202, name='VLAN 202', site=sites[4], group=groups[22], role=roles[1], tenant=tenants[1], status=VLANStatusChoices.STATUS_DEPRECATED), - VLAN(vid=301, name='VLAN 301', site=sites[5], group=groups[23], role=roles[2], tenant=tenants[2], status=VLANStatusChoices.STATUS_RESERVED), - VLAN(vid=302, name='VLAN 302', site=sites[5], group=groups[23], role=roles[2], tenant=tenants[2], status=VLANStatusChoices.STATUS_RESERVED), - + VLAN( + vid=101, + name='VLAN 101', + site=sites[3], + group=groups[21], + role=roles[0], + tenant=tenants[0], + status=VLANStatusChoices.STATUS_ACTIVE, + ), + VLAN( + vid=102, + name='VLAN 102', + site=sites[3], + group=groups[21], + role=roles[0], + tenant=tenants[0], + status=VLANStatusChoices.STATUS_ACTIVE, + ), + VLAN( + vid=201, + name='VLAN 201', + site=sites[4], + group=groups[22], + role=roles[1], + tenant=tenants[1], + status=VLANStatusChoices.STATUS_DEPRECATED, + ), + VLAN( + vid=202, + name='VLAN 202', + site=sites[4], + group=groups[22], + role=roles[1], + tenant=tenants[1], + status=VLANStatusChoices.STATUS_DEPRECATED, + ), + VLAN( + vid=301, + name='VLAN 301', + site=sites[5], + group=groups[23], + role=roles[2], + tenant=tenants[2], + status=VLANStatusChoices.STATUS_RESERVED, + ), + VLAN( + vid=302, + name='VLAN 302', + site=sites[5], + group=groups[23], + role=roles[2], + tenant=tenants[2], + status=VLANStatusChoices.STATUS_RESERVED, + ), # Create one globally available VLAN on a VLAN group VLAN(vid=500, name='VLAN Group 1', group=groups[24]), - # Create one globally available VLAN VLAN(vid=1000, name='Global VLAN'), + # Create some Q-in-Q service VLANs + VLAN(vid=2001, name='SVLAN 1', site=sites[6], qinq_role=VLANQinQRoleChoices.ROLE_SERVICE), + VLAN(vid=2002, name='SVLAN 2', site=sites[6], qinq_role=VLANQinQRoleChoices.ROLE_SERVICE), + VLAN(vid=2003, name='SVLAN 3', site=sites[6], qinq_role=VLANQinQRoleChoices.ROLE_SERVICE), ) VLAN.objects.bulk_create(vlans) + # Create Q-in-Q customer VLANs + VLAN.objects.bulk_create( + [ + VLAN( + vid=3001, + name='CVLAN 1', + site=sites[6], + qinq_svlan=vlans[29], + qinq_role=VLANQinQRoleChoices.ROLE_CUSTOMER, + ), + VLAN( + vid=3002, + name='CVLAN 2', + site=sites[6], + qinq_svlan=vlans[30], + qinq_role=VLANQinQRoleChoices.ROLE_CUSTOMER, + ), + VLAN( + vid=3003, + name='CVLAN 3', + site=sites[6], + qinq_svlan=vlans[31], + qinq_role=VLANQinQRoleChoices.ROLE_CUSTOMER, + ), + ] + ) + # Assign VLANs to device interfaces interfaces[0].untagged_vlan = vlans[0] interfaces[0].tagged_vlans.add(vlans[1]) @@ -1897,6 +2054,110 @@ class VLANTestCase(TestCase, ChangeLoggedFilterSetTests): params = {'vminterface_id': vminterface_id} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + def test_qinq_role(self): + params = {'qinq_role': [VLANQinQRoleChoices.ROLE_SERVICE, VLANQinQRoleChoices.ROLE_CUSTOMER]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6) + + def test_qinq_svlan(self): + vlans = VLAN.objects.filter(qinq_role=VLANQinQRoleChoices.ROLE_SERVICE)[:2] + params = {'qinq_svlan_id': [vlans[0].pk, vlans[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'qinq_svlan_vid': [vlans[0].vid, vlans[1].vid]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class VLANTranslationPolicyTestCase(TestCase, ChangeLoggedFilterSetTests): + queryset = VLANTranslationPolicy.objects.all() + filterset = VLANTranslationPolicyFilterSet + + @classmethod + def setUpTestData(cls): + + vlan_translation_policies = ( + VLANTranslationPolicy( + name='Policy 1', + description='foobar1', + ), + VLANTranslationPolicy( + name='Policy 2', + description='foobar2', + ), + VLANTranslationPolicy( + name='Policy 3', + description='foobar3', + ), + ) + VLANTranslationPolicy.objects.bulk_create(vlan_translation_policies) + + def test_name(self): + params = {'name': ['Policy 1', 'Policy 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_description(self): + params = {'description': ['foobar1', 'foobar2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + +class VLANTranslationRuleTestCase(TestCase, ChangeLoggedFilterSetTests): + queryset = VLANTranslationRule.objects.all() + filterset = VLANTranslationRuleFilterSet + + @classmethod + def setUpTestData(cls): + + vlan_translation_policies = ( + VLANTranslationPolicy( + name='Policy 1', + description='foobar1', + ), + VLANTranslationPolicy( + name='Policy 2', + description='foobar2', + ), + ) + VLANTranslationPolicy.objects.bulk_create(vlan_translation_policies) + + vlan_translation_rules = ( + VLANTranslationRule( + policy=vlan_translation_policies[0], + local_vid=100, + remote_vid=200, + description='foo', + ), + VLANTranslationRule( + policy=vlan_translation_policies[0], + local_vid=101, + remote_vid=201, + description='bar', + ), + VLANTranslationRule( + policy=vlan_translation_policies[1], + local_vid=100, + remote_vid=200, + description='baz', + ), + ) + VLANTranslationRule.objects.bulk_create(vlan_translation_rules) + + def test_policy_id(self): + policies = VLANTranslationPolicy.objects.all()[:2] + params = {'policy_id': [policies[0].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'policy': [policies[0].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_local_vid(self): + params = {'local_vid': [100]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_remote_vid(self): + params = {'remote_vid': [200]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_description(self): + params = {'description': ['foo', 'bar']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + class ServiceTemplateTestCase(TestCase, ChangeLoggedFilterSetTests): queryset = ServiceTemplate.objects.all() @@ -2007,12 +2268,39 @@ class ServiceTestCase(TestCase, ChangeLoggedFilterSetTests): VirtualMachine.objects.bulk_create(virtual_machines) services = ( - Service(device=devices[0], name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[1001], description='foobar1'), - Service(device=devices[1], name='Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[1002], description='foobar2'), + Service( + device=devices[0], + name='Service 1', + protocol=ServiceProtocolChoices.PROTOCOL_TCP, + ports=[1001], + description='foobar1', + ), + Service( + device=devices[1], + name='Service 2', + protocol=ServiceProtocolChoices.PROTOCOL_TCP, + ports=[1002], + description='foobar2', + ), Service(device=devices[2], name='Service 3', protocol=ServiceProtocolChoices.PROTOCOL_UDP, ports=[1003]), - Service(virtual_machine=virtual_machines[0], name='Service 4', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[2001]), - Service(virtual_machine=virtual_machines[1], name='Service 5', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[2002]), - Service(virtual_machine=virtual_machines[2], name='Service 6', protocol=ServiceProtocolChoices.PROTOCOL_UDP, ports=[2003]), + Service( + virtual_machine=virtual_machines[0], + name='Service 4', + protocol=ServiceProtocolChoices.PROTOCOL_TCP, + ports=[2001], + ), + Service( + virtual_machine=virtual_machines[1], + name='Service 5', + protocol=ServiceProtocolChoices.PROTOCOL_TCP, + ports=[2002], + ), + Service( + virtual_machine=virtual_machines[2], + name='Service 6', + protocol=ServiceProtocolChoices.PROTOCOL_UDP, + ports=[2003], + ), ) Service.objects.bulk_create(services) services[0].ipaddresses.add(ip_addresses[0]) diff --git a/netbox/ipam/tests/test_models.py b/netbox/ipam/tests/test_models.py index 8a5d918a9..62eb74123 100644 --- a/netbox/ipam/tests/test_models.py +++ b/netbox/ipam/tests/test_models.py @@ -36,6 +36,56 @@ class TestAggregate(TestCase): self.assertEqual(aggregate.get_utilization(), 100) +class TestIPRange(TestCase): + + def test_overlapping_range(self): + iprange_192_168 = IPRange.objects.create( + start_address=IPNetwork('192.168.0.1/22'), end_address=IPNetwork('192.168.0.49/22') + ) + iprange_192_168.clean() + iprange_3_1_99 = IPRange.objects.create( + start_address=IPNetwork('1.2.3.1/24'), end_address=IPNetwork('1.2.3.99/24') + ) + iprange_3_1_99.clean() + iprange_3_100_199 = IPRange.objects.create( + start_address=IPNetwork('1.2.3.100/24'), end_address=IPNetwork('1.2.3.199/24') + ) + iprange_3_100_199.clean() + iprange_3_200_255 = IPRange.objects.create( + start_address=IPNetwork('1.2.3.200/24'), end_address=IPNetwork('1.2.3.255/24') + ) + iprange_3_200_255.clean() + iprange_4_1_99 = IPRange.objects.create( + start_address=IPNetwork('1.2.4.1/24'), end_address=IPNetwork('1.2.4.99/24') + ) + iprange_4_1_99.clean() + iprange_4_200 = IPRange.objects.create( + start_address=IPNetwork('1.2.4.200/24'), end_address=IPNetwork('1.2.4.255/24') + ) + iprange_4_200.clean() + + # Overlapping range entirely within existing + with self.assertRaises(ValidationError): + iprange_3_123_124 = IPRange.objects.create( + start_address=IPNetwork('1.2.3.123/26'), end_address=IPNetwork('1.2.3.124/26') + ) + iprange_3_123_124.clean() + + # Overlapping range starting within existing + with self.assertRaises(ValidationError): + iprange_4_98_101 = IPRange.objects.create( + start_address=IPNetwork('1.2.4.98/24'), end_address=IPNetwork('1.2.4.101/24') + ) + iprange_4_98_101.clean() + + # Overlapping range ending within existing + with self.assertRaises(ValidationError): + iprange_4_198_201 = IPRange.objects.create( + start_address=IPNetwork('1.2.4.198/24'), end_address=IPNetwork('1.2.4.201/24') + ) + iprange_4_198_201.clean() + + class TestPrefix(TestCase): def test_get_duplicates(self): @@ -76,13 +126,30 @@ class TestPrefix(TestCase): def test_get_child_ranges(self): prefix = Prefix(prefix='192.168.0.16/28') prefix.save() - ranges = IPRange.objects.bulk_create(( - IPRange(start_address=IPNetwork('192.168.0.1/24'), end_address=IPNetwork('192.168.0.10/24'), size=10), # No overlap - IPRange(start_address=IPNetwork('192.168.0.11/24'), end_address=IPNetwork('192.168.0.17/24'), size=7), # Partial overlap - IPRange(start_address=IPNetwork('192.168.0.18/24'), end_address=IPNetwork('192.168.0.23/24'), size=6), # Full overlap - IPRange(start_address=IPNetwork('192.168.0.24/24'), end_address=IPNetwork('192.168.0.30/24'), size=7), # Full overlap - IPRange(start_address=IPNetwork('192.168.0.31/24'), end_address=IPNetwork('192.168.0.40/24'), size=10), # Partial overlap - )) + ranges = IPRange.objects.bulk_create( + ( + # No overlap + IPRange( + start_address=IPNetwork('192.168.0.1/24'), end_address=IPNetwork('192.168.0.10/24'), size=10 + ), + # Partial overlap + IPRange( + start_address=IPNetwork('192.168.0.11/24'), end_address=IPNetwork('192.168.0.17/24'), size=7 + ), + # Full overlap + IPRange( + start_address=IPNetwork('192.168.0.18/24'), end_address=IPNetwork('192.168.0.23/24'), size=6 + ), + # Full overlap + IPRange( + start_address=IPNetwork('192.168.0.24/24'), end_address=IPNetwork('192.168.0.30/24'), size=7 + ), + # Partial overlap + IPRange( + start_address=IPNetwork('192.168.0.31/24'), end_address=IPNetwork('192.168.0.40/24'), size=10 + ), + ) + ) child_ranges = prefix.get_child_ranges() @@ -557,3 +624,24 @@ class TestVLANGroup(TestCase): vlangroup.vid_ranges = string_to_ranges('2-2') vlangroup.full_clean() vlangroup.save() + + +class TestVLAN(TestCase): + + @classmethod + def setUpTestData(cls): + VLAN.objects.bulk_create(( + VLAN(name='VLAN 1', vid=1, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE), + )) + + def test_qinq_role(self): + svlan = VLAN.objects.filter(qinq_role=VLANQinQRoleChoices.ROLE_SERVICE).first() + + vlan = VLAN( + name='VLAN X', + vid=999, + qinq_role=VLANQinQRoleChoices.ROLE_SERVICE, + qinq_svlan=svlan + ) + with self.assertRaises(ValidationError): + vlan.full_clean() diff --git a/netbox/ipam/tests/test_ordering.py b/netbox/ipam/tests/test_ordering.py index 8d69af847..2f7a5342d 100644 --- a/netbox/ipam/tests/test_ordering.py +++ b/netbox/ipam/tests/test_ordering.py @@ -42,7 +42,7 @@ class PrefixOrderingTestCase(OrderingTestBase): """ This is a very basic test, which tests both prefixes without VRFs and prefixes with VRFs """ - vrf1, vrf2, vrf3 = list(VRF.objects.all()) + vrf1, vrf2 = VRF.objects.all()[:2] prefixes = ( Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=None, prefix=netaddr.IPNetwork('192.168.0.0/16')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, prefix=netaddr.IPNetwork('192.168.0.0/24')), @@ -92,8 +92,8 @@ class PrefixOrderingTestCase(OrderingTestBase): def test_prefix_complex_ordering(self): """ - This function tests a complex ordering of interwoven prefixes and vrfs. This is the current expected ordering of VRFs - This includes the testing of the Container status. + This function tests a complex ordering of interwoven prefixes and vrfs. This is the current expected ordering + of VRFs. This includes the testing of the Container status. The proper ordering, to get proper containerization should be: None:10.0.0.0/8 @@ -106,7 +106,7 @@ class PrefixOrderingTestCase(OrderingTestBase): VRF A:10.1.1.0/24 None: 192.168.0.0/16 """ - vrf1, vrf2, vrf3 = list(VRF.objects.all()) + vrf1 = VRF.objects.first() prefixes = [ Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=None, prefix=netaddr.IPNetwork('10.0.0.0/8')), Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=None, prefix=netaddr.IPNetwork('10.0.0.0/16')), @@ -125,12 +125,11 @@ class PrefixOrderingTestCase(OrderingTestBase): class IPAddressOrderingTestCase(OrderingTestBase): - def test_address_vrf_ordering(self): """ This function tests ordering with the inclusion of vrfs """ - vrf1, vrf2, vrf3 = list(VRF.objects.all()) + vrf1, vrf2 = VRF.objects.all()[:2] addresses = ( IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf1, address=netaddr.IPNetwork('10.0.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf1, address=netaddr.IPNetwork('10.0.1.1/24')), @@ -147,24 +146,54 @@ class IPAddressOrderingTestCase(OrderingTestBase): IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf1, address=netaddr.IPNetwork('10.2.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf1, address=netaddr.IPNetwork('10.2.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf1, address=netaddr.IPNetwork('10.2.4.1/24')), - - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.16.0.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.16.1.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.16.2.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.16.3.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.16.4.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.17.0.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.17.1.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.17.2.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.17.3.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.17.4.1/24')), - - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.0.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.1.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.2.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.3.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.4.1/24')), - IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.5.1/24')), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.16.0.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.16.1.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.16.2.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.16.3.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.16.4.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.17.0.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.17.1.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.17.2.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.17.3.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrf2, address=netaddr.IPNetwork('172.17.4.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.0.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.1.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.2.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.3.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.4.1/24') + ), + IPAddress( + status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.5.1/24') + ), ) IPAddress.objects.bulk_create(addresses) diff --git a/netbox/ipam/tests/test_views.py b/netbox/ipam/tests/test_views.py index 95b311878..d7d367bb7 100644 --- a/netbox/ipam/tests/test_views.py +++ b/netbox/ipam/tests/test_views.py @@ -1,5 +1,6 @@ import datetime +from django.contrib.contenttypes.models import ContentType from django.test import override_settings from django.urls import reverse from netaddr import IPNetwork @@ -409,9 +410,9 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase): Role.objects.bulk_create(roles) prefixes = ( - Prefix(prefix=IPNetwork('10.1.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]), - Prefix(prefix=IPNetwork('10.2.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]), - Prefix(prefix=IPNetwork('10.3.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]), + Prefix(prefix=IPNetwork('10.1.0.0/16'), vrf=vrfs[0], scope=sites[0], role=roles[0]), + Prefix(prefix=IPNetwork('10.2.0.0/16'), vrf=vrfs[0], scope=sites[0], role=roles[0]), + Prefix(prefix=IPNetwork('10.3.0.0/16'), vrf=vrfs[0], scope=sites[0], role=roles[0]), ) Prefix.objects.bulk_create(prefixes) @@ -419,7 +420,8 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase): cls.form_data = { 'prefix': IPNetwork('192.0.2.0/24'), - 'site': sites[1].pk, + 'scope_type': ContentType.objects.get_for_model(Site).pk, + 'scope': sites[1].pk, 'vrf': vrfs[1].pk, 'tenant': None, 'vlan': None, @@ -430,11 +432,12 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase): 'tags': [t.pk for t in tags], } + site = sites[0].pk cls.csv_data = ( - "vrf,prefix,status", - "VRF 1,10.4.0.0/16,active", - "VRF 1,10.5.0.0/16,active", - "VRF 1,10.6.0.0/16,active", + "vrf,prefix,status,scope_type,scope_id", + f"VRF 1,10.4.0.0/16,active,dcim.site,{site}", + f"VRF 1,10.5.0.0/16,active,dcim.site,{site}", + f"VRF 1,10.6.0.0/16,active,dcim.site,{site}", ) cls.csv_update_data = ( @@ -445,7 +448,6 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase): ) cls.bulk_edit_data = { - 'site': sites[1].pk, 'vrf': vrfs[1].pk, 'tenant': None, 'status': PrefixStatusChoices.STATUS_RESERVED, @@ -501,11 +503,13 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase): """ Custom import test for YAML-based imports (versus CSV) """ - IMPORT_DATA = """ + site = Site.objects.get(name='Site 1') + IMPORT_DATA = f""" prefix: 10.1.1.0/24 status: active vlan: 101 -site: Site 1 +scope_type: dcim.site +scope_id: {site.pk} """ # Note, a site is not tied to the VLAN to verify the fix for #12622 VLAN.objects.create(vid=101, name='VLAN101') @@ -517,25 +521,27 @@ site: Site 1 'data': IMPORT_DATA, 'format': 'yaml' } - response = self.client.post(reverse('ipam:prefix_import'), data=form_data, follow=True) + response = self.client.post(reverse('ipam:prefix_bulk_import'), data=form_data, follow=True) self.assertHttpStatus(response, 200) prefix = Prefix.objects.get(prefix='10.1.1.0/24') self.assertEqual(prefix.status, PrefixStatusChoices.STATUS_ACTIVE) self.assertEqual(prefix.vlan.vid, 101) - self.assertEqual(prefix.site.name, "Site 1") + self.assertEqual(prefix.scope, site) @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) def test_prefix_import_with_vlan_group(self): """ This test covers a unique import edge case where VLAN group is specified during the import. """ - IMPORT_DATA = """ + site = Site.objects.get(name='Site 1') + IMPORT_DATA = f""" prefix: 10.1.2.0/24 status: active -vlan: 102 -site: Site 1 +scope_type: dcim.site +scope_id: {site.pk} vlan_group: Group 1 +vlan: 102 """ vlan_group = VLANGroup.objects.create(name='Group 1', slug='group-1', scope=Site.objects.get(name="Site 1")) VLAN.objects.create(vid=102, name='VLAN102', group=vlan_group) @@ -547,13 +553,13 @@ vlan_group: Group 1 'data': IMPORT_DATA, 'format': 'yaml' } - response = self.client.post(reverse('ipam:prefix_import'), data=form_data, follow=True) + response = self.client.post(reverse('ipam:prefix_bulk_import'), data=form_data, follow=True) self.assertHttpStatus(response, 200) prefix = Prefix.objects.get(prefix='10.1.2.0/24') self.assertEqual(prefix.status, PrefixStatusChoices.STATUS_ACTIVE) self.assertEqual(prefix.vlan.vid, 102) - self.assertEqual(prefix.site.name, "Site 1") + self.assertEqual(prefix.scope, site) class IPRangeTestCase(ViewTestCases.PrimaryObjectViewTestCase): @@ -701,11 +707,23 @@ class FHRPGroupTestCase(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): - fhrp_groups = ( - FHRPGroup(protocol=FHRPGroupProtocolChoices.PROTOCOL_VRRP2, group_id=10, auth_type=FHRPGroupAuthTypeChoices.AUTHENTICATION_PLAINTEXT, auth_key='foobar123'), - FHRPGroup(protocol=FHRPGroupProtocolChoices.PROTOCOL_VRRP3, group_id=20, auth_type=FHRPGroupAuthTypeChoices.AUTHENTICATION_MD5, auth_key='foobar123'), - FHRPGroup(protocol=FHRPGroupProtocolChoices.PROTOCOL_HSRP, group_id=30), + FHRPGroup( + protocol=FHRPGroupProtocolChoices.PROTOCOL_VRRP2, + group_id=10, + auth_type=FHRPGroupAuthTypeChoices.AUTHENTICATION_PLAINTEXT, + auth_key='foobar123', + ), + FHRPGroup( + protocol=FHRPGroupProtocolChoices.PROTOCOL_VRRP3, + group_id=20, + auth_type=FHRPGroupAuthTypeChoices.AUTHENTICATION_MD5, + auth_key='foobar123', + ), + FHRPGroup( + protocol=FHRPGroupProtocolChoices.PROTOCOL_HSRP, + group_id=30 + ), ) FHRPGroup.objects.bulk_create(fhrp_groups) @@ -857,6 +875,121 @@ class VLANTestCase(ViewTestCases.PrimaryObjectViewTestCase): } +class VLANTranslationPolicyTestCase(ViewTestCases.PrimaryObjectViewTestCase): + model = VLANTranslationPolicy + + @classmethod + def setUpTestData(cls): + + vlan_translation_policies = ( + VLANTranslationPolicy( + name='Policy 1', + description='foobar1', + ), + VLANTranslationPolicy( + name='Policy 2', + description='foobar2', + ), + VLANTranslationPolicy( + name='Policy 3', + description='foobar3', + ), + ) + VLANTranslationPolicy.objects.bulk_create(vlan_translation_policies) + + tags = create_tags('Alpha', 'Bravo', 'Charlie') + + cls.form_data = { + 'name': 'Policy999', + 'description': 'A new VLAN Translation Policy', + 'tags': [t.pk for t in tags], + } + + cls.csv_data = ( + "name,description", + "Policy101,foobar1", + "Policy102,foobar2", + "Policy103,foobar3", + ) + + cls.csv_update_data = ( + "id,name,description", + f"{vlan_translation_policies[0].pk},Policy101,New description 1", + f"{vlan_translation_policies[1].pk},Policy102,New description 2", + f"{vlan_translation_policies[2].pk},Policy103,New description 3", + ) + + cls.bulk_edit_data = { + 'description': 'New description', + } + + +class VLANTranslationRuleTestCase(ViewTestCases.PrimaryObjectViewTestCase): + model = VLANTranslationRule + + @classmethod + def setUpTestData(cls): + + vlan_translation_policies = ( + VLANTranslationPolicy( + name='Policy 1', + description='foobar1', + ), + VLANTranslationPolicy( + name='Policy 2', + description='foobar2', + ), + VLANTranslationPolicy( + name='Policy 3', + description='foobar3', + ), + ) + VLANTranslationPolicy.objects.bulk_create(vlan_translation_policies) + + vlan_translation_rules = ( + VLANTranslationRule( + policy=vlan_translation_policies[0], + local_vid=100, + remote_vid=200, + ), + VLANTranslationRule( + policy=vlan_translation_policies[0], + local_vid=101, + remote_vid=201, + ), + VLANTranslationRule( + policy=vlan_translation_policies[1], + local_vid=102, + remote_vid=202, + ), + ) + VLANTranslationRule.objects.bulk_create(vlan_translation_rules) + + cls.form_data = { + 'policy': vlan_translation_policies[0].pk, + 'local_vid': 300, + 'remote_vid': 400, + } + + cls.csv_data = ( + "policy,local_vid,remote_vid", + f"{vlan_translation_policies[0].name},103,203", + f"{vlan_translation_policies[0].name},104,204", + f"{vlan_translation_policies[1].name},105,205", + ) + + cls.csv_update_data = ( + "id,local_vid,remote_vid", + f"{vlan_translation_rules[0].pk},105,205", + f"{vlan_translation_rules[1].pk},106,206", + f"{vlan_translation_rules[2].pk},107,207", + ) + + cls.bulk_edit_data = { + 'policy': vlan_translation_policies[2].pk, + } + + class ServiceTemplateTestCase(ViewTestCases.PrimaryObjectViewTestCase): model = ServiceTemplate diff --git a/netbox/ipam/urls.py b/netbox/ipam/urls.py index 61deeff4b..c55e874a1 100644 --- a/netbox/ipam/urls.py +++ b/netbox/ipam/urls.py @@ -1,134 +1,62 @@ from django.urls import include, path from utilities.urls import get_model_urls -from . import views +from . import views # noqa F401 app_name = 'ipam' urlpatterns = [ - # ASN ranges - path('asn-ranges/', views.ASNRangeListView.as_view(), name='asnrange_list'), - path('asn-ranges/add/', views.ASNRangeEditView.as_view(), name='asnrange_add'), - path('asn-ranges/import/', views.ASNRangeBulkImportView.as_view(), name='asnrange_import'), - path('asn-ranges/edit/', views.ASNRangeBulkEditView.as_view(), name='asnrange_bulk_edit'), - path('asn-ranges/delete/', views.ASNRangeBulkDeleteView.as_view(), name='asnrange_bulk_delete'), + path('asn-ranges/', include(get_model_urls('ipam', 'asnrange', detail=False))), path('asn-ranges//', include(get_model_urls('ipam', 'asnrange'))), - # ASNs - path('asns/', views.ASNListView.as_view(), name='asn_list'), - path('asns/add/', views.ASNEditView.as_view(), name='asn_add'), - path('asns/import/', views.ASNBulkImportView.as_view(), name='asn_import'), - path('asns/edit/', views.ASNBulkEditView.as_view(), name='asn_bulk_edit'), - path('asns/delete/', views.ASNBulkDeleteView.as_view(), name='asn_bulk_delete'), + path('asns/', include(get_model_urls('ipam', 'asn', detail=False))), path('asns//', include(get_model_urls('ipam', 'asn'))), - # VRFs - path('vrfs/', views.VRFListView.as_view(), name='vrf_list'), - path('vrfs/add/', views.VRFEditView.as_view(), name='vrf_add'), - path('vrfs/import/', views.VRFBulkImportView.as_view(), name='vrf_import'), - path('vrfs/edit/', views.VRFBulkEditView.as_view(), name='vrf_bulk_edit'), - path('vrfs/delete/', views.VRFBulkDeleteView.as_view(), name='vrf_bulk_delete'), + path('vrfs/', include(get_model_urls('ipam', 'vrf', detail=False))), path('vrfs//', include(get_model_urls('ipam', 'vrf'))), - # Route targets - path('route-targets/', views.RouteTargetListView.as_view(), name='routetarget_list'), - path('route-targets/add/', views.RouteTargetEditView.as_view(), name='routetarget_add'), - path('route-targets/import/', views.RouteTargetBulkImportView.as_view(), name='routetarget_import'), - path('route-targets/edit/', views.RouteTargetBulkEditView.as_view(), name='routetarget_bulk_edit'), - path('route-targets/delete/', views.RouteTargetBulkDeleteView.as_view(), name='routetarget_bulk_delete'), + path('route-targets/', include(get_model_urls('ipam', 'routetarget', detail=False))), path('route-targets//', include(get_model_urls('ipam', 'routetarget'))), - # RIRs - path('rirs/', views.RIRListView.as_view(), name='rir_list'), - path('rirs/add/', views.RIREditView.as_view(), name='rir_add'), - path('rirs/import/', views.RIRBulkImportView.as_view(), name='rir_import'), - path('rirs/edit/', views.RIRBulkEditView.as_view(), name='rir_bulk_edit'), - path('rirs/delete/', views.RIRBulkDeleteView.as_view(), name='rir_bulk_delete'), + path('rirs/', include(get_model_urls('ipam', 'rir', detail=False))), path('rirs//', include(get_model_urls('ipam', 'rir'))), - # Aggregates - path('aggregates/', views.AggregateListView.as_view(), name='aggregate_list'), - path('aggregates/add/', views.AggregateEditView.as_view(), name='aggregate_add'), - path('aggregates/import/', views.AggregateBulkImportView.as_view(), name='aggregate_import'), - path('aggregates/edit/', views.AggregateBulkEditView.as_view(), name='aggregate_bulk_edit'), - path('aggregates/delete/', views.AggregateBulkDeleteView.as_view(), name='aggregate_bulk_delete'), + path('aggregates/', include(get_model_urls('ipam', 'aggregate', detail=False))), path('aggregates//', include(get_model_urls('ipam', 'aggregate'))), - # Roles - path('roles/', views.RoleListView.as_view(), name='role_list'), - path('roles/add/', views.RoleEditView.as_view(), name='role_add'), - path('roles/import/', views.RoleBulkImportView.as_view(), name='role_import'), - path('roles/edit/', views.RoleBulkEditView.as_view(), name='role_bulk_edit'), - path('roles/delete/', views.RoleBulkDeleteView.as_view(), name='role_bulk_delete'), + path('roles/', include(get_model_urls('ipam', 'role', detail=False))), path('roles//', include(get_model_urls('ipam', 'role'))), - # Prefixes - path('prefixes/', views.PrefixListView.as_view(), name='prefix_list'), - path('prefixes/add/', views.PrefixEditView.as_view(), name='prefix_add'), - path('prefixes/import/', views.PrefixBulkImportView.as_view(), name='prefix_import'), - path('prefixes/edit/', views.PrefixBulkEditView.as_view(), name='prefix_bulk_edit'), - path('prefixes/delete/', views.PrefixBulkDeleteView.as_view(), name='prefix_bulk_delete'), + path('prefixes/', include(get_model_urls('ipam', 'prefix', detail=False))), path('prefixes//', include(get_model_urls('ipam', 'prefix'))), - # IP ranges - path('ip-ranges/', views.IPRangeListView.as_view(), name='iprange_list'), - path('ip-ranges/add/', views.IPRangeEditView.as_view(), name='iprange_add'), - path('ip-ranges/import/', views.IPRangeBulkImportView.as_view(), name='iprange_import'), - path('ip-ranges/edit/', views.IPRangeBulkEditView.as_view(), name='iprange_bulk_edit'), - path('ip-ranges/delete/', views.IPRangeBulkDeleteView.as_view(), name='iprange_bulk_delete'), + path('ip-ranges/', include(get_model_urls('ipam', 'iprange', detail=False))), path('ip-ranges//', include(get_model_urls('ipam', 'iprange'))), - # IP addresses - path('ip-addresses/', views.IPAddressListView.as_view(), name='ipaddress_list'), - path('ip-addresses/add/', views.IPAddressEditView.as_view(), name='ipaddress_add'), - path('ip-addresses/bulk-add/', views.IPAddressBulkCreateView.as_view(), name='ipaddress_bulk_add'), - path('ip-addresses/import/', views.IPAddressBulkImportView.as_view(), name='ipaddress_import'), - path('ip-addresses/edit/', views.IPAddressBulkEditView.as_view(), name='ipaddress_bulk_edit'), - path('ip-addresses/delete/', views.IPAddressBulkDeleteView.as_view(), name='ipaddress_bulk_delete'), - path('ip-addresses/assign/', views.IPAddressAssignView.as_view(), name='ipaddress_assign'), + path('ip-addresses/', include(get_model_urls('ipam', 'ipaddress', detail=False))), path('ip-addresses//', include(get_model_urls('ipam', 'ipaddress'))), - # FHRP groups - path('fhrp-groups/', views.FHRPGroupListView.as_view(), name='fhrpgroup_list'), - path('fhrp-groups/add/', views.FHRPGroupEditView.as_view(), name='fhrpgroup_add'), - path('fhrp-groups/import/', views.FHRPGroupBulkImportView.as_view(), name='fhrpgroup_import'), - path('fhrp-groups/edit/', views.FHRPGroupBulkEditView.as_view(), name='fhrpgroup_bulk_edit'), - path('fhrp-groups/delete/', views.FHRPGroupBulkDeleteView.as_view(), name='fhrpgroup_bulk_delete'), + path('fhrp-groups/', include(get_model_urls('ipam', 'fhrpgroup', detail=False))), path('fhrp-groups//', include(get_model_urls('ipam', 'fhrpgroup'))), - # FHRP group assignments - path('fhrp-group-assignments/add/', views.FHRPGroupAssignmentEditView.as_view(), name='fhrpgroupassignment_add'), + path('fhrp-group-assignments/', include(get_model_urls('ipam', 'fhrpgroupassignment', detail=False))), path('fhrp-group-assignments//', include(get_model_urls('ipam', 'fhrpgroupassignment'))), - # VLAN groups - path('vlan-groups/', views.VLANGroupListView.as_view(), name='vlangroup_list'), - path('vlan-groups/add/', views.VLANGroupEditView.as_view(), name='vlangroup_add'), - path('vlan-groups/import/', views.VLANGroupBulkImportView.as_view(), name='vlangroup_import'), - path('vlan-groups/edit/', views.VLANGroupBulkEditView.as_view(), name='vlangroup_bulk_edit'), - path('vlan-groups/delete/', views.VLANGroupBulkDeleteView.as_view(), name='vlangroup_bulk_delete'), + path('vlan-groups/', include(get_model_urls('ipam', 'vlangroup', detail=False))), path('vlan-groups//', include(get_model_urls('ipam', 'vlangroup'))), - # VLANs - path('vlans/', views.VLANListView.as_view(), name='vlan_list'), - path('vlans/add/', views.VLANEditView.as_view(), name='vlan_add'), - path('vlans/import/', views.VLANBulkImportView.as_view(), name='vlan_import'), - path('vlans/edit/', views.VLANBulkEditView.as_view(), name='vlan_bulk_edit'), - path('vlans/delete/', views.VLANBulkDeleteView.as_view(), name='vlan_bulk_delete'), + path('vlans/', include(get_model_urls('ipam', 'vlan', detail=False))), path('vlans//', include(get_model_urls('ipam', 'vlan'))), - # Service templates - path('service-templates/', views.ServiceTemplateListView.as_view(), name='servicetemplate_list'), - path('service-templates/add/', views.ServiceTemplateEditView.as_view(), name='servicetemplate_add'), - path('service-templates/import/', views.ServiceTemplateBulkImportView.as_view(), name='servicetemplate_import'), - path('service-templates/edit/', views.ServiceTemplateBulkEditView.as_view(), name='servicetemplate_bulk_edit'), - path('service-templates/delete/', views.ServiceTemplateBulkDeleteView.as_view(), name='servicetemplate_bulk_delete'), + path('vlan-translation-policies/', include(get_model_urls('ipam', 'vlantranslationpolicy', detail=False))), + path('vlan-translation-policies//', include(get_model_urls('ipam', 'vlantranslationpolicy'))), + + path('vlan-translation-rules/', include(get_model_urls('ipam', 'vlantranslationrule', detail=False))), + path('vlan-translation-rules//', include(get_model_urls('ipam', 'vlantranslationrule'))), + + path('service-templates/', include(get_model_urls('ipam', 'servicetemplate', detail=False))), path('service-templates//', include(get_model_urls('ipam', 'servicetemplate'))), - # Services - path('services/', views.ServiceListView.as_view(), name='service_list'), - path('services/add/', views.ServiceCreateView.as_view(), name='service_add'), - path('services/import/', views.ServiceBulkImportView.as_view(), name='service_import'), - path('services/edit/', views.ServiceBulkEditView.as_view(), name='service_bulk_edit'), - path('services/delete/', views.ServiceBulkDeleteView.as_view(), name='service_bulk_delete'), + path('services/', include(get_model_urls('ipam', 'service', detail=False))), path('services//', include(get_model_urls('ipam', 'service'))), ] diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 67d56f15e..c606c1088 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -3,12 +3,13 @@ from django.db.models import Prefetch from django.db.models.expressions import RawSQL from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse -from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy as _ from circuits.models import Provider from dcim.filtersets import InterfaceFilterSet from dcim.forms import InterfaceFilterForm from dcim.models import Interface, Site +from ipam.tables import VLANTranslationRuleTable from netbox.views import generic from tenancy.views import ObjectContactsView from utilities.query import count_related @@ -28,6 +29,7 @@ from .utils import add_requested_prefixes, add_available_ipaddresses, add_availa # VRFs # +@register_model_view(VRF, 'list', path='', detail=False) class VRFListView(generic.ObjectListView): queryset = VRF.objects.all() filterset = filtersets.VRFFilterSet @@ -56,6 +58,7 @@ class VRFView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(VRF, 'add', detail=False) @register_model_view(VRF, 'edit') class VRFEditView(generic.ObjectEditView): queryset = VRF.objects.all() @@ -67,11 +70,13 @@ class VRFDeleteView(generic.ObjectDeleteView): queryset = VRF.objects.all() +@register_model_view(VRF, 'bulk_import', detail=False) class VRFBulkImportView(generic.BulkImportView): queryset = VRF.objects.all() model_form = forms.VRFImportForm +@register_model_view(VRF, 'bulk_edit', path='edit', detail=False) class VRFBulkEditView(generic.BulkEditView): queryset = VRF.objects.all() filterset = filtersets.VRFFilterSet @@ -79,6 +84,7 @@ class VRFBulkEditView(generic.BulkEditView): form = forms.VRFBulkEditForm +@register_model_view(VRF, 'bulk_delete', path='delete', detail=False) class VRFBulkDeleteView(generic.BulkDeleteView): queryset = VRF.objects.all() filterset = filtersets.VRFFilterSet @@ -89,6 +95,7 @@ class VRFBulkDeleteView(generic.BulkDeleteView): # Route targets # +@register_model_view(RouteTarget, 'list', path='', detail=False) class RouteTargetListView(generic.ObjectListView): queryset = RouteTarget.objects.all() filterset = filtersets.RouteTargetFilterSet @@ -101,6 +108,7 @@ class RouteTargetView(generic.ObjectView): queryset = RouteTarget.objects.all() +@register_model_view(RouteTarget, 'add', detail=False) @register_model_view(RouteTarget, 'edit') class RouteTargetEditView(generic.ObjectEditView): queryset = RouteTarget.objects.all() @@ -112,11 +120,13 @@ class RouteTargetDeleteView(generic.ObjectDeleteView): queryset = RouteTarget.objects.all() +@register_model_view(RouteTarget, 'bulk_import', detail=False) class RouteTargetBulkImportView(generic.BulkImportView): queryset = RouteTarget.objects.all() model_form = forms.RouteTargetImportForm +@register_model_view(RouteTarget, 'bulk_edit', path='edit', detail=False) class RouteTargetBulkEditView(generic.BulkEditView): queryset = RouteTarget.objects.all() filterset = filtersets.RouteTargetFilterSet @@ -124,6 +134,7 @@ class RouteTargetBulkEditView(generic.BulkEditView): form = forms.RouteTargetBulkEditForm +@register_model_view(RouteTarget, 'bulk_delete', path='delete', detail=False) class RouteTargetBulkDeleteView(generic.BulkDeleteView): queryset = RouteTarget.objects.all() filterset = filtersets.RouteTargetFilterSet @@ -134,6 +145,7 @@ class RouteTargetBulkDeleteView(generic.BulkDeleteView): # RIRs # +@register_model_view(RIR, 'list', path='', detail=False) class RIRListView(generic.ObjectListView): queryset = RIR.objects.annotate( aggregate_count=count_related(Aggregate, 'rir') @@ -153,6 +165,7 @@ class RIRView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(RIR, 'add', detail=False) @register_model_view(RIR, 'edit') class RIREditView(generic.ObjectEditView): queryset = RIR.objects.all() @@ -164,11 +177,13 @@ class RIRDeleteView(generic.ObjectDeleteView): queryset = RIR.objects.all() +@register_model_view(RIR, 'bulk_import', detail=False) class RIRBulkImportView(generic.BulkImportView): queryset = RIR.objects.all() model_form = forms.RIRImportForm +@register_model_view(RIR, 'bulk_edit', path='edit', detail=False) class RIRBulkEditView(generic.BulkEditView): queryset = RIR.objects.annotate( aggregate_count=count_related(Aggregate, 'rir') @@ -178,6 +193,7 @@ class RIRBulkEditView(generic.BulkEditView): form = forms.RIRBulkEditForm +@register_model_view(RIR, 'bulk_delete', path='delete', detail=False) class RIRBulkDeleteView(generic.BulkDeleteView): queryset = RIR.objects.annotate( aggregate_count=count_related(Aggregate, 'rir') @@ -190,6 +206,7 @@ class RIRBulkDeleteView(generic.BulkDeleteView): # ASN ranges # +@register_model_view(ASNRange, 'list', path='', detail=False) class ASNRangeListView(generic.ObjectListView): queryset = ASNRange.objects.annotate_asn_counts() filterset = filtersets.ASNRangeFilterSet @@ -223,6 +240,7 @@ class ASNRangeASNsView(generic.ObjectChildrenView): ) +@register_model_view(ASNRange, 'add', detail=False) @register_model_view(ASNRange, 'edit') class ASNRangeEditView(generic.ObjectEditView): queryset = ASNRange.objects.all() @@ -234,11 +252,13 @@ class ASNRangeDeleteView(generic.ObjectDeleteView): queryset = ASNRange.objects.all() +@register_model_view(ASNRange, 'bulk_import', detail=False) class ASNRangeBulkImportView(generic.BulkImportView): queryset = ASNRange.objects.all() model_form = forms.ASNRangeImportForm +@register_model_view(ASNRange, 'bulk_edit', path='edit', detail=False) class ASNRangeBulkEditView(generic.BulkEditView): queryset = ASNRange.objects.annotate_asn_counts() filterset = filtersets.ASNRangeFilterSet @@ -246,6 +266,7 @@ class ASNRangeBulkEditView(generic.BulkEditView): form = forms.ASNRangeBulkEditForm +@register_model_view(ASNRange, 'bulk_delete', path='delete', detail=False) class ASNRangeBulkDeleteView(generic.BulkDeleteView): queryset = ASNRange.objects.annotate_asn_counts() filterset = filtersets.ASNRangeFilterSet @@ -256,6 +277,7 @@ class ASNRangeBulkDeleteView(generic.BulkDeleteView): # ASNs # +@register_model_view(ASN, 'list', path='', detail=False) class ASNListView(generic.ObjectListView): queryset = ASN.objects.annotate( site_count=count_related(Site, 'asns'), @@ -283,6 +305,7 @@ class ASNView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(ASN, 'add', detail=False) @register_model_view(ASN, 'edit') class ASNEditView(generic.ObjectEditView): queryset = ASN.objects.all() @@ -294,11 +317,13 @@ class ASNDeleteView(generic.ObjectDeleteView): queryset = ASN.objects.all() +@register_model_view(ASN, 'bulk_import', detail=False) class ASNBulkImportView(generic.BulkImportView): queryset = ASN.objects.all() model_form = forms.ASNImportForm +@register_model_view(ASN, 'bulk_edit', path='edit', detail=False) class ASNBulkEditView(generic.BulkEditView): queryset = ASN.objects.annotate( site_count=count_related(Site, 'asns') @@ -308,6 +333,7 @@ class ASNBulkEditView(generic.BulkEditView): form = forms.ASNBulkEditForm +@register_model_view(ASN, 'bulk_delete', path='delete', detail=False) class ASNBulkDeleteView(generic.BulkDeleteView): queryset = ASN.objects.annotate( site_count=count_related(Site, 'asns') @@ -320,6 +346,7 @@ class ASNBulkDeleteView(generic.BulkDeleteView): # Aggregates # +@register_model_view(Aggregate, 'list', path='', detail=False) class AggregateListView(generic.ObjectListView): queryset = Aggregate.objects.annotate( child_count=RawSQL('SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix', ()) @@ -352,7 +379,7 @@ class AggregatePrefixesView(generic.ObjectChildrenView): def get_children(self, request, parent): return Prefix.objects.restrict(request.user, 'view').filter( prefix__net_contained_or_equal=str(parent.prefix) - ).prefetch_related('site', 'role', 'tenant', 'tenant__group', 'vlan') + ).prefetch_related('scope', 'role', 'tenant', 'tenant__group', 'vlan') def prep_table_data(self, request, queryset, parent): # Determine whether to show assigned prefixes, available prefixes, or both @@ -370,6 +397,7 @@ class AggregatePrefixesView(generic.ObjectChildrenView): } +@register_model_view(Aggregate, 'add', detail=False) @register_model_view(Aggregate, 'edit') class AggregateEditView(generic.ObjectEditView): queryset = Aggregate.objects.all() @@ -381,11 +409,13 @@ class AggregateDeleteView(generic.ObjectDeleteView): queryset = Aggregate.objects.all() +@register_model_view(Aggregate, 'bulk_import', detail=False) class AggregateBulkImportView(generic.BulkImportView): queryset = Aggregate.objects.all() model_form = forms.AggregateImportForm +@register_model_view(Aggregate, 'bulk_edit', path='edit', detail=False) class AggregateBulkEditView(generic.BulkEditView): queryset = Aggregate.objects.annotate( child_count=RawSQL('SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix', ()) @@ -395,6 +425,7 @@ class AggregateBulkEditView(generic.BulkEditView): form = forms.AggregateBulkEditForm +@register_model_view(Aggregate, 'bulk_delete', path='delete', detail=False) class AggregateBulkDeleteView(generic.BulkDeleteView): queryset = Aggregate.objects.annotate( child_count=RawSQL('SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix', ()) @@ -412,6 +443,7 @@ class AggregateContactsView(ObjectContactsView): # Prefix/VLAN roles # +@register_model_view(Role, 'list', path='', detail=False) class RoleListView(generic.ObjectListView): queryset = Role.objects.annotate( prefix_count=count_related(Prefix, 'role'), @@ -433,6 +465,7 @@ class RoleView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(Role, 'add', detail=False) @register_model_view(Role, 'edit') class RoleEditView(generic.ObjectEditView): queryset = Role.objects.all() @@ -444,11 +477,13 @@ class RoleDeleteView(generic.ObjectDeleteView): queryset = Role.objects.all() +@register_model_view(Role, 'bulk_import', detail=False) class RoleBulkImportView(generic.BulkImportView): queryset = Role.objects.all() model_form = forms.RoleImportForm +@register_model_view(Role, 'bulk_edit', path='edit', detail=False) class RoleBulkEditView(generic.BulkEditView): queryset = Role.objects.all() filterset = filtersets.RoleFilterSet @@ -456,6 +491,7 @@ class RoleBulkEditView(generic.BulkEditView): form = forms.RoleBulkEditForm +@register_model_view(Role, 'bulk_delete', path='delete', detail=False) class RoleBulkDeleteView(generic.BulkDeleteView): queryset = Role.objects.all() filterset = filtersets.RoleFilterSet @@ -466,6 +502,7 @@ class RoleBulkDeleteView(generic.BulkDeleteView): # Prefixes # +@register_model_view(Prefix, 'list', path='', detail=False) class PrefixListView(generic.ObjectListView): queryset = Prefix.objects.all() filterset = filtersets.PrefixFilterSet @@ -492,7 +529,7 @@ class PrefixView(generic.ObjectView): ).filter( prefix__net_contains=str(instance.prefix) ).prefetch_related( - 'site', 'role', 'tenant', 'vlan', + 'scope', 'role', 'tenant', 'vlan', ) parent_prefix_table = tables.PrefixTable( list(parent_prefixes), @@ -506,7 +543,7 @@ class PrefixView(generic.ObjectView): ).exclude( pk=instance.pk ).prefetch_related( - 'site', 'role', 'tenant', 'vlan', + 'scope', 'role', 'tenant', 'vlan', ) duplicate_prefix_table = tables.PrefixTable( list(duplicate_prefixes), @@ -538,7 +575,7 @@ class PrefixPrefixesView(generic.ObjectChildrenView): def get_children(self, request, parent): return parent.get_child_prefixes().restrict(request.user, 'view').prefetch_related( - 'site', 'vrf', 'vlan', 'role', 'tenant', 'tenant__group' + 'scope', 'vrf', 'vlan', 'role', 'tenant', 'tenant__group' ) def prep_table_data(self, request, queryset, parent): @@ -614,6 +651,7 @@ class PrefixIPAddressesView(generic.ObjectChildrenView): } +@register_model_view(Prefix, 'add', detail=False) @register_model_view(Prefix, 'edit') class PrefixEditView(generic.ObjectEditView): queryset = Prefix.objects.all() @@ -625,11 +663,13 @@ class PrefixDeleteView(generic.ObjectDeleteView): queryset = Prefix.objects.all() +@register_model_view(Prefix, 'bulk_import', detail=False) class PrefixBulkImportView(generic.BulkImportView): queryset = Prefix.objects.all() model_form = forms.PrefixImportForm +@register_model_view(Prefix, 'bulk_edit', path='edit', detail=False) class PrefixBulkEditView(generic.BulkEditView): queryset = Prefix.objects.prefetch_related('vrf__tenant') filterset = filtersets.PrefixFilterSet @@ -637,6 +677,7 @@ class PrefixBulkEditView(generic.BulkEditView): form = forms.PrefixBulkEditForm +@register_model_view(Prefix, 'bulk_delete', path='delete', detail=False) class PrefixBulkDeleteView(generic.BulkDeleteView): queryset = Prefix.objects.prefetch_related('vrf__tenant') filterset = filtersets.PrefixFilterSet @@ -652,6 +693,7 @@ class PrefixContactsView(ObjectContactsView): # IP Ranges # +@register_model_view(IPRange, 'list', path='', detail=False) class IPRangeListView(generic.ObjectListView): queryset = IPRange.objects.all() filterset = filtersets.IPRangeFilterSet @@ -671,7 +713,7 @@ class IPRangeView(generic.ObjectView): Q(prefix__net_contains_or_equals=str(instance.end_address.ip)), vrf=instance.vrf ).prefetch_related( - 'site', 'role', 'tenant', 'vlan', 'role' + 'scope', 'role', 'tenant', 'vlan', 'role' ) parent_prefixes_table = tables.PrefixTable( list(parent_prefixes), @@ -703,6 +745,7 @@ class IPRangeIPAddressesView(generic.ObjectChildrenView): return parent.get_child_ips().restrict(request.user, 'view') +@register_model_view(IPRange, 'add', detail=False) @register_model_view(IPRange, 'edit') class IPRangeEditView(generic.ObjectEditView): queryset = IPRange.objects.all() @@ -714,11 +757,13 @@ class IPRangeDeleteView(generic.ObjectDeleteView): queryset = IPRange.objects.all() +@register_model_view(IPRange, 'bulk_import', detail=False) class IPRangeBulkImportView(generic.BulkImportView): queryset = IPRange.objects.all() model_form = forms.IPRangeImportForm +@register_model_view(IPRange, 'bulk_edit', path='edit', detail=False) class IPRangeBulkEditView(generic.BulkEditView): queryset = IPRange.objects.all() filterset = filtersets.IPRangeFilterSet @@ -726,6 +771,7 @@ class IPRangeBulkEditView(generic.BulkEditView): form = forms.IPRangeBulkEditForm +@register_model_view(IPRange, 'bulk_delete', path='delete', detail=False) class IPRangeBulkDeleteView(generic.BulkDeleteView): queryset = IPRange.objects.all() filterset = filtersets.IPRangeFilterSet @@ -741,6 +787,7 @@ class IPRangeContactsView(ObjectContactsView): # IP addresses # +@register_model_view(IPAddress, 'list', path='', detail=False) class IPAddressListView(generic.ObjectListView): queryset = IPAddress.objects.all() filterset = filtersets.IPAddressFilterSet @@ -758,7 +805,7 @@ class IPAddressView(generic.ObjectView): vrf=instance.vrf, prefix__net_contains_or_equals=str(instance.address.ip) ).prefetch_related( - 'site', 'role' + 'scope', 'role' ) parent_prefixes_table = tables.PrefixTable( list(parent_prefixes), @@ -787,6 +834,7 @@ class IPAddressView(generic.ObjectView): } +@register_model_view(IPAddress, 'add', detail=False) @register_model_view(IPAddress, 'edit') class IPAddressEditView(generic.ObjectEditView): queryset = IPAddress.objects.all() @@ -817,6 +865,7 @@ class IPAddressEditView(generic.ObjectEditView): # TODO: Standardize or remove this view +@register_model_view(IPAddress, 'assign', path='assign', detail=False) class IPAddressAssignView(generic.ObjectView): """ Search for IPAddresses to be assigned to an Interface. @@ -861,6 +910,7 @@ class IPAddressDeleteView(generic.ObjectDeleteView): queryset = IPAddress.objects.all() +@register_model_view(IPAddress, 'bulk_add', path='bulk-add', detail=False) class IPAddressBulkCreateView(generic.BulkCreateView): queryset = IPAddress.objects.all() form = forms.IPAddressBulkCreateForm @@ -869,11 +919,13 @@ class IPAddressBulkCreateView(generic.BulkCreateView): template_name = 'ipam/ipaddress_bulk_add.html' +@register_model_view(IPAddress, 'bulk_import', detail=False) class IPAddressBulkImportView(generic.BulkImportView): queryset = IPAddress.objects.all() model_form = forms.IPAddressImportForm +@register_model_view(IPAddress, 'bulk_edit', path='edit', detail=False) class IPAddressBulkEditView(generic.BulkEditView): queryset = IPAddress.objects.prefetch_related('vrf__tenant') filterset = filtersets.IPAddressFilterSet @@ -881,6 +933,7 @@ class IPAddressBulkEditView(generic.BulkEditView): form = forms.IPAddressBulkEditForm +@register_model_view(IPAddress, 'bulk_delete', path='delete', detail=False) class IPAddressBulkDeleteView(generic.BulkDeleteView): queryset = IPAddress.objects.prefetch_related('vrf__tenant') filterset = filtersets.IPAddressFilterSet @@ -914,6 +967,7 @@ class IPAddressContactsView(ObjectContactsView): # VLAN groups # +@register_model_view(VLANGroup, 'list', path='', detail=False) class VLANGroupListView(generic.ObjectListView): queryset = VLANGroup.objects.annotate_utilization() filterset = filtersets.VLANGroupFilterSet @@ -931,6 +985,7 @@ class VLANGroupView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(VLANGroup, 'add', detail=False) @register_model_view(VLANGroup, 'edit') class VLANGroupEditView(generic.ObjectEditView): queryset = VLANGroup.objects.all() @@ -942,11 +997,13 @@ class VLANGroupDeleteView(generic.ObjectDeleteView): queryset = VLANGroup.objects.all() +@register_model_view(VLANGroup, 'bulk_import', detail=False) class VLANGroupBulkImportView(generic.BulkImportView): queryset = VLANGroup.objects.all() model_form = forms.VLANGroupImportForm +@register_model_view(VLANGroup, 'bulk_edit', path='edit', detail=False) class VLANGroupBulkEditView(generic.BulkEditView): queryset = VLANGroup.objects.annotate_utilization().prefetch_related('tags') filterset = filtersets.VLANGroupFilterSet @@ -954,6 +1011,7 @@ class VLANGroupBulkEditView(generic.BulkEditView): form = forms.VLANGroupBulkEditForm +@register_model_view(VLANGroup, 'bulk_delete', path='delete', detail=False) class VLANGroupBulkDeleteView(generic.BulkDeleteView): queryset = VLANGroup.objects.annotate_utilization().prefetch_related('tags') filterset = filtersets.VLANGroupFilterSet @@ -986,10 +1044,127 @@ class VLANGroupVLANsView(generic.ObjectChildrenView): return queryset +# +# VLAN Translation Policies +# + +@register_model_view(VLANTranslationPolicy, 'list', path='', detail=False) +class VLANTranslationPolicyListView(generic.ObjectListView): + queryset = VLANTranslationPolicy.objects.annotate( + rule_count=count_related(VLANTranslationRule, 'policy'), + ) + filterset = filtersets.VLANTranslationPolicyFilterSet + filterset_form = forms.VLANTranslationPolicyFilterForm + table = tables.VLANTranslationPolicyTable + + +@register_model_view(VLANTranslationPolicy) +class VLANTranslationPolicyView(GetRelatedModelsMixin, generic.ObjectView): + queryset = VLANTranslationPolicy.objects.all() + + def get_extra_context(self, request, instance): + vlan_translation_table = VLANTranslationRuleTable( + data=instance.rules.all(), + orderable=False + ) + return { + 'vlan_translation_table': vlan_translation_table, + } + + +@register_model_view(VLANTranslationPolicy, 'add', detail=False) +@register_model_view(VLANTranslationPolicy, 'edit') +class VLANTranslationPolicyEditView(generic.ObjectEditView): + queryset = VLANTranslationPolicy.objects.all() + form = forms.VLANTranslationPolicyForm + + +@register_model_view(VLANTranslationPolicy, 'delete') +class VLANTranslationPolicyDeleteView(generic.ObjectDeleteView): + queryset = VLANTranslationPolicy.objects.all() + + +@register_model_view(VLANTranslationPolicy, 'bulk_import', detail=False) +class VLANTranslationPolicyBulkImportView(generic.BulkImportView): + queryset = VLANTranslationPolicy.objects.all() + model_form = forms.VLANTranslationPolicyImportForm + + +@register_model_view(VLANTranslationPolicy, 'bulk_edit', path='edit', detail=False) +class VLANTranslationPolicyBulkEditView(generic.BulkEditView): + queryset = VLANTranslationPolicy.objects.all() + filterset = filtersets.VLANTranslationPolicyFilterSet + table = tables.VLANTranslationPolicyTable + form = forms.VLANTranslationPolicyBulkEditForm + + +@register_model_view(VLANTranslationPolicy, 'bulk_delete', path='delete', detail=False) +class VLANTranslationPolicyBulkDeleteView(generic.BulkDeleteView): + queryset = VLANTranslationPolicy.objects.all() + filterset = filtersets.VLANTranslationPolicyFilterSet + table = tables.VLANTranslationPolicyTable + + +# +# VLAN Translation Rules +# + +@register_model_view(VLANTranslationRule, 'list', path='', detail=False) +class VLANTranslationRuleListView(generic.ObjectListView): + queryset = VLANTranslationRule.objects.all() + filterset = filtersets.VLANTranslationRuleFilterSet + filterset_form = forms.VLANTranslationRuleFilterForm + table = tables.VLANTranslationRuleTable + + +@register_model_view(VLANTranslationRule) +class VLANTranslationRuleView(GetRelatedModelsMixin, generic.ObjectView): + queryset = VLANTranslationRule.objects.all() + + def get_extra_context(self, request, instance): + return { + 'related_models': self.get_related_models(request, instance), + } + + +@register_model_view(VLANTranslationRule, 'add', detail=False) +@register_model_view(VLANTranslationRule, 'edit') +class VLANTranslationRuleEditView(generic.ObjectEditView): + queryset = VLANTranslationRule.objects.all() + form = forms.VLANTranslationRuleForm + + +@register_model_view(VLANTranslationRule, 'delete') +class VLANTranslationRuleDeleteView(generic.ObjectDeleteView): + queryset = VLANTranslationRule.objects.all() + + +@register_model_view(VLANTranslationRule, 'bulk_import', detail=False) +class VLANTranslationRuleBulkImportView(generic.BulkImportView): + queryset = VLANTranslationRule.objects.all() + model_form = forms.VLANTranslationRuleImportForm + + +@register_model_view(VLANTranslationRule, 'bulk_edit', path='edit', detail=False) +class VLANTranslationRuleBulkEditView(generic.BulkEditView): + queryset = VLANTranslationRule.objects.all() + filterset = filtersets.VLANTranslationRuleFilterSet + table = tables.VLANTranslationRuleTable + form = forms.VLANTranslationRuleBulkEditForm + + +@register_model_view(VLANTranslationRule, 'bulk_delete', path='delete', detail=False) +class VLANTranslationRuleBulkDeleteView(generic.BulkDeleteView): + queryset = VLANTranslationRule.objects.all() + filterset = filtersets.VLANTranslationRuleFilterSet + table = tables.VLANTranslationRuleTable + + # # FHRP groups # +@register_model_view(FHRPGroup, 'list', path='', detail=False) class FHRPGroupListView(generic.ObjectListView): queryset = FHRPGroup.objects.annotate( member_count=count_related(FHRPGroupAssignment, 'group') @@ -1017,6 +1192,7 @@ class FHRPGroupView(generic.ObjectView): } +@register_model_view(FHRPGroup, 'add', detail=False) @register_model_view(FHRPGroup, 'edit') class FHRPGroupEditView(generic.ObjectEditView): queryset = FHRPGroup.objects.all() @@ -1044,11 +1220,13 @@ class FHRPGroupDeleteView(generic.ObjectDeleteView): queryset = FHRPGroup.objects.all() +@register_model_view(FHRPGroup, 'bulk_import', detail=False) class FHRPGroupBulkImportView(generic.BulkImportView): queryset = FHRPGroup.objects.all() model_form = forms.FHRPGroupImportForm +@register_model_view(FHRPGroup, 'bulk_edit', path='edit', detail=False) class FHRPGroupBulkEditView(generic.BulkEditView): queryset = FHRPGroup.objects.all() filterset = filtersets.FHRPGroupFilterSet @@ -1056,6 +1234,7 @@ class FHRPGroupBulkEditView(generic.BulkEditView): form = forms.FHRPGroupBulkEditForm +@register_model_view(FHRPGroup, 'bulk_delete', path='delete', detail=False) class FHRPGroupBulkDeleteView(generic.BulkDeleteView): queryset = FHRPGroup.objects.all() filterset = filtersets.FHRPGroupFilterSet @@ -1066,6 +1245,7 @@ class FHRPGroupBulkDeleteView(generic.BulkDeleteView): # FHRP group assignments # +@register_model_view(FHRPGroupAssignment, 'add', detail=False) @register_model_view(FHRPGroupAssignment, 'edit') class FHRPGroupAssignmentEditView(generic.ObjectEditView): queryset = FHRPGroupAssignment.objects.all() @@ -1094,6 +1274,7 @@ class FHRPGroupAssignmentDeleteView(generic.ObjectDeleteView): # VLANs # +@register_model_view(VLAN, 'list', path='', detail=False) class VLANListView(generic.ObjectListView): queryset = VLAN.objects.all() filterset = filtersets.VLANFilterSet @@ -1107,7 +1288,7 @@ class VLANView(generic.ObjectView): def get_extra_context(self, request, instance): prefixes = Prefix.objects.restrict(request.user, 'view').filter(vlan=instance).prefetch_related( - 'vrf', 'site', 'role', 'tenant' + 'vrf', 'scope', 'role', 'tenant' ) prefix_table = tables.PrefixTable(list(prefixes), exclude=('vlan', 'utilization'), orderable=False) @@ -1152,6 +1333,7 @@ class VLANVMInterfacesView(generic.ObjectChildrenView): return parent.get_vminterfaces().restrict(request.user, 'view') +@register_model_view(VLAN, 'add', detail=False) @register_model_view(VLAN, 'edit') class VLANEditView(generic.ObjectEditView): queryset = VLAN.objects.all() @@ -1164,11 +1346,13 @@ class VLANDeleteView(generic.ObjectDeleteView): queryset = VLAN.objects.all() +@register_model_view(VLAN, 'bulk_import', detail=False) class VLANBulkImportView(generic.BulkImportView): queryset = VLAN.objects.all() model_form = forms.VLANImportForm +@register_model_view(VLAN, 'bulk_edit', path='edit', detail=False) class VLANBulkEditView(generic.BulkEditView): queryset = VLAN.objects.all() filterset = filtersets.VLANFilterSet @@ -1176,6 +1360,7 @@ class VLANBulkEditView(generic.BulkEditView): form = forms.VLANBulkEditForm +@register_model_view(VLAN, 'bulk_delete', path='delete', detail=False) class VLANBulkDeleteView(generic.BulkDeleteView): queryset = VLAN.objects.all() filterset = filtersets.VLANFilterSet @@ -1186,6 +1371,7 @@ class VLANBulkDeleteView(generic.BulkDeleteView): # Service templates # +@register_model_view(ServiceTemplate, 'list', path='', detail=False) class ServiceTemplateListView(generic.ObjectListView): queryset = ServiceTemplate.objects.all() filterset = filtersets.ServiceTemplateFilterSet @@ -1198,6 +1384,7 @@ class ServiceTemplateView(generic.ObjectView): queryset = ServiceTemplate.objects.all() +@register_model_view(ServiceTemplate, 'add', detail=False) @register_model_view(ServiceTemplate, 'edit') class ServiceTemplateEditView(generic.ObjectEditView): queryset = ServiceTemplate.objects.all() @@ -1209,11 +1396,13 @@ class ServiceTemplateDeleteView(generic.ObjectDeleteView): queryset = ServiceTemplate.objects.all() +@register_model_view(ServiceTemplate, 'bulk_import', detail=False) class ServiceTemplateBulkImportView(generic.BulkImportView): queryset = ServiceTemplate.objects.all() model_form = forms.ServiceTemplateImportForm +@register_model_view(ServiceTemplate, 'bulk_edit', path='edit', detail=False) class ServiceTemplateBulkEditView(generic.BulkEditView): queryset = ServiceTemplate.objects.all() filterset = filtersets.ServiceTemplateFilterSet @@ -1221,6 +1410,7 @@ class ServiceTemplateBulkEditView(generic.BulkEditView): form = forms.ServiceTemplateBulkEditForm +@register_model_view(ServiceTemplate, 'bulk_delete', path='delete', detail=False) class ServiceTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ServiceTemplate.objects.all() filterset = filtersets.ServiceTemplateFilterSet @@ -1231,6 +1421,7 @@ class ServiceTemplateBulkDeleteView(generic.BulkDeleteView): # Services # +@register_model_view(Service, 'list', path='', detail=False) class ServiceListView(generic.ObjectListView): queryset = Service.objects.prefetch_related('device', 'virtual_machine') filterset = filtersets.ServiceFilterSet @@ -1243,6 +1434,7 @@ class ServiceView(generic.ObjectView): queryset = Service.objects.all() +@register_model_view(Service, 'add', detail=False) class ServiceCreateView(generic.ObjectEditView): queryset = Service.objects.all() form = forms.ServiceCreateForm @@ -1259,11 +1451,13 @@ class ServiceDeleteView(generic.ObjectDeleteView): queryset = Service.objects.all() +@register_model_view(Service, 'bulk_import', detail=False) class ServiceBulkImportView(generic.BulkImportView): queryset = Service.objects.all() model_form = forms.ServiceImportForm +@register_model_view(Service, 'bulk_edit', path='edit', detail=False) class ServiceBulkEditView(generic.BulkEditView): queryset = Service.objects.prefetch_related('device', 'virtual_machine') filterset = filtersets.ServiceFilterSet @@ -1271,6 +1465,7 @@ class ServiceBulkEditView(generic.BulkEditView): form = forms.ServiceBulkEditForm +@register_model_view(Service, 'bulk_delete', path='delete', detail=False) class ServiceBulkDeleteView(generic.BulkDeleteView): queryset = Service.objects.prefetch_related('device', 'virtual_machine') filterset = filtersets.ServiceFilterSet diff --git a/netbox/manage.py b/netbox/manage.py index 2ce3867f3..737592ae8 100755 --- a/netbox/manage.py +++ b/netbox/manage.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import sys diff --git a/netbox/netbox/api/pagination.py b/netbox/netbox/api/pagination.py index 5ecade264..f1430a9fd 100644 --- a/netbox/netbox/api/pagination.py +++ b/netbox/netbox/api/pagination.py @@ -38,12 +38,14 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination): def get_limit(self, request): if self.limit_query_param: + MAX_PAGE_SIZE = get_config().MAX_PAGE_SIZE + if MAX_PAGE_SIZE: + MAX_PAGE_SIZE = max(MAX_PAGE_SIZE, self.default_limit) try: limit = int(request.query_params[self.limit_query_param]) if limit < 0: raise ValueError() # Enforce maximum page size, if defined - MAX_PAGE_SIZE = get_config().MAX_PAGE_SIZE if MAX_PAGE_SIZE: return MAX_PAGE_SIZE if limit == 0 else min(limit, MAX_PAGE_SIZE) return limit @@ -83,3 +85,28 @@ class StripCountAnnotationsPaginator(OptionalLimitOffsetPagination): cloned_queryset.query.annotations.clear() return cloned_queryset.count() + + +class LimitOffsetListPagination(LimitOffsetPagination): + """ + DRF LimitOffset Paginator but for list instead of queryset + """ + count = 0 + offset = 0 + + def paginate_list(self, data, request, view=None): + self.request = request + self.limit = self.get_limit(request) + self.count = len(data) + self.offset = self.get_offset(request) + + if self.limit is None: + self.limit = self.count + + if self.count == 0 or self.offset > self.count: + return [] + + if self.count > self.limit and self.template is not None: + self.display_page_controls = True + + return data[self.offset:self.offset + self.limit] diff --git a/netbox/netbox/api/serializers/base.py b/netbox/netbox/api/serializers/base.py index 8115fe020..6cd4e5738 100644 --- a/netbox/netbox/api/serializers/base.py +++ b/netbox/netbox/api/serializers/base.py @@ -76,6 +76,12 @@ class ValidatedModelSerializer(BaseModelSerializer): Extends the built-in ModelSerializer to enforce calling full_clean() on a copy of the associated instance during validation. (DRF does not do this by default; see https://github.com/encode/django-rest-framework/issues/3144) """ + + # Bypass DRF's built-in validation of unique constraints due to DRF bug #9410. Rely instead + # on our own custom model validation (below). + def get_unique_together_constraints(self, model): + return [] + def validate(self, data): # Skip validation if we're being used to represent a nested object diff --git a/netbox/netbox/authentication/__init__.py b/netbox/netbox/authentication/__init__.py index f80454f99..83f699e42 100644 --- a/netbox/netbox/authentication/__init__.py +++ b/netbox/netbox/authentication/__init__.py @@ -20,10 +20,10 @@ AUTH_BACKEND_ATTRS = { 'amazon': ('Amazon AWS', 'aws'), 'apple': ('Apple', 'apple'), 'auth0': ('Auth0', None), - 'entraid-oauth2': ('Microsoft Entra ID', 'microsoft'), - 'entraid-b2c-oauth2': ('Microsoft Entra ID', 'microsoft'), - 'entraid-tenant-oauth2': ('Microsoft Entra ID', 'microsoft'), - 'entraid-v2-tenant-oauth2': ('Microsoft Entra ID', 'microsoft'), + 'azuread-oauth2': ('Microsoft Entra ID', 'microsoft'), + 'azuread-b2c-oauth2': ('Microsoft Entra ID', 'microsoft'), + 'azuread-tenant-oauth2': ('Microsoft Entra ID', 'microsoft'), + 'azuread-v2-tenant-oauth2': ('Microsoft Entra ID', 'microsoft'), 'bitbucket': ('BitBucket', 'bitbucket'), 'bitbucket-oauth2': ('BitBucket', 'bitbucket'), 'digitalocean': ('DigitalOcean', 'digital-ocean'), @@ -107,7 +107,7 @@ class ObjectPermissionMixin: return perms def has_perm(self, user_obj, perm, obj=None): - app_label, action, model_name = resolve_permission(perm) + app_label, __, model_name = resolve_permission(perm) # Superusers implicitly have all permissions if user_obj.is_active and user_obj.is_superuser: diff --git a/netbox/netbox/constants.py b/netbox/netbox/constants.py index b8c679ec0..8d20fed45 100644 --- a/netbox/netbox/constants.py +++ b/netbox/netbox/constants.py @@ -31,8 +31,8 @@ ADVISORY_LOCK_KEYS = { # Default view action permission mapping DEFAULT_ACTION_PERMISSIONS = { 'add': {'add'}, - 'import': {'add'}, 'export': {'view'}, + 'bulk_import': {'add'}, 'bulk_edit': {'change'}, 'bulk_delete': {'delete'}, } diff --git a/netbox/netbox/context_managers.py b/netbox/netbox/context_managers.py index ca434df82..7b01cce94 100644 --- a/netbox/netbox/context_managers.py +++ b/netbox/netbox/context_managers.py @@ -1,9 +1,11 @@ from contextlib import contextmanager from netbox.context import current_request, events_queue +from netbox.utils import register_request_processor from extras.events import flush_events +@register_request_processor @contextmanager def event_tracking(request): """ diff --git a/netbox/netbox/filtersets.py b/netbox/netbox/filtersets.py index 637a40bf1..b8fbe7ad5 100644 --- a/netbox/netbox/filtersets.py +++ b/netbox/netbox/filtersets.py @@ -179,6 +179,8 @@ class BaseFilterSet(django_filters.FilterSet): # The filter field has been explicitly defined on the filterset class so we must manually # create the new filter with the same type because there is no guarantee the defined type # is the same as the default type for the field + if field is None: + raise ValueError('Invalid field name/lookup on {}: {}'.format(existing_filter_name, field_name)) resolve_field(field, lookup_expr) # Will raise FieldLookupError if the lookup is invalid filter_cls = type(existing_filter) if lookup_expr == 'empty': @@ -262,7 +264,9 @@ class ChangeLoggedModelFilterSet(BaseFilterSet): action = { 'created_by_request': Q(action=ObjectChangeActionChoices.ACTION_CREATE), 'updated_by_request': Q(action=ObjectChangeActionChoices.ACTION_UPDATE), - 'modified_by_request': Q(action__in=[ObjectChangeActionChoices.ACTION_CREATE, ObjectChangeActionChoices.ACTION_UPDATE]), + 'modified_by_request': Q( + action__in=[ObjectChangeActionChoices.ACTION_CREATE, ObjectChangeActionChoices.ACTION_UPDATE] + ), }.get(name) request_id = value pks = ObjectChange.objects.filter( diff --git a/netbox/netbox/graphql/views.py b/netbox/netbox/graphql/views.py index 85a01f025..46a073c93 100644 --- a/netbox/netbox/graphql/views.py +++ b/netbox/netbox/graphql/views.py @@ -14,7 +14,6 @@ class NetBoxGraphQLView(GraphQLView): """ Extends strawberry's GraphQLView to support DRF's token-based authentication. """ - graphiql_template = 'graphiql.html' @csrf_exempt def dispatch(self, request, *args, **kwargs): diff --git a/netbox/netbox/jobs.py b/netbox/netbox/jobs.py index 087c24896..3af3af554 100644 --- a/netbox/netbox/jobs.py +++ b/netbox/netbox/jobs.py @@ -2,6 +2,7 @@ import logging from abc import ABC, abstractmethod from datetime import timedelta +from django.core.exceptions import ImproperlyConfigured from django.utils.functional import classproperty from django_pglocks import advisory_lock from rq.timeouts import JobTimeoutException @@ -9,12 +10,30 @@ from rq.timeouts import JobTimeoutException from core.choices import JobStatusChoices from core.models import Job, ObjectType from netbox.constants import ADVISORY_LOCK_KEYS +from netbox.registry import registry __all__ = ( 'JobRunner', + 'system_job', ) +def system_job(interval): + """ + Decorator for registering a `JobRunner` class as system background job. + """ + if type(interval) is not int: + raise ImproperlyConfigured("System job interval must be an integer (minutes).") + + def _wrapper(cls): + registry['system_jobs'][cls] = { + 'interval': interval + } + return cls + + return _wrapper + + class JobRunner(ABC): """ Background Job helper class. @@ -68,8 +87,11 @@ class JobRunner(ABC): finally: if job.interval: new_scheduled_time = (job.scheduled or job.started) + timedelta(minutes=job.interval) + if job.object and getattr(job.object, "python_class", None): + kwargs["job_timeout"] = job.object.python_class.job_timeout cls.enqueue( instance=job.object, + name=job.name, user=job.user, schedule_at=new_scheduled_time, interval=job.interval, @@ -127,7 +149,7 @@ class JobRunner(ABC): if job: # If the job parameters haven't changed, don't schedule a new job and keep the current schedule. Otherwise, # delete the existing job and schedule a new job instead. - if (schedule_at and job.scheduled == schedule_at) and (job.interval == interval): + if (not schedule_at or job.scheduled == schedule_at) and (job.interval == interval): return job job.delete() diff --git a/netbox/netbox/middleware.py b/netbox/netbox/middleware.py index 8012965a4..b9424bd7c 100644 --- a/netbox/netbox/middleware.py +++ b/netbox/netbox/middleware.py @@ -1,3 +1,5 @@ +from contextlib import ExitStack + import logging import uuid @@ -10,7 +12,7 @@ from django.db.utils import InternalError from django.http import Http404, HttpResponseRedirect from netbox.config import clear_config, get_config -from netbox.context_managers import event_tracking +from netbox.registry import registry from netbox.views import handler_500 from utilities.api import is_api_request from utilities.error_handlers import handle_rest_api_exception @@ -32,8 +34,10 @@ class CoreMiddleware: # Assign a random unique ID to the request. This will be used for change logging. request.id = uuid.uuid4() - # Enable the event_tracking context manager and process the request. - with event_tracking(request): + # Apply all registered request processors + with ExitStack() as stack: + for request_processor in registry['request_processors']: + stack.enter_context(request_processor(request)) response = self.get_response(request) # Check if language cookie should be renewed diff --git a/netbox/netbox/models/mixins.py b/netbox/netbox/models/mixins.py index 804e0b71a..dc706c7c2 100644 --- a/netbox/netbox/models/mixins.py +++ b/netbox/netbox/models/mixins.py @@ -23,6 +23,7 @@ class WeightMixin(models.Model): max_length=50, choices=WeightUnitChoices, blank=True, + null=True, ) # Stores the normalized weight (in grams) for database ordering _abs_weight = models.PositiveBigIntegerField( @@ -64,6 +65,7 @@ class DistanceMixin(models.Model): max_length=50, choices=DistanceUnitChoices, blank=True, + null=True, ) # Stores the normalized distance (in meters) for database ordering _abs_distance = models.DecimalField( @@ -85,7 +87,7 @@ class DistanceMixin(models.Model): # Clear distance_unit if no distance is defined if self.distance is None: - self.distance_unit = '' + self.distance_unit = None super().save(*args, **kwargs) diff --git a/netbox/netbox/navigation/__init__.py b/netbox/netbox/navigation/__init__.py index b4f7dbd9f..75ca8f440 100644 --- a/netbox/netbox/navigation/__init__.py +++ b/netbox/netbox/navigation/__init__.py @@ -60,7 +60,7 @@ class Menu: # Utility functions # -def get_model_item(app_label, model_name, label, actions=('add', 'import')): +def get_model_item(app_label, model_name, label, actions=('add', 'bulk_import')): return MenuItem( link=f'{app_label}:{model_name}_list', link_text=label, @@ -69,7 +69,7 @@ def get_model_item(app_label, model_name, label, actions=('add', 'import')): ) -def get_model_buttons(app_label, model_name, actions=('add', 'import')): +def get_model_buttons(app_label, model_name, actions=('add', 'bulk_import')): buttons = [] if 'add' in actions: @@ -81,10 +81,10 @@ def get_model_buttons(app_label, model_name, actions=('add', 'import')): permissions=[f'{app_label}.add_{model_name}'] ) ) - if 'import' in actions: + if 'bulk_import' in actions: buttons.append( MenuItemButton( - link=f'{app_label}:{model_name}_import', + link=f'{app_label}:{model_name}_bulk_import', title='Import', icon_class='mdi mdi-upload', permissions=[f'{app_label}.add_{model_name}'] diff --git a/netbox/netbox/navigation/menu.py b/netbox/netbox/navigation/menu.py index 9d8ffaaf8..9148caa8e 100644 --- a/netbox/netbox/navigation/menu.py +++ b/netbox/netbox/navigation/menu.py @@ -33,7 +33,7 @@ ORGANIZATION_MENU = Menu( get_model_item('tenancy', 'contact', _('Contacts')), get_model_item('tenancy', 'contactgroup', _('Contact Groups')), get_model_item('tenancy', 'contactrole', _('Contact Roles')), - get_model_item('tenancy', 'contactassignment', _('Contact Assignments'), actions=['import']), + get_model_item('tenancy', 'contactassignment', _('Contact Assignments'), actions=['bulk_import']), ), ), ), @@ -104,6 +104,12 @@ DEVICES_MENU = Menu( get_model_item('dcim', 'inventoryitemrole', _('Inventory Item Roles')), ), ), + MenuGroup( + label=_('Addressing'), + items=( + get_model_item('dcim', 'macaddress', _('MAC Addresses')), + ), + ), ), ) @@ -194,6 +200,8 @@ IPAM_MENU = Menu( items=( get_model_item('ipam', 'vlan', _('VLANs')), get_model_item('ipam', 'vlangroup', _('VLAN Groups')), + get_model_item('ipam', 'vlantranslationpolicy', _('VLAN Translation Policies')), + get_model_item('ipam', 'vlantranslationrule', _('VLAN Translation Rules')), ), ), MenuGroup( @@ -271,9 +279,22 @@ CIRCUITS_MENU = Menu( items=( get_model_item('circuits', 'circuit', _('Circuits')), get_model_item('circuits', 'circuittype', _('Circuit Types')), + get_model_item('circuits', 'circuittermination', _('Circuit Terminations')), + ), + ), + MenuGroup( + label=_('Virtual Circuits'), + items=( + get_model_item('circuits', 'virtualcircuit', _('Virtual Circuits')), + get_model_item('circuits', 'virtualcircuittype', _('Virtual Circuit Types')), + get_model_item('circuits', 'virtualcircuittermination', _('Virtual Circuit Terminations')), + ), + ), + MenuGroup( + label=_('Groups'), + items=( get_model_item('circuits', 'circuitgroup', _('Circuit Groups')), get_model_item('circuits', 'circuitgroupassignment', _('Group Assignments')), - get_model_item('circuits', 'circuittermination', _('Circuit Terminations')), ), ), MenuGroup( @@ -371,7 +392,7 @@ OPERATIONS_MENU = Menu( label=_('Logging'), items=( get_model_item('extras', 'notificationgroup', _('Notification Groups')), - get_model_item('extras', 'journalentry', _('Journal Entries'), actions=['import']), + get_model_item('extras', 'journalentry', _('Journal Entries'), actions=['bulk_import']), get_model_item('core', 'objectchange', _('Change Log'), actions=[]), ), ), @@ -398,7 +419,7 @@ ADMIN_MENU = Menu( permissions=['users.add_user'] ), MenuItemButton( - link='users:user_import', + link='users:user_bulk_import', title='Import', icon_class='mdi mdi-upload', permissions=['users.add_user'] @@ -418,7 +439,7 @@ ADMIN_MENU = Menu( permissions=['users.add_group'] ), MenuItemButton( - link='users:group_import', + link='users:group_bulk_import', title='Import', icon_class='mdi mdi-upload', permissions=['users.add_group'] diff --git a/netbox/netbox/plugins/__init__.py b/netbox/netbox/plugins/__init__.py index e2f0f22fc..69881a251 100644 --- a/netbox/netbox/plugins/__init__.py +++ b/netbox/netbox/plugins/__init__.py @@ -78,6 +78,7 @@ class PluginConfig(AppConfig): menu_items = None template_extensions = None user_preferences = None + events_pipeline = [] def _load_resource(self, name): # Import from the configured path, if defined. diff --git a/netbox/netbox/plugins/registration.py b/netbox/netbox/plugins/registration.py index c84572794..515405f1b 100644 --- a/netbox/netbox/plugins/registration.py +++ b/netbox/netbox/plugins/registration.py @@ -1,4 +1,5 @@ import inspect +import warnings from django.utils.translation import gettext_lazy as _ from netbox.registry import registry @@ -37,7 +38,12 @@ def register_template_extensions(class_list): # Registration for multiple models models = template_extension.models elif template_extension.model: - # Registration for a single model + # Registration for a single model (deprecated) + warnings.warn( + "PluginTemplateExtension.model is deprecated and will be removed in a future release. Use " + "'models' instead.", + DeprecationWarning + ) models = [template_extension.model] else: # Global registration (no specific models) diff --git a/netbox/netbox/plugins/templates.py b/netbox/netbox/plugins/templates.py index e1f4b7a47..4ea90b4db 100644 --- a/netbox/netbox/plugins/templates.py +++ b/netbox/netbox/plugins/templates.py @@ -21,7 +21,7 @@ class PluginTemplateExtension: * config - Plugin-specific configuration parameters """ models = None - model = None + model = None # Deprecated; use `models` instead def __init__(self, context): self.context = context diff --git a/netbox/netbox/registry.py b/netbox/netbox/registry.py index 0920cbccf..02b741779 100644 --- a/netbox/netbox/registry.py +++ b/netbox/netbox/registry.py @@ -29,7 +29,9 @@ registry = Registry({ 'model_features': dict(), 'models': collections.defaultdict(set), 'plugins': dict(), + 'request_processors': list(), 'search': dict(), + 'system_jobs': dict(), 'tables': collections.defaultdict(dict), 'views': collections.defaultdict(dict), 'widgets': dict(), diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 2b057b9ab..0682e713d 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -110,9 +110,9 @@ DEFAULT_PERMISSIONS = getattr(configuration, 'DEFAULT_PERMISSIONS', { DEVELOPER = getattr(configuration, 'DEVELOPER', False) DOCS_ROOT = getattr(configuration, 'DOCS_ROOT', os.path.join(os.path.dirname(BASE_DIR), 'docs')) EMAIL = getattr(configuration, 'EMAIL', {}) -EVENTS_PIPELINE = getattr(configuration, 'EVENTS_PIPELINE', ( +EVENTS_PIPELINE = getattr(configuration, 'EVENTS_PIPELINE', [ 'extras.events.process_event_queue', -)) +]) EXEMPT_VIEW_PERMISSIONS = getattr(configuration, 'EXEMPT_VIEW_PERMISSIONS', []) FIELD_CHOICES = getattr(configuration, 'FIELD_CHOICES', {}) FILE_UPLOAD_MAX_MEMORY_SIZE = getattr(configuration, 'FILE_UPLOAD_MAX_MEMORY_SIZE', 2621440) @@ -787,6 +787,10 @@ STRAWBERRY_DJANGO = { PLUGIN_CATALOG_URL = 'https://api.netbox.oss.netboxlabs.com/v1/plugins' +EVENTS_PIPELINE = list(EVENTS_PIPELINE) +if 'extras.events.process_event_queue' not in EVENTS_PIPELINE: + EVENTS_PIPELINE.insert(0, 'extras.events.process_event_queue') + # Register any configured plugins for plugin_name in PLUGINS: try: @@ -857,6 +861,13 @@ for plugin_name in PLUGINS: f"{plugin_name}.{queue}": RQ_PARAMS for queue in plugin_config.queues }) + events_pipeline = plugin_config.events_pipeline + if events_pipeline: + if type(events_pipeline) in (list, tuple): + EVENTS_PIPELINE.extend(events_pipeline) + else: + raise ImproperlyConfigured(f"events_pipline in plugin: {plugin_name} must be a list or tuple") + # UNSUPPORTED FUNCTIONALITY: Import any local overrides. try: from .local_settings import * diff --git a/netbox/netbox/tables/columns.py b/netbox/netbox/tables/columns.py index ee1420396..cf6e1f133 100644 --- a/netbox/netbox/tables/columns.py +++ b/netbox/netbox/tables/columns.py @@ -286,7 +286,8 @@ class ActionsColumn(tables.Column): if len(self.actions) == 1 or (self.split_actions and idx == 0): dropdown_class = attrs.css_class button = ( - f'' + f'' f'' ) @@ -303,7 +304,8 @@ class ActionsColumn(tables.Column): html += ( f'' f' {button}' - f' ' + f' ' f' {toggle_text}' f' ' f'' diff --git a/netbox/netbox/tests/dummy_plugin/__init__.py b/netbox/netbox/tests/dummy_plugin/__init__.py index 3ade8f9df..2ca7c290c 100644 --- a/netbox/netbox/tests/dummy_plugin/__init__.py +++ b/netbox/netbox/tests/dummy_plugin/__init__.py @@ -17,6 +17,14 @@ class DummyPluginConfig(PluginConfig): 'testing-medium', 'testing-high' ] + events_pipeline = [ + 'netbox.tests.dummy_plugin.events.process_events_queue' + ] + + def ready(self): + super().ready() + + from . import jobs # noqa: F401 config = DummyPluginConfig diff --git a/netbox/netbox/tests/dummy_plugin/events.py b/netbox/netbox/tests/dummy_plugin/events.py new file mode 100644 index 000000000..934594643 --- /dev/null +++ b/netbox/netbox/tests/dummy_plugin/events.py @@ -0,0 +1,2 @@ +def process_events_queue(events): + pass diff --git a/netbox/netbox/tests/dummy_plugin/jobs.py b/netbox/netbox/tests/dummy_plugin/jobs.py new file mode 100644 index 000000000..3b9dc7a5f --- /dev/null +++ b/netbox/netbox/tests/dummy_plugin/jobs.py @@ -0,0 +1,9 @@ +from core.choices import JobIntervalChoices +from netbox.jobs import JobRunner, system_job + + +@system_job(interval=JobIntervalChoices.INTERVAL_HOURLY) +class DummySystemJob(JobRunner): + + def run(self, *args, **kwargs): + pass diff --git a/netbox/netbox/tests/test_authentication.py b/netbox/netbox/tests/test_authentication.py index ae6d3f4c2..9eb21661d 100644 --- a/netbox/netbox/tests/test_authentication.py +++ b/netbox/netbox/tests/test_authentication.py @@ -4,12 +4,10 @@ from django.conf import settings from django.test import Client from django.test.utils import override_settings from django.urls import reverse -from netaddr import IPNetwork from rest_framework.test import APIClient from core.models import ObjectType -from dcim.models import Site -from ipam.models import Prefix +from dcim.models import Rack, Site from users.models import Group, ObjectPermission, Token, User from utilities.testing import TestCase from utilities.testing.api import APITestCase @@ -410,18 +408,18 @@ class ObjectPermissionAPIViewTestCase(TestCase): ) Site.objects.bulk_create(cls.sites) - cls.prefixes = ( - Prefix(prefix=IPNetwork('10.0.0.0/24'), site=cls.sites[0]), - Prefix(prefix=IPNetwork('10.0.1.0/24'), site=cls.sites[0]), - Prefix(prefix=IPNetwork('10.0.2.0/24'), site=cls.sites[0]), - Prefix(prefix=IPNetwork('10.0.3.0/24'), site=cls.sites[1]), - Prefix(prefix=IPNetwork('10.0.4.0/24'), site=cls.sites[1]), - Prefix(prefix=IPNetwork('10.0.5.0/24'), site=cls.sites[1]), - Prefix(prefix=IPNetwork('10.0.6.0/24'), site=cls.sites[2]), - Prefix(prefix=IPNetwork('10.0.7.0/24'), site=cls.sites[2]), - Prefix(prefix=IPNetwork('10.0.8.0/24'), site=cls.sites[2]), + cls.racks = ( + Rack(name='Rack 1', site=cls.sites[0]), + Rack(name='Rack 2', site=cls.sites[0]), + Rack(name='Rack 3', site=cls.sites[0]), + Rack(name='Rack 4', site=cls.sites[1]), + Rack(name='Rack 5', site=cls.sites[1]), + Rack(name='Rack 6', site=cls.sites[1]), + Rack(name='Rack 7', site=cls.sites[2]), + Rack(name='Rack 8', site=cls.sites[2]), + Rack(name='Rack 9', site=cls.sites[2]), ) - Prefix.objects.bulk_create(cls.prefixes) + Rack.objects.bulk_create(cls.racks) def setUp(self): """ @@ -435,8 +433,7 @@ class ObjectPermissionAPIViewTestCase(TestCase): def test_get_object(self): # Attempt to retrieve object without permission - url = reverse('ipam-api:prefix-detail', - kwargs={'pk': self.prefixes[0].pk}) + url = reverse('dcim-api:rack-detail', kwargs={'pk': self.racks[0].pk}) response = self.client.get(url, **self.header) self.assertEqual(response.status_code, 403) @@ -448,23 +445,21 @@ class ObjectPermissionAPIViewTestCase(TestCase): ) obj_perm.save() obj_perm.users.add(self.user) - obj_perm.object_types.add(ObjectType.objects.get_for_model(Prefix)) + obj_perm.object_types.add(ObjectType.objects.get_for_model(Rack)) # Retrieve permitted object - url = reverse('ipam-api:prefix-detail', - kwargs={'pk': self.prefixes[0].pk}) + url = reverse('dcim-api:rack-detail', kwargs={'pk': self.racks[0].pk}) response = self.client.get(url, **self.header) self.assertEqual(response.status_code, 200) # Attempt to retrieve non-permitted object - url = reverse('ipam-api:prefix-detail', - kwargs={'pk': self.prefixes[3].pk}) + url = reverse('dcim-api:rack-detail', kwargs={'pk': self.racks[3].pk}) response = self.client.get(url, **self.header) self.assertEqual(response.status_code, 404) @override_settings(EXEMPT_VIEW_PERMISSIONS=[]) def test_list_objects(self): - url = reverse('ipam-api:prefix-list') + url = reverse('dcim-api:rack-list') # Attempt to list objects without permission response = self.client.get(url, **self.header) @@ -478,7 +473,7 @@ class ObjectPermissionAPIViewTestCase(TestCase): ) obj_perm.save() obj_perm.users.add(self.user) - obj_perm.object_types.add(ObjectType.objects.get_for_model(Prefix)) + obj_perm.object_types.add(ObjectType.objects.get_for_model(Rack)) # Retrieve all objects. Only permitted objects should be returned. response = self.client.get(url, **self.header) @@ -487,12 +482,12 @@ class ObjectPermissionAPIViewTestCase(TestCase): @override_settings(EXEMPT_VIEW_PERMISSIONS=[]) def test_create_object(self): - url = reverse('ipam-api:prefix-list') + url = reverse('dcim-api:rack-list') data = { - 'prefix': '10.0.9.0/24', + 'name': 'Rack 10', 'site': self.sites[1].pk, } - initial_count = Prefix.objects.count() + initial_count = Rack.objects.count() # Attempt to create an object without permission response = self.client.post(url, data, format='json', **self.header) @@ -506,26 +501,25 @@ class ObjectPermissionAPIViewTestCase(TestCase): ) obj_perm.save() obj_perm.users.add(self.user) - obj_perm.object_types.add(ObjectType.objects.get_for_model(Prefix)) + obj_perm.object_types.add(ObjectType.objects.get_for_model(Rack)) # Attempt to create a non-permitted object response = self.client.post(url, data, format='json', **self.header) self.assertEqual(response.status_code, 403) - self.assertEqual(Prefix.objects.count(), initial_count) + self.assertEqual(Rack.objects.count(), initial_count) # Create a permitted object data['site'] = self.sites[0].pk response = self.client.post(url, data, format='json', **self.header) self.assertEqual(response.status_code, 201) - self.assertEqual(Prefix.objects.count(), initial_count + 1) + self.assertEqual(Rack.objects.count(), initial_count + 1) @override_settings(EXEMPT_VIEW_PERMISSIONS=[]) def test_edit_object(self): # Attempt to edit an object without permission data = {'site': self.sites[0].pk} - url = reverse('ipam-api:prefix-detail', - kwargs={'pk': self.prefixes[0].pk}) + url = reverse('dcim-api:rack-detail', kwargs={'pk': self.racks[0].pk}) response = self.client.patch(url, data, format='json', **self.header) self.assertEqual(response.status_code, 403) @@ -537,26 +531,23 @@ class ObjectPermissionAPIViewTestCase(TestCase): ) obj_perm.save() obj_perm.users.add(self.user) - obj_perm.object_types.add(ObjectType.objects.get_for_model(Prefix)) + obj_perm.object_types.add(ObjectType.objects.get_for_model(Rack)) # Attempt to edit a non-permitted object data = {'site': self.sites[0].pk} - url = reverse('ipam-api:prefix-detail', - kwargs={'pk': self.prefixes[3].pk}) + url = reverse('dcim-api:rack-detail', kwargs={'pk': self.racks[3].pk}) response = self.client.patch(url, data, format='json', **self.header) self.assertEqual(response.status_code, 404) # Edit a permitted object data['status'] = 'reserved' - url = reverse('ipam-api:prefix-detail', - kwargs={'pk': self.prefixes[0].pk}) + url = reverse('dcim-api:rack-detail', kwargs={'pk': self.racks[0].pk}) response = self.client.patch(url, data, format='json', **self.header) self.assertEqual(response.status_code, 200) # Attempt to modify a permitted object to a non-permitted object data['site'] = self.sites[1].pk - url = reverse('ipam-api:prefix-detail', - kwargs={'pk': self.prefixes[0].pk}) + url = reverse('dcim-api:rack-detail', kwargs={'pk': self.racks[0].pk}) response = self.client.patch(url, data, format='json', **self.header) self.assertEqual(response.status_code, 403) @@ -564,8 +555,7 @@ class ObjectPermissionAPIViewTestCase(TestCase): def test_delete_object(self): # Attempt to delete an object without permission - url = reverse('ipam-api:prefix-detail', - kwargs={'pk': self.prefixes[0].pk}) + url = reverse('dcim-api:rack-detail', kwargs={'pk': self.racks[0].pk}) response = self.client.delete(url, format='json', **self.header) self.assertEqual(response.status_code, 403) @@ -577,16 +567,14 @@ class ObjectPermissionAPIViewTestCase(TestCase): ) obj_perm.save() obj_perm.users.add(self.user) - obj_perm.object_types.add(ObjectType.objects.get_for_model(Prefix)) + obj_perm.object_types.add(ObjectType.objects.get_for_model(Rack)) # Attempt to delete a non-permitted object - url = reverse('ipam-api:prefix-detail', - kwargs={'pk': self.prefixes[3].pk}) + url = reverse('dcim-api:rack-detail', kwargs={'pk': self.racks[3].pk}) response = self.client.delete(url, format='json', **self.header) self.assertEqual(response.status_code, 404) # Delete a permitted object - url = reverse('ipam-api:prefix-detail', - kwargs={'pk': self.prefixes[0].pk}) + url = reverse('dcim-api:rack-detail', kwargs={'pk': self.racks[0].pk}) response = self.client.delete(url, format='json', **self.header) self.assertEqual(response.status_code, 204) diff --git a/netbox/netbox/tests/test_import.py b/netbox/netbox/tests/test_import.py index 16711ef72..690a6dc14 100644 --- a/netbox/netbox/tests/test_import.py +++ b/netbox/netbox/tests/test_import.py @@ -37,7 +37,7 @@ class CSVImportTestCase(ModelViewTestCase): } # Form validation should fail with invalid header present - self.assertHttpStatus(self.client.post(self._get_url('import'), data), 200) + self.assertHttpStatus(self.client.post(self._get_url('bulk_import'), data), 200) self.assertEqual(Region.objects.count(), 0) # Correct the CSV header name @@ -45,7 +45,7 @@ class CSVImportTestCase(ModelViewTestCase): data['data'] = self._get_csv_data(csv_data) # Validation should succeed - self.assertHttpStatus(self.client.post(self._get_url('import'), data), 302) + self.assertHttpStatus(self.client.post(self._get_url('bulk_import'), data), 302) self.assertEqual(Region.objects.count(), 3) @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) @@ -71,10 +71,10 @@ class CSVImportTestCase(ModelViewTestCase): obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model)) # Try GET with model-level permission - self.assertHttpStatus(self.client.get(self._get_url('import')), 200) + self.assertHttpStatus(self.client.get(self._get_url('bulk_import')), 200) # Test POST with permission - self.assertHttpStatus(self.client.post(self._get_url('import'), data), 302) + self.assertHttpStatus(self.client.post(self._get_url('bulk_import'), data), 302) regions = Region.objects.all() self.assertEqual(regions.count(), 4) self.assertEqual( @@ -111,10 +111,10 @@ class CSVImportTestCase(ModelViewTestCase): obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model)) # Try GET with model-level permission - self.assertHttpStatus(self.client.get(self._get_url('import')), 200) + self.assertHttpStatus(self.client.get(self._get_url('bulk_import')), 200) # Test POST with permission - self.assertHttpStatus(self.client.post(self._get_url('import'), data), 200) + self.assertHttpStatus(self.client.post(self._get_url('bulk_import'), data), 200) self.assertEqual(Region.objects.count(), 0) @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) @@ -138,6 +138,6 @@ class CSVImportTestCase(ModelViewTestCase): ) cf.object_types.set([ObjectType.objects.get_for_model(self.model)]) - self.assertHttpStatus(self.client.post(self._get_url('import'), data), 302) + self.assertHttpStatus(self.client.post(self._get_url('bulk_import'), data), 302) region = Region.objects.get(slug='region-1') self.assertEqual(region.cf['tcf'], 'def-cf-text') diff --git a/netbox/netbox/tests/test_jobs.py b/netbox/netbox/tests/test_jobs.py index cb3024038..e3e24a235 100644 --- a/netbox/netbox/tests/test_jobs.py +++ b/netbox/netbox/tests/test_jobs.py @@ -5,7 +5,7 @@ from django.utils import timezone from django_rq import get_queue from ..jobs import * -from core.models import Job +from core.models import DataSource, Job from core.choices import JobStatusChoices @@ -68,7 +68,7 @@ class EnqueueTest(JobRunnerTestCase): """ def test_enqueue(self): - instance = Job() + instance = DataSource() for i in range(1, 3): job = TestJobRunner.enqueue(instance, schedule_at=self.get_schedule_at()) @@ -76,13 +76,13 @@ class EnqueueTest(JobRunnerTestCase): self.assertEqual(TestJobRunner.get_jobs(instance).count(), i) def test_enqueue_once(self): - job = TestJobRunner.enqueue_once(instance=Job(), schedule_at=self.get_schedule_at()) + job = TestJobRunner.enqueue_once(instance=DataSource(), schedule_at=self.get_schedule_at()) self.assertIsInstance(job, Job) self.assertEqual(job.name, TestJobRunner.__name__) def test_enqueue_once_twice_same(self): - instance = Job() + instance = DataSource() schedule_at = self.get_schedule_at() job1 = TestJobRunner.enqueue_once(instance, schedule_at=schedule_at) job2 = TestJobRunner.enqueue_once(instance, schedule_at=schedule_at) @@ -90,8 +90,17 @@ class EnqueueTest(JobRunnerTestCase): self.assertEqual(job1, job2) self.assertEqual(TestJobRunner.get_jobs(instance).count(), 1) + def test_enqueue_once_twice_same_no_schedule_at(self): + instance = DataSource() + schedule_at = self.get_schedule_at() + job1 = TestJobRunner.enqueue_once(instance, schedule_at=schedule_at) + job2 = TestJobRunner.enqueue_once(instance) + + self.assertEqual(job1, job2) + self.assertEqual(TestJobRunner.get_jobs(instance).count(), 1) + def test_enqueue_once_twice_different_schedule_at(self): - instance = Job() + instance = DataSource() job1 = TestJobRunner.enqueue_once(instance, schedule_at=self.get_schedule_at()) job2 = TestJobRunner.enqueue_once(instance, schedule_at=self.get_schedule_at(2)) @@ -100,7 +109,7 @@ class EnqueueTest(JobRunnerTestCase): self.assertEqual(TestJobRunner.get_jobs(instance).count(), 1) def test_enqueue_once_twice_different_interval(self): - instance = Job() + instance = DataSource() schedule_at = self.get_schedule_at() job1 = TestJobRunner.enqueue_once(instance, schedule_at=schedule_at) job2 = TestJobRunner.enqueue_once(instance, schedule_at=schedule_at, interval=60) @@ -112,7 +121,7 @@ class EnqueueTest(JobRunnerTestCase): self.assertEqual(TestJobRunner.get_jobs(instance).count(), 1) def test_enqueue_once_with_enqueue(self): - instance = Job() + instance = DataSource() job1 = TestJobRunner.enqueue_once(instance, schedule_at=self.get_schedule_at(2)) job2 = TestJobRunner.enqueue(instance, schedule_at=self.get_schedule_at()) @@ -120,10 +129,37 @@ class EnqueueTest(JobRunnerTestCase): self.assertEqual(TestJobRunner.get_jobs(instance).count(), 2) def test_enqueue_once_after_enqueue(self): - instance = Job() + instance = DataSource() job1 = TestJobRunner.enqueue(instance, schedule_at=self.get_schedule_at()) job2 = TestJobRunner.enqueue_once(instance, schedule_at=self.get_schedule_at(2)) self.assertNotEqual(job1, job2) self.assertRaises(Job.DoesNotExist, job1.refresh_from_db) self.assertEqual(TestJobRunner.get_jobs(instance).count(), 1) + + +class SystemJobTest(JobRunnerTestCase): + """ + Test that system jobs can be scheduled. + + General functionality already tested by `JobRunnerTest` and `EnqueueTest`. + """ + + def test_scheduling(self): + # Can job be enqueued? + job = TestJobRunner.enqueue(schedule_at=self.get_schedule_at()) + self.assertIsInstance(job, Job) + self.assertEqual(TestJobRunner.get_jobs().count(), 1) + + # Can job be deleted again? + job.delete() + self.assertRaises(Job.DoesNotExist, job.refresh_from_db) + self.assertEqual(TestJobRunner.get_jobs().count(), 0) + + def test_enqueue_once(self): + schedule_at = self.get_schedule_at() + job1 = TestJobRunner.enqueue_once(schedule_at=schedule_at) + job2 = TestJobRunner.enqueue_once(schedule_at=schedule_at) + + self.assertEqual(job1, job2) + self.assertEqual(TestJobRunner.get_jobs().count(), 1) diff --git a/netbox/netbox/tests/test_plugins.py b/netbox/netbox/tests/test_plugins.py index ba44378c5..264c8e6f9 100644 --- a/netbox/netbox/tests/test_plugins.py +++ b/netbox/netbox/tests/test_plugins.py @@ -5,8 +5,10 @@ from django.core.exceptions import ImproperlyConfigured from django.test import Client, TestCase, override_settings from django.urls import reverse +from core.choices import JobIntervalChoices from netbox.tests.dummy_plugin import config as dummy_config from netbox.tests.dummy_plugin.data_backends import DummyBackend +from netbox.tests.dummy_plugin.jobs import DummySystemJob from netbox.plugins.navigation import PluginMenu from netbox.plugins.utils import get_plugin_config from netbox.graphql.schema import Query @@ -130,6 +132,13 @@ class PluginTest(TestCase): self.assertIn('dummy', registry['data_backends']) self.assertIs(registry['data_backends']['dummy'], DummyBackend) + def test_system_jobs(self): + """ + Check registered system jobs. + """ + self.assertIn(DummySystemJob, registry['system_jobs']) + self.assertEqual(registry['system_jobs'][DummySystemJob]['interval'], JobIntervalChoices.INTERVAL_HOURLY) + def test_queues(self): """ Check that plugin queues are registered with the accurate name. @@ -203,3 +212,9 @@ class PluginTest(TestCase): self.assertEqual(get_plugin_config(plugin, 'foo'), 123) self.assertEqual(get_plugin_config(plugin, 'bar'), None) self.assertEqual(get_plugin_config(plugin, 'bar', default=456), 456) + + def test_events_pipeline(self): + """ + Check that events pipeline is registered. + """ + self.assertIn('netbox.tests.dummy_plugin.events.process_events_queue', settings.EVENTS_PIPELINE) diff --git a/netbox/netbox/tests/test_views.py b/netbox/netbox/tests/test_views.py index ccba73baa..50cfa5755 100644 --- a/netbox/netbox/tests/test_views.py +++ b/netbox/netbox/tests/test_views.py @@ -1,7 +1,7 @@ import urllib.parse from django.urls import reverse -from django.test import override_settings +from django.test import Client, override_settings from dcim.models import Site from netbox.constants import EMPTY_TABLE_TEXT @@ -74,3 +74,21 @@ class SearchViewTestCase(TestCase): self.assertHttpStatus(response, 200) content = str(response.content) self.assertIn(EMPTY_TABLE_TEXT, content) + + +class MediaViewTestCase(TestCase): + + def test_media_login_required(self): + url = reverse('media', kwargs={'path': 'foo.txt'}) + response = Client().get(url) + + # Unauthenticated request should redirect to login page + self.assertHttpStatus(response, 302) + + @override_settings(LOGIN_REQUIRED=False) + def test_media_login_not_required(self): + url = reverse('media', kwargs={'path': 'foo.txt'}) + response = Client().get(url) + + # Unauthenticated request should return a 404 (not found) + self.assertHttpStatus(response, 404) diff --git a/netbox/netbox/urls.py b/netbox/netbox/urls.py index 08c9a46a8..90d70a357 100644 --- a/netbox/netbox/urls.py +++ b/netbox/netbox/urls.py @@ -2,7 +2,6 @@ from django.conf import settings from django.conf.urls import include from django.urls import path from django.views.decorators.cache import cache_page -from django.views.static import serve from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView from account.views import LoginView, LogoutView @@ -10,7 +9,7 @@ from netbox.api.views import APIRootView, StatusView from netbox.graphql.schema import schema from netbox.graphql.views import NetBoxGraphQLView from netbox.plugins.urls import plugin_patterns, plugin_api_patterns -from netbox.views import HomeView, StaticMediaFailureView, SearchView, htmx +from netbox.views import HomeView, MediaView, StaticMediaFailureView, SearchView, htmx _patterns = [ @@ -69,7 +68,7 @@ _patterns = [ path('graphql/', NetBoxGraphQLView.as_view(schema=schema), name='graphql'), # Serving static media in Django to pipe it through LoginRequiredMiddleware - path('media/', serve, {'document_root': settings.MEDIA_ROOT}), + path('media/', MediaView.as_view(), name='media'), path('media-failure/', StaticMediaFailureView.as_view(), name='media_failure'), # Plugins diff --git a/netbox/netbox/utils.py b/netbox/netbox/utils.py index f27d1b5f7..f2c34722c 100644 --- a/netbox/netbox/utils.py +++ b/netbox/netbox/utils.py @@ -3,6 +3,7 @@ from netbox.registry import registry __all__ = ( 'get_data_backend_choices', 'register_data_backend', + 'register_request_processor', ) @@ -24,3 +25,12 @@ def register_data_backend(): return cls return _wrapper + + +def register_request_processor(func): + """ + Decorator for registering a request processor. + """ + registry['request_processors'].append(func) + + return func diff --git a/netbox/netbox/views/errors.py b/netbox/netbox/views/errors.py index 9e8ed5a3a..5872a59cd 100644 --- a/netbox/netbox/views/errors.py +++ b/netbox/netbox/views/errors.py @@ -49,7 +49,7 @@ def handler_500(request, template_name=ERROR_500_TEMPLATE_NAME): template = loader.get_template(template_name) except TemplateDoesNotExist: return HttpResponseServerError('

    Server Error (500)

    ', content_type='text/html') - type_, error, traceback = sys.exc_info() + type_, error = sys.exc_info()[:2] return HttpResponseServerError(template.render({ 'error': error, diff --git a/netbox/netbox/views/generic/bulk_views.py b/netbox/netbox/views/generic/bulk_views.py index d8c4c5e27..c8636b4de 100644 --- a/netbox/netbox/views/generic/bulk_views.py +++ b/netbox/netbox/views/generic/bulk_views.py @@ -3,7 +3,7 @@ import re from copy import deepcopy from django.contrib import messages -from django.contrib.contenttypes.fields import GenericRel +from django.contrib.contenttypes.fields import GenericForeignKey, GenericRel from django.contrib.contenttypes.models import ContentType from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist, ValidationError from django.db import transaction, IntegrityError @@ -567,6 +567,17 @@ class BulkEditView(GetReturnURLMixin, BaseMultiObjectView): def get_required_permission(self): return get_permission_for_model(self.queryset.model, 'change') + def post_save_operations(self, form, obj): + """ + This method is called for each object in _update_objects. Override to perform additional object-level + operations that are specific to a particular ModelForm. + """ + # Add/remove tags + if form.cleaned_data.get('add_tags', None): + obj.tags.add(*form.cleaned_data['add_tags']) + if form.cleaned_data.get('remove_tags', None): + obj.tags.remove(*form.cleaned_data['remove_tags']) + def _update_objects(self, form, request): custom_fields = getattr(form, 'custom_fields', {}) standard_fields = [ @@ -602,7 +613,10 @@ class BulkEditView(GetReturnURLMixin, BaseMultiObjectView): for name, model_field in model_fields.items(): # Handle nullification if name in form.nullable_fields and name in nullified_fields: - setattr(obj, name, None if model_field.null else '') + if type(model_field) is GenericForeignKey: + setattr(obj, name, None) + else: + setattr(obj, name, None if model_field.null else '') # Normal fields elif name in form.changed_data: setattr(obj, name, form.cleaned_data[name]) @@ -635,11 +649,7 @@ class BulkEditView(GetReturnURLMixin, BaseMultiObjectView): elif form.cleaned_data[name]: getattr(obj, name).set(form.cleaned_data[name]) - # Add/remove tags - if form.cleaned_data.get('add_tags', None): - obj.tags.add(*form.cleaned_data['add_tags']) - if form.cleaned_data.get('remove_tags', None): - obj.tags.remove(*form.cleaned_data['remove_tags']) + self.post_save_operations(form, obj) # Rebuild the tree for MPTT models if issubclass(self.queryset.model, MPTTModel): @@ -677,15 +687,13 @@ class BulkEditView(GetReturnURLMixin, BaseMultiObjectView): elif 'virtual_machine' in request.GET: initial_data['virtual_machine'] = request.GET.get('virtual_machine') - if '_apply' in request.POST: - form = self.form(request.POST, initial=initial_data) - restrict_form_fields(form, request.user) + form = self.form(request.POST, initial=initial_data) + restrict_form_fields(form, request.user) + if '_apply' in request.POST: if form.is_valid(): logger.debug("Form validation was successful") - try: - with transaction.atomic(): updated_objects = self._update_objects(form, request) @@ -713,10 +721,6 @@ class BulkEditView(GetReturnURLMixin, BaseMultiObjectView): else: logger.debug("Form validation failed") - else: - form = self.form(initial=initial_data) - restrict_form_fields(form, request.user) - # Retrieve objects being edited table = self.table(self.queryset.filter(pk__in=pk_list), orderable=False) if not table.rows: @@ -760,7 +764,6 @@ class BulkRenameView(GetReturnURLMixin, BaseMultiObjectView): renamed_pks = [] for obj in selected_objects: - # Take a snapshot of change-logged models if hasattr(obj, 'snapshot'): obj.snapshot() @@ -774,7 +777,7 @@ class BulkRenameView(GetReturnURLMixin, BaseMultiObjectView): except re.error: obj.new_name = obj.name else: - obj.new_name = obj.name.replace(find, replace) + obj.new_name = (obj.name or '').replace(find, replace) renamed_pks.append(obj.pk) return renamed_pks @@ -809,6 +812,10 @@ class BulkRenameView(GetReturnURLMixin, BaseMultiObjectView): ) return redirect(self.get_return_url(request)) + except IntegrityError as e: + messages.error(self.request, ", ".join(e.args)) + clear_events.send(sender=self) + except (AbortRequest, PermissionsViolation) as e: logger.debug(e.message) form.add_error(None, e.message) @@ -1011,7 +1018,8 @@ class BulkComponentCreateView(GetReturnURLMixin, BaseMultiObjectView): form.add_error(field, '{}: {}'.format(obj, ', '.join(e))) # Enforce object-level permissions - if self.queryset.filter(pk__in=[obj.pk for obj in new_components]).count() != len(new_components): + component_ids = [obj.pk for obj in new_components] + if self.queryset.filter(pk__in=component_ids).count() != len(new_components): raise PermissionsViolation except IntegrityError: diff --git a/netbox/netbox/views/generic/feature_views.py b/netbox/netbox/views/generic/feature_views.py index 451c9c01d..1e17d5354 100644 --- a/netbox/netbox/views/generic/feature_views.py +++ b/netbox/netbox/views/generic/feature_views.py @@ -4,7 +4,7 @@ from django.contrib import messages from django.db import transaction from django.db.models import Q from django.shortcuts import get_object_or_404, redirect, render -from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy as _ from django.views.generic import View from core.models import Job, ObjectChange @@ -143,7 +143,12 @@ class ObjectJobsView(ConditionalLoginRequiredMixin, View): """ Render a list of all Job assigned to an object. For example: - path('data-sources//jobs/', ObjectJobsView.as_view(), name='datasource_jobs', kwargs={'model': DataSource}), + path( + 'data-sources//jobs/', + ObjectJobsView.as_view(), + name='datasource_jobs', + kwargs={'model': DataSource} + ) Attributes: base_template: The name of the template to extend. If not provided, "{app}/{model}.html" will be used. diff --git a/netbox/netbox/views/generic/object_views.py b/netbox/netbox/views/generic/object_views.py index 0686e52b7..fb554ca4f 100644 --- a/netbox/netbox/views/generic/object_views.py +++ b/netbox/netbox/views/generic/object_views.py @@ -233,18 +233,23 @@ class ObjectEditView(GetReturnURLMixin, BaseObjectView): form = self.form(instance=obj, initial=initial_data) restrict_form_fields(form, request.user) - # If this is an HTMX request, return only the rendered form HTML - if htmx_partial(request): - return render(request, self.htmx_template_name, { - 'model': model, - 'object': obj, - 'form': form, - }) - - return render(request, self.template_name, { + context = { 'model': model, 'object': obj, 'form': form, + } + + # If the form is being displayed within a "quick add" widget, + # use the appropriate template + if request.GET.get('_quickadd'): + return render(request, 'htmx/quick_add.html', context) + + # If this is an HTMX request, return only the rendered form HTML + if htmx_partial(request): + return render(request, self.htmx_template_name, context) + + return render(request, self.template_name, { + **context, 'return_url': self.get_return_url(request, obj), 'prerequisite_model': get_prerequisite_model(self.queryset), **self.get_extra_context(request, obj), @@ -259,6 +264,7 @@ class ObjectEditView(GetReturnURLMixin, BaseObjectView): """ logger = logging.getLogger('netbox.views.ObjectEditView') obj = self.get_object(**kwargs) + model = self.queryset.model # Take a snapshot for change logging (if editing an existing object) if obj.pk and hasattr(obj, 'snapshot'): @@ -292,6 +298,12 @@ class ObjectEditView(GetReturnURLMixin, BaseObjectView): msg = f'{msg} {obj}' messages.success(request, msg) + # Object was created via "quick add" modal + if '_quickadd' in request.POST: + return render(request, 'htmx/quick_add_created.html', { + 'object': obj, + }) + # If adding another object, redirect back to the edit form if '_addanother' in request.POST: redirect_url = request.path @@ -324,12 +336,19 @@ class ObjectEditView(GetReturnURLMixin, BaseObjectView): else: logger.debug("Form validation failed") - return render(request, self.template_name, { + context = { + 'model': model, 'object': obj, 'form': form, 'return_url': self.get_return_url(request, obj), **self.get_extra_context(request, obj), - }) + } + + # Form was submitted via a "quick add" widget + if '_quickadd' in request.POST: + return render(request, 'htmx/quick_add.html', context) + + return render(request, self.template_name, context) class ObjectDeleteView(GetReturnURLMixin, BaseObjectView): diff --git a/netbox/netbox/views/misc.py b/netbox/netbox/views/misc.py index c584e99e4..f28b0f7b1 100644 --- a/netbox/netbox/views/misc.py +++ b/netbox/netbox/views/misc.py @@ -8,6 +8,7 @@ from django.core.cache import cache from django.shortcuts import redirect, render from django.utils.translation import gettext_lazy as _ from django.views.generic import View +from django.views.static import serve from django_tables2 import RequestConfig from packaging import version @@ -23,6 +24,7 @@ from utilities.views import ConditionalLoginRequiredMixin __all__ = ( 'HomeView', + 'MediaView', 'SearchView', ) @@ -115,3 +117,11 @@ class SearchView(ConditionalLoginRequiredMixin, View): 'form': form, 'table': table, }) + + +class MediaView(ConditionalLoginRequiredMixin, View): + """ + Wrap Django's serve() view to enforce LOGIN_REQUIRED for static media. + """ + def get(self, request, path): + return serve(request, path, document_root=settings.MEDIA_ROOT) diff --git a/netbox/project-static/dist/graphiql/graphiql.min.js b/netbox/project-static/dist/graphiql/graphiql.min.js index 862ce3a80..03d4ac1e1 100644 --- a/netbox/project-static/dist/graphiql/graphiql.min.js +++ b/netbox/project-static/dist/graphiql/graphiql.min.js @@ -22986,17 +22986,79 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.GraphQLError = void 0; +exports.formatError = formatError; +exports.printError = printError; var _isObjectLike = __webpack_require__(/*! ../jsutils/isObjectLike.mjs */ "../../../node_modules/graphql/jsutils/isObjectLike.mjs"); var _location = __webpack_require__(/*! ../language/location.mjs */ "../../../node_modules/graphql/language/location.mjs"); var _printLocation = __webpack_require__(/*! ../language/printLocation.mjs */ "../../../node_modules/graphql/language/printLocation.mjs"); +function toNormalizedOptions(args) { + const firstArg = args[0]; + if (firstArg == null || 'kind' in firstArg || 'length' in firstArg) { + return { + nodes: firstArg, + source: args[1], + positions: args[2], + path: args[3], + originalError: args[4], + extensions: args[5] + }; + } + return firstArg; +} /** * A GraphQLError describes an Error found during the parse, validate, or * execute phases of performing a GraphQL operation. In addition to a message * and stack trace, it also includes information about the locations in a * GraphQL document and/or execution result that correspond to the Error. */ + class GraphQLError extends Error { - constructor(message, options = {}) { + /** + * An array of `{ line, column }` locations within the source GraphQL document + * which correspond to this error. + * + * Errors during validation often contain multiple locations, for example to + * point out two things with the same name. Errors during execution include a + * single location, the field which produced the error. + * + * Enumerable, and appears in the result of JSON.stringify(). + */ + + /** + * An array describing the JSON-path into the execution response which + * corresponds to this error. Only included for errors during execution. + * + * Enumerable, and appears in the result of JSON.stringify(). + */ + + /** + * An array of GraphQL AST Nodes corresponding to this error. + */ + + /** + * The source GraphQL document for the first location of this error. + * + * Note that if this Error represents more than one node, the source may not + * represent nodes after the first node. + */ + + /** + * An array of character offsets within the source GraphQL document + * which correspond to this error. + */ + + /** + * The original error thrown from a field resolver during execution. + */ + + /** + * Extension fields to add to the formatted error. + */ + + /** + * @deprecated Please use the `GraphQLErrorOptions` constructor overload instead. + */ + constructor(message, ...rawArgs) { var _this$nodes, _nodeLocations$, _ref; const { nodes, @@ -23005,22 +23067,22 @@ class GraphQLError extends Error { path, originalError, extensions - } = options; + } = toNormalizedOptions(rawArgs); super(message); this.name = 'GraphQLError'; this.path = path !== null && path !== void 0 ? path : undefined; - this.originalError = originalError !== null && originalError !== void 0 ? originalError : undefined; - // Compute list of blame nodes. + this.originalError = originalError !== null && originalError !== void 0 ? originalError : undefined; // Compute list of blame nodes. + this.nodes = undefinedIfEmpty(Array.isArray(nodes) ? nodes : nodes ? [nodes] : undefined); - const nodeLocations = undefinedIfEmpty((_this$nodes = this.nodes) === null || _this$nodes === void 0 ? void 0 : _this$nodes.map(node => node.loc).filter(loc => loc != null)); - // Compute locations in the source for the given nodes/positions. + const nodeLocations = undefinedIfEmpty((_this$nodes = this.nodes) === null || _this$nodes === void 0 ? void 0 : _this$nodes.map(node => node.loc).filter(loc => loc != null)); // Compute locations in the source for the given nodes/positions. + this.source = source !== null && source !== void 0 ? source : nodeLocations === null || nodeLocations === void 0 ? void 0 : (_nodeLocations$ = nodeLocations[0]) === null || _nodeLocations$ === void 0 ? void 0 : _nodeLocations$.source; this.positions = positions !== null && positions !== void 0 ? positions : nodeLocations === null || nodeLocations === void 0 ? void 0 : nodeLocations.map(loc => loc.start); this.locations = positions && source ? positions.map(pos => (0, _location.getLocation)(source, pos)) : nodeLocations === null || nodeLocations === void 0 ? void 0 : nodeLocations.map(loc => (0, _location.getLocation)(loc.source, loc.start)); const originalExtensions = (0, _isObjectLike.isObjectLike)(originalError === null || originalError === void 0 ? void 0 : originalError.extensions) ? originalError === null || originalError === void 0 ? void 0 : originalError.extensions : undefined; - this.extensions = (_ref = extensions !== null && extensions !== void 0 ? extensions : originalExtensions) !== null && _ref !== void 0 ? _ref : Object.create(null); - // Only properties prescribed by the spec should be enumerable. + this.extensions = (_ref = extensions !== null && extensions !== void 0 ? extensions : originalExtensions) !== null && _ref !== void 0 ? _ref : Object.create(null); // Only properties prescribed by the spec should be enumerable. // Keep the rest as non-enumerable. + Object.defineProperties(this, { message: { writable: true, @@ -23041,17 +23103,18 @@ class GraphQLError extends Error { originalError: { enumerable: false } - }); - // Include (non-enumerable) stack trace. + }); // Include (non-enumerable) stack trace. + /* c8 ignore start */ // FIXME: https://github.com/graphql/graphql-js/issues/2317 - if ((originalError === null || originalError === void 0 ? void 0 : originalError.stack) != null) { + + if (originalError !== null && originalError !== void 0 && originalError.stack) { Object.defineProperty(this, 'stack', { value: originalError.stack, writable: true, configurable: true }); - } else if (Error.captureStackTrace != null) { + } else if (Error.captureStackTrace) { Error.captureStackTrace(this, GraphQLError); } else { Object.defineProperty(this, 'stack', { @@ -23100,6 +23163,29 @@ exports.GraphQLError = GraphQLError; function undefinedIfEmpty(array) { return array === undefined || array.length === 0 ? undefined : array; } +/** + * See: https://spec.graphql.org/draft/#sec-Errors + */ + +/** + * Prints a GraphQLError to a string, representing useful location information + * about the error's position in the source. + * + * @deprecated Please use `error.toString` instead. Will be removed in v17 + */ +function printError(error) { + return error.toString(); +} +/** + * Given a GraphQLError, format it according to the rules described by the + * Response Format, Errors section of the GraphQL Specification. + * + * @deprecated Please use `error.toJSON` instead. Will be removed in v17 + */ + +function formatError(error) { + return error.toJSON(); +} /***/ }), @@ -23120,12 +23206,24 @@ Object.defineProperty(exports, "GraphQLError", ({ return _GraphQLError.GraphQLError; } })); +Object.defineProperty(exports, "formatError", ({ + enumerable: true, + get: function () { + return _GraphQLError.formatError; + } +})); Object.defineProperty(exports, "locatedError", ({ enumerable: true, get: function () { return _locatedError.locatedError; } })); +Object.defineProperty(exports, "printError", ({ + enumerable: true, + get: function () { + return _GraphQLError.printError; + } +})); Object.defineProperty(exports, "syntaxError", ({ enumerable: true, get: function () { @@ -23157,15 +23255,16 @@ var _GraphQLError = __webpack_require__(/*! ./GraphQLError.mjs */ "../../../node * GraphQL operation, produce a new GraphQLError aware of the location in the * document responsible for the original Error. */ + function locatedError(rawOriginalError, nodes, path) { - var _originalError$nodes; - const originalError = (0, _toError.toError)(rawOriginalError); - // Note: this uses a brand-check to support GraphQL errors originating from other contexts. + var _nodes; + const originalError = (0, _toError.toError)(rawOriginalError); // Note: this uses a brand-check to support GraphQL errors originating from other contexts. + if (isLocatedGraphQLError(originalError)) { return originalError; } return new _GraphQLError.GraphQLError(originalError.message, { - nodes: (_originalError$nodes = originalError.nodes) !== null && _originalError$nodes !== void 0 ? _originalError$nodes : nodes, + nodes: (_nodes = originalError.nodes) !== null && _nodes !== void 0 ? _nodes : nodes, source: originalError.source, positions: originalError.positions, path, @@ -23195,6 +23294,7 @@ var _GraphQLError = __webpack_require__(/*! ./GraphQLError.mjs */ "../../../node * Produces a GraphQLError representing a syntax error, containing useful * descriptive information about the syntax error's position in the source. */ + function syntaxError(source, position, description) { return new _GraphQLError.GraphQLError(`Syntax Error: ${description}`, { source, @@ -23204,613 +23304,6 @@ function syntaxError(source, position, description) { /***/ }), -/***/ "../../../node_modules/graphql/execution/IncrementalGraph.mjs": -/*!********************************************************************!*\ - !*** ../../../node_modules/graphql/execution/IncrementalGraph.mjs ***! - \********************************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.IncrementalGraph = void 0; -var _BoxedPromiseOrValue = __webpack_require__(/*! ../jsutils/BoxedPromiseOrValue.mjs */ "../../../node_modules/graphql/jsutils/BoxedPromiseOrValue.mjs"); -var _invariant = __webpack_require__(/*! ../jsutils/invariant.mjs */ "../../../node_modules/graphql/jsutils/invariant.mjs"); -var _isPromise = __webpack_require__(/*! ../jsutils/isPromise.mjs */ "../../../node_modules/graphql/jsutils/isPromise.mjs"); -var _promiseWithResolvers = __webpack_require__(/*! ../jsutils/promiseWithResolvers.mjs */ "../../../node_modules/graphql/jsutils/promiseWithResolvers.mjs"); -var _types = __webpack_require__(/*! ./types.mjs */ "../../../node_modules/graphql/execution/types.mjs"); -/** - * @internal - */ -class IncrementalGraph { - constructor() { - this._rootNodes = new Set(); - this._completedQueue = []; - this._nextQueue = []; - } - getNewRootNodes(incrementalDataRecords) { - const initialResultChildren = new Set(); - this._addIncrementalDataRecords(incrementalDataRecords, undefined, initialResultChildren); - return this._promoteNonEmptyToRoot(initialResultChildren); - } - addCompletedSuccessfulExecutionGroup(successfulExecutionGroup) { - for (const deferredFragmentRecord of successfulExecutionGroup.pendingExecutionGroup.deferredFragmentRecords) { - deferredFragmentRecord.pendingExecutionGroups.delete(successfulExecutionGroup.pendingExecutionGroup); - deferredFragmentRecord.successfulExecutionGroups.add(successfulExecutionGroup); - } - const incrementalDataRecords = successfulExecutionGroup.incrementalDataRecords; - if (incrementalDataRecords !== undefined) { - this._addIncrementalDataRecords(incrementalDataRecords, successfulExecutionGroup.pendingExecutionGroup.deferredFragmentRecords); - } - } - *currentCompletedBatch() { - let completed; - while ((completed = this._completedQueue.shift()) !== undefined) { - yield completed; - } - if (this._rootNodes.size === 0) { - for (const resolve of this._nextQueue) { - resolve(undefined); - } - } - } - nextCompletedBatch() { - const { - promise, - resolve - } = (0, _promiseWithResolvers.promiseWithResolvers)(); - this._nextQueue.push(resolve); - return promise; - } - abort() { - for (const resolve of this._nextQueue) { - resolve(undefined); - } - } - hasNext() { - return this._rootNodes.size > 0; - } - completeDeferredFragment(deferredFragmentRecord) { - if (!this._rootNodes.has(deferredFragmentRecord) || deferredFragmentRecord.pendingExecutionGroups.size > 0) { - return; - } - const successfulExecutionGroups = Array.from(deferredFragmentRecord.successfulExecutionGroups); - this._removeRootNode(deferredFragmentRecord); - for (const successfulExecutionGroup of successfulExecutionGroups) { - for (const otherDeferredFragmentRecord of successfulExecutionGroup.pendingExecutionGroup.deferredFragmentRecords) { - otherDeferredFragmentRecord.successfulExecutionGroups.delete(successfulExecutionGroup); - } - } - const newRootNodes = this._promoteNonEmptyToRoot(deferredFragmentRecord.children); - return { - newRootNodes, - successfulExecutionGroups - }; - } - removeDeferredFragment(deferredFragmentRecord) { - if (!this._rootNodes.has(deferredFragmentRecord)) { - return false; - } - this._removeRootNode(deferredFragmentRecord); - return true; - } - removeStream(streamRecord) { - this._removeRootNode(streamRecord); - } - _removeRootNode(deliveryGroup) { - this._rootNodes.delete(deliveryGroup); - } - _addIncrementalDataRecords(incrementalDataRecords, parents, initialResultChildren) { - for (const incrementalDataRecord of incrementalDataRecords) { - if ((0, _types.isPendingExecutionGroup)(incrementalDataRecord)) { - for (const deferredFragmentRecord of incrementalDataRecord.deferredFragmentRecords) { - this._addDeferredFragment(deferredFragmentRecord, initialResultChildren); - deferredFragmentRecord.pendingExecutionGroups.add(incrementalDataRecord); - } - if (this._completesRootNode(incrementalDataRecord)) { - this._onExecutionGroup(incrementalDataRecord); - } - } else if (parents === undefined) { - initialResultChildren !== undefined || (0, _invariant.invariant)(false); - initialResultChildren.add(incrementalDataRecord); - } else { - for (const parent of parents) { - this._addDeferredFragment(parent, initialResultChildren); - parent.children.add(incrementalDataRecord); - } - } - } - } - _promoteNonEmptyToRoot(maybeEmptyNewRootNodes) { - const newRootNodes = []; - for (const node of maybeEmptyNewRootNodes) { - if ((0, _types.isDeferredFragmentRecord)(node)) { - if (node.pendingExecutionGroups.size > 0) { - for (const pendingExecutionGroup of node.pendingExecutionGroups) { - if (!this._completesRootNode(pendingExecutionGroup)) { - this._onExecutionGroup(pendingExecutionGroup); - } - } - this._rootNodes.add(node); - newRootNodes.push(node); - continue; - } - for (const child of node.children) { - maybeEmptyNewRootNodes.add(child); - } - } else { - this._rootNodes.add(node); - newRootNodes.push(node); - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this._onStreamItems(node); - } - } - return newRootNodes; - } - _completesRootNode(pendingExecutionGroup) { - return pendingExecutionGroup.deferredFragmentRecords.some(deferredFragmentRecord => this._rootNodes.has(deferredFragmentRecord)); - } - _addDeferredFragment(deferredFragmentRecord, initialResultChildren) { - if (this._rootNodes.has(deferredFragmentRecord)) { - return; - } - const parent = deferredFragmentRecord.parent; - if (parent === undefined) { - initialResultChildren !== undefined || (0, _invariant.invariant)(false); - initialResultChildren.add(deferredFragmentRecord); - return; - } - parent.children.add(deferredFragmentRecord); - this._addDeferredFragment(parent, initialResultChildren); - } - _onExecutionGroup(pendingExecutionGroup) { - let completedExecutionGroup = pendingExecutionGroup.result; - if (!(completedExecutionGroup instanceof _BoxedPromiseOrValue.BoxedPromiseOrValue)) { - completedExecutionGroup = completedExecutionGroup(); - } - const value = completedExecutionGroup.value; - if ((0, _isPromise.isPromise)(value)) { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - value.then(resolved => this._enqueue(resolved)); - } else { - this._enqueue(value); - } - } - async _onStreamItems(streamRecord) { - let items = []; - let errors = []; - let incrementalDataRecords = []; - const streamItemQueue = streamRecord.streamItemQueue; - let streamItemRecord; - while ((streamItemRecord = streamItemQueue.shift()) !== undefined) { - let result = streamItemRecord instanceof _BoxedPromiseOrValue.BoxedPromiseOrValue ? streamItemRecord.value : streamItemRecord().value; - if ((0, _isPromise.isPromise)(result)) { - if (items.length > 0) { - this._enqueue({ - streamRecord, - result: - // TODO add additional test case or rework for coverage - errors.length > 0 /* c8 ignore start */ ? { - items, - errors - } /* c8 ignore stop */ : { - items - }, - incrementalDataRecords - }); - items = []; - errors = []; - incrementalDataRecords = []; - } - // eslint-disable-next-line no-await-in-loop - result = await result; - // wait an additional tick to coalesce resolving additional promises - // within the queue - // eslint-disable-next-line no-await-in-loop - await Promise.resolve(); - } - if (result.item === undefined) { - if (items.length > 0) { - this._enqueue({ - streamRecord, - result: errors.length > 0 ? { - items, - errors - } : { - items - }, - incrementalDataRecords - }); - } - this._enqueue(result.errors === undefined ? { - streamRecord - } : { - streamRecord, - errors: result.errors - }); - return; - } - items.push(result.item); - if (result.errors !== undefined) { - errors.push(...result.errors); - } - if (result.incrementalDataRecords !== undefined) { - incrementalDataRecords.push(...result.incrementalDataRecords); - } - } - } - *_yieldCurrentCompletedIncrementalData(first) { - yield first; - yield* this.currentCompletedBatch(); - } - _enqueue(completed) { - const next = this._nextQueue.shift(); - if (next !== undefined) { - next(this._yieldCurrentCompletedIncrementalData(completed)); - return; - } - this._completedQueue.push(completed); - } -} -exports.IncrementalGraph = IncrementalGraph; - -/***/ }), - -/***/ "../../../node_modules/graphql/execution/IncrementalPublisher.mjs": -/*!************************************************************************!*\ - !*** ../../../node_modules/graphql/execution/IncrementalPublisher.mjs ***! - \************************************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.buildIncrementalResponse = buildIncrementalResponse; -var _invariant = __webpack_require__(/*! ../jsutils/invariant.mjs */ "../../../node_modules/graphql/jsutils/invariant.mjs"); -var _Path = __webpack_require__(/*! ../jsutils/Path.mjs */ "../../../node_modules/graphql/jsutils/Path.mjs"); -var _IncrementalGraph = __webpack_require__(/*! ./IncrementalGraph.mjs */ "../../../node_modules/graphql/execution/IncrementalGraph.mjs"); -var _types = __webpack_require__(/*! ./types.mjs */ "../../../node_modules/graphql/execution/types.mjs"); -function buildIncrementalResponse(context, result, errors, incrementalDataRecords) { - const incrementalPublisher = new IncrementalPublisher(context); - return incrementalPublisher.buildResponse(result, errors, incrementalDataRecords); -} -/** - * This class is used to publish incremental results to the client, enabling semi-concurrent - * execution while preserving result order. - * - * @internal - */ -class IncrementalPublisher { - constructor(context) { - this._context = context; - this._nextId = 0; - this._incrementalGraph = new _IncrementalGraph.IncrementalGraph(); - } - buildResponse(data, errors, incrementalDataRecords) { - const newRootNodes = this._incrementalGraph.getNewRootNodes(incrementalDataRecords); - const pending = this._toPendingResults(newRootNodes); - const initialResult = errors === undefined ? { - data, - pending, - hasNext: true - } : { - errors, - data, - pending, - hasNext: true - }; - return { - initialResult, - subsequentResults: this._subscribe() - }; - } - _toPendingResults(newRootNodes) { - const pendingResults = []; - for (const node of newRootNodes) { - const id = String(this._getNextId()); - node.id = id; - const pendingResult = { - id, - path: (0, _Path.pathToArray)(node.path) - }; - if (node.label !== undefined) { - pendingResult.label = node.label; - } - pendingResults.push(pendingResult); - } - return pendingResults; - } - _getNextId() { - return String(this._nextId++); - } - _subscribe() { - let isDone = false; - const _next = async () => { - if (isDone) { - await this._returnAsyncIteratorsIgnoringErrors(); - return { - value: undefined, - done: true - }; - } - const context = { - pending: [], - incremental: [], - completed: [] - }; - let batch = this._incrementalGraph.currentCompletedBatch(); - do { - for (const completedResult of batch) { - this._handleCompletedIncrementalData(completedResult, context); - } - const { - incremental, - completed - } = context; - if (incremental.length > 0 || completed.length > 0) { - const hasNext = this._incrementalGraph.hasNext(); - if (!hasNext) { - isDone = true; - } - const subsequentIncrementalExecutionResult = { - hasNext - }; - const pending = context.pending; - if (pending.length > 0) { - subsequentIncrementalExecutionResult.pending = pending; - } - if (incremental.length > 0) { - subsequentIncrementalExecutionResult.incremental = incremental; - } - if (completed.length > 0) { - subsequentIncrementalExecutionResult.completed = completed; - } - return { - value: subsequentIncrementalExecutionResult, - done: false - }; - } - // eslint-disable-next-line no-await-in-loop - batch = await this._incrementalGraph.nextCompletedBatch(); - } while (batch !== undefined); - await this._returnAsyncIteratorsIgnoringErrors(); - return { - value: undefined, - done: true - }; - }; - const _return = async () => { - isDone = true; - this._incrementalGraph.abort(); - await this._returnAsyncIterators(); - return { - value: undefined, - done: true - }; - }; - const _throw = async error => { - isDone = true; - this._incrementalGraph.abort(); - await this._returnAsyncIterators(); - return Promise.reject(error); - }; - return { - [Symbol.asyncIterator]() { - return this; - }, - next: _next, - return: _return, - throw: _throw - }; - } - _handleCompletedIncrementalData(completedIncrementalData, context) { - if ((0, _types.isCompletedExecutionGroup)(completedIncrementalData)) { - this._handleCompletedExecutionGroup(completedIncrementalData, context); - } else { - this._handleCompletedStreamItems(completedIncrementalData, context); - } - } - _handleCompletedExecutionGroup(completedExecutionGroup, context) { - if ((0, _types.isFailedExecutionGroup)(completedExecutionGroup)) { - for (const deferredFragmentRecord of completedExecutionGroup.pendingExecutionGroup.deferredFragmentRecords) { - const id = deferredFragmentRecord.id; - if (!this._incrementalGraph.removeDeferredFragment(deferredFragmentRecord)) { - // This can occur if multiple deferred grouped field sets error for a fragment. - continue; - } - id !== undefined || (0, _invariant.invariant)(false); - context.completed.push({ - id, - errors: completedExecutionGroup.errors - }); - } - return; - } - this._incrementalGraph.addCompletedSuccessfulExecutionGroup(completedExecutionGroup); - for (const deferredFragmentRecord of completedExecutionGroup.pendingExecutionGroup.deferredFragmentRecords) { - const completion = this._incrementalGraph.completeDeferredFragment(deferredFragmentRecord); - if (completion === undefined) { - continue; - } - const id = deferredFragmentRecord.id; - id !== undefined || (0, _invariant.invariant)(false); - const incremental = context.incremental; - const { - newRootNodes, - successfulExecutionGroups - } = completion; - context.pending.push(...this._toPendingResults(newRootNodes)); - for (const successfulExecutionGroup of successfulExecutionGroups) { - const { - bestId, - subPath - } = this._getBestIdAndSubPath(id, deferredFragmentRecord, successfulExecutionGroup); - const incrementalEntry = { - ...successfulExecutionGroup.result, - id: bestId - }; - if (subPath !== undefined) { - incrementalEntry.subPath = subPath; - } - incremental.push(incrementalEntry); - } - context.completed.push({ - id - }); - } - } - _handleCompletedStreamItems(streamItemsResult, context) { - const streamRecord = streamItemsResult.streamRecord; - const id = streamRecord.id; - id !== undefined || (0, _invariant.invariant)(false); - if (streamItemsResult.errors !== undefined) { - context.completed.push({ - id, - errors: streamItemsResult.errors - }); - this._incrementalGraph.removeStream(streamRecord); - if ((0, _types.isCancellableStreamRecord)(streamRecord)) { - this._context.cancellableStreams !== undefined || (0, _invariant.invariant)(false); - this._context.cancellableStreams.delete(streamRecord); - streamRecord.earlyReturn().catch(() => { - /* c8 ignore next 1 */ - // ignore error - }); - } - } else if (streamItemsResult.result === undefined) { - context.completed.push({ - id - }); - this._incrementalGraph.removeStream(streamRecord); - if ((0, _types.isCancellableStreamRecord)(streamRecord)) { - this._context.cancellableStreams !== undefined || (0, _invariant.invariant)(false); - this._context.cancellableStreams.delete(streamRecord); - } - } else { - const incrementalEntry = { - id, - ...streamItemsResult.result - }; - context.incremental.push(incrementalEntry); - const incrementalDataRecords = streamItemsResult.incrementalDataRecords; - if (incrementalDataRecords !== undefined) { - const newRootNodes = this._incrementalGraph.getNewRootNodes(incrementalDataRecords); - context.pending.push(...this._toPendingResults(newRootNodes)); - } - } - } - _getBestIdAndSubPath(initialId, initialDeferredFragmentRecord, completedExecutionGroup) { - let maxLength = (0, _Path.pathToArray)(initialDeferredFragmentRecord.path).length; - let bestId = initialId; - for (const deferredFragmentRecord of completedExecutionGroup.pendingExecutionGroup.deferredFragmentRecords) { - if (deferredFragmentRecord === initialDeferredFragmentRecord) { - continue; - } - const id = deferredFragmentRecord.id; - // TODO: add test case for when an fragment has not been released, but might be processed for the shortest path. - /* c8 ignore next 3 */ - if (id === undefined) { - continue; - } - const fragmentPath = (0, _Path.pathToArray)(deferredFragmentRecord.path); - const length = fragmentPath.length; - if (length > maxLength) { - maxLength = length; - bestId = id; - } - } - const subPath = completedExecutionGroup.path.slice(maxLength); - return { - bestId, - subPath: subPath.length > 0 ? subPath : undefined - }; - } - async _returnAsyncIterators() { - const cancellableStreams = this._context.cancellableStreams; - if (cancellableStreams === undefined) { - return; - } - const promises = []; - for (const streamRecord of cancellableStreams) { - if (streamRecord.earlyReturn !== undefined) { - promises.push(streamRecord.earlyReturn()); - } - } - await Promise.all(promises); - } - async _returnAsyncIteratorsIgnoringErrors() { - await this._returnAsyncIterators().catch(() => { - // Ignore errors - }); - } -} - -/***/ }), - -/***/ "../../../node_modules/graphql/execution/buildExecutionPlan.mjs": -/*!**********************************************************************!*\ - !*** ../../../node_modules/graphql/execution/buildExecutionPlan.mjs ***! - \**********************************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.buildExecutionPlan = buildExecutionPlan; -var _getBySet = __webpack_require__(/*! ../jsutils/getBySet.mjs */ "../../../node_modules/graphql/jsutils/getBySet.mjs"); -var _isSameSet = __webpack_require__(/*! ../jsutils/isSameSet.mjs */ "../../../node_modules/graphql/jsutils/isSameSet.mjs"); -function buildExecutionPlan(originalGroupedFieldSet, parentDeferUsages = new Set()) { - const groupedFieldSet = new Map(); - const newGroupedFieldSets = new Map(); - for (const [responseKey, fieldGroup] of originalGroupedFieldSet) { - const filteredDeferUsageSet = getFilteredDeferUsageSet(fieldGroup); - if ((0, _isSameSet.isSameSet)(filteredDeferUsageSet, parentDeferUsages)) { - groupedFieldSet.set(responseKey, fieldGroup); - continue; - } - let newGroupedFieldSet = (0, _getBySet.getBySet)(newGroupedFieldSets, filteredDeferUsageSet); - if (newGroupedFieldSet === undefined) { - newGroupedFieldSet = new Map(); - newGroupedFieldSets.set(filteredDeferUsageSet, newGroupedFieldSet); - } - newGroupedFieldSet.set(responseKey, fieldGroup); - } - return { - groupedFieldSet, - newGroupedFieldSets - }; -} -function getFilteredDeferUsageSet(fieldGroup) { - const filteredDeferUsageSet = new Set(); - for (const fieldDetails of fieldGroup) { - const deferUsage = fieldDetails.deferUsage; - if (deferUsage === undefined) { - filteredDeferUsageSet.clear(); - return filteredDeferUsageSet; - } - filteredDeferUsageSet.add(deferUsage); - } - for (const deferUsage of filteredDeferUsageSet) { - let parentDeferUsage = deferUsage.parentDeferUsage; - while (parentDeferUsage !== undefined) { - if (filteredDeferUsageSet.has(parentDeferUsage)) { - filteredDeferUsageSet.delete(deferUsage); - break; - } - parentDeferUsage = parentDeferUsage.parentDeferUsage; - } - } - return filteredDeferUsageSet; -} - -/***/ }), - /***/ "../../../node_modules/graphql/execution/collectFields.mjs": /*!*****************************************************************!*\ !*** ../../../node_modules/graphql/execution/collectFields.mjs ***! @@ -23824,9 +23317,6 @@ Object.defineProperty(exports, "__esModule", ({ })); exports.collectFields = collectFields; exports.collectSubfields = collectSubfields; -var _AccumulatorMap = __webpack_require__(/*! ../jsutils/AccumulatorMap.mjs */ "../../../node_modules/graphql/jsutils/AccumulatorMap.mjs"); -var _invariant = __webpack_require__(/*! ../jsutils/invariant.mjs */ "../../../node_modules/graphql/jsutils/invariant.mjs"); -var _ast = __webpack_require__(/*! ../language/ast.mjs */ "../../../node_modules/graphql/language/ast.mjs"); var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); var _definition = __webpack_require__(/*! ../type/definition.mjs */ "../../../node_modules/graphql/type/definition.mjs"); var _directives = __webpack_require__(/*! ../type/directives.mjs */ "../../../node_modules/graphql/type/directives.mjs"); @@ -23841,22 +23331,11 @@ var _values = __webpack_require__(/*! ./values.mjs */ "../../../node_modules/gra * * @internal */ -function collectFields(schema, fragments, variableValues, runtimeType, operation) { - const groupedFieldSet = new _AccumulatorMap.AccumulatorMap(); - const newDeferUsages = []; - const context = { - schema, - fragments, - variableValues, - runtimeType, - operation, - visitedFragmentNames: new Set() - }; - collectFieldsImpl(context, operation.selectionSet, groupedFieldSet, newDeferUsages); - return { - groupedFieldSet, - newDeferUsages - }; + +function collectFields(schema, fragments, variableValues, runtimeType, selectionSet) { + const fields = new Map(); + collectFieldsImpl(schema, fragments, variableValues, runtimeType, selectionSet, fields, new Set()); + return fields; } /** * Given an array of field nodes, collects all of the subfields of the passed @@ -23868,38 +23347,18 @@ function collectFields(schema, fragments, variableValues, runtimeType, operation * * @internal */ -// eslint-disable-next-line max-params -function collectSubfields(schema, fragments, variableValues, operation, returnType, fieldGroup) { - const context = { - schema, - fragments, - variableValues, - runtimeType: returnType, - operation, - visitedFragmentNames: new Set() - }; - const subGroupedFieldSet = new _AccumulatorMap.AccumulatorMap(); - const newDeferUsages = []; - for (const fieldDetail of fieldGroup) { - const node = fieldDetail.node; + +function collectSubfields(schema, fragments, variableValues, returnType, fieldNodes) { + const subFieldNodes = new Map(); + const visitedFragmentNames = new Set(); + for (const node of fieldNodes) { if (node.selectionSet) { - collectFieldsImpl(context, node.selectionSet, subGroupedFieldSet, newDeferUsages, fieldDetail.deferUsage); + collectFieldsImpl(schema, fragments, variableValues, returnType, node.selectionSet, subFieldNodes, visitedFragmentNames); } } - return { - groupedFieldSet: subGroupedFieldSet, - newDeferUsages - }; + return subFieldNodes; } -function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsages, deferUsage) { - const { - schema, - fragments, - variableValues, - runtimeType, - operation, - visitedFragmentNames - } = context; +function collectFieldsImpl(schema, fragments, variableValues, runtimeType, selectionSet, fields, visitedFragmentNames) { for (const selection of selectionSet.selections) { switch (selection.kind) { case _kinds.Kind.FIELD: @@ -23907,10 +23366,13 @@ function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsage if (!shouldIncludeNode(variableValues, selection)) { continue; } - groupedFieldSet.add(getFieldEntryKey(selection), { - node: selection, - deferUsage - }); + const name = getFieldEntryKey(selection); + const fieldList = fields.get(name); + if (fieldList !== undefined) { + fieldList.push(selection); + } else { + fields.set(name, [selection]); + } break; } case _kinds.Kind.INLINE_FRAGMENT: @@ -23918,61 +23380,31 @@ function collectFieldsImpl(context, selectionSet, groupedFieldSet, newDeferUsage if (!shouldIncludeNode(variableValues, selection) || !doesFragmentConditionMatch(schema, selection, runtimeType)) { continue; } - const newDeferUsage = getDeferUsage(operation, variableValues, selection, deferUsage); - if (!newDeferUsage) { - collectFieldsImpl(context, selection.selectionSet, groupedFieldSet, newDeferUsages, deferUsage); - } else { - newDeferUsages.push(newDeferUsage); - collectFieldsImpl(context, selection.selectionSet, groupedFieldSet, newDeferUsages, newDeferUsage); - } + collectFieldsImpl(schema, fragments, variableValues, runtimeType, selection.selectionSet, fields, visitedFragmentNames); break; } case _kinds.Kind.FRAGMENT_SPREAD: { const fragName = selection.name.value; - const newDeferUsage = getDeferUsage(operation, variableValues, selection, deferUsage); - if (!newDeferUsage && (visitedFragmentNames.has(fragName) || !shouldIncludeNode(variableValues, selection))) { + if (visitedFragmentNames.has(fragName) || !shouldIncludeNode(variableValues, selection)) { continue; } + visitedFragmentNames.add(fragName); const fragment = fragments[fragName]; - if (fragment == null || !doesFragmentConditionMatch(schema, fragment, runtimeType)) { + if (!fragment || !doesFragmentConditionMatch(schema, fragment, runtimeType)) { continue; } - if (!newDeferUsage) { - visitedFragmentNames.add(fragName); - collectFieldsImpl(context, fragment.selectionSet, groupedFieldSet, newDeferUsages, deferUsage); - } else { - newDeferUsages.push(newDeferUsage); - collectFieldsImpl(context, fragment.selectionSet, groupedFieldSet, newDeferUsages, newDeferUsage); - } + collectFieldsImpl(schema, fragments, variableValues, runtimeType, fragment.selectionSet, fields, visitedFragmentNames); break; } } } } -/** - * Returns an object containing the `@defer` arguments if a field should be - * deferred based on the experimental flag, defer directive present and - * not disabled by the "if" argument. - */ -function getDeferUsage(operation, variableValues, node, parentDeferUsage) { - const defer = (0, _values.getDirectiveValues)(_directives.GraphQLDeferDirective, node, variableValues); - if (!defer) { - return; - } - if (defer.if === false) { - return; - } - operation.operation !== _ast.OperationTypeNode.SUBSCRIPTION || (0, _invariant.invariant)(false, '`@defer` directive not supported on subscription operations. Disable `@defer` by setting the `if` argument to `false`.'); - return { - label: typeof defer.label === 'string' ? defer.label : undefined, - parentDeferUsage - }; -} /** * Determines if a field should be included based on the `@include` and `@skip` * directives, where `@skip` has higher precedence than `@include`. */ + function shouldIncludeNode(variableValues, node) { const skip = (0, _values.getDirectiveValues)(_directives.GraphQLSkipDirective, node, variableValues); if ((skip === null || skip === void 0 ? void 0 : skip.if) === true) { @@ -23987,6 +23419,7 @@ function shouldIncludeNode(variableValues, node) { /** * Determines if a fragment is applicable to the given type. */ + function doesFragmentConditionMatch(schema, fragment, type) { const typeConditionNode = fragment.typeCondition; if (!typeConditionNode) { @@ -24004,6 +23437,7 @@ function doesFragmentConditionMatch(schema, fragment, type) { /** * Implements the logic to compute the key of a given field's entry */ + function getFieldEntryKey(node) { return node.alias ? node.alias.value : node.name.value; } @@ -24021,18 +23455,16 @@ function getFieldEntryKey(node) { Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.assertValidExecutionArguments = assertValidExecutionArguments; exports.buildExecutionContext = buildExecutionContext; exports.buildResolveInfo = buildResolveInfo; -exports.createSourceEventStream = createSourceEventStream; exports.defaultTypeResolver = exports.defaultFieldResolver = void 0; exports.execute = execute; exports.executeSync = executeSync; -exports.experimentalExecuteIncrementally = experimentalExecuteIncrementally; -exports.subscribe = subscribe; -var _BoxedPromiseOrValue = __webpack_require__(/*! ../jsutils/BoxedPromiseOrValue.mjs */ "../../../node_modules/graphql/jsutils/BoxedPromiseOrValue.mjs"); +exports.getFieldDef = getFieldDef; +var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); var _invariant = __webpack_require__(/*! ../jsutils/invariant.mjs */ "../../../node_modules/graphql/jsutils/invariant.mjs"); -var _isAsyncIterable = __webpack_require__(/*! ../jsutils/isAsyncIterable.mjs */ "../../../node_modules/graphql/jsutils/isAsyncIterable.mjs"); var _isIterableObject = __webpack_require__(/*! ../jsutils/isIterableObject.mjs */ "../../../node_modules/graphql/jsutils/isIterableObject.mjs"); var _isObjectLike = __webpack_require__(/*! ../jsutils/isObjectLike.mjs */ "../../../node_modules/graphql/jsutils/isObjectLike.mjs"); var _isPromise = __webpack_require__(/*! ../jsutils/isPromise.mjs */ "../../../node_modules/graphql/jsutils/isPromise.mjs"); @@ -24045,25 +23477,44 @@ var _locatedError = __webpack_require__(/*! ../error/locatedError.mjs */ "../../ var _ast = __webpack_require__(/*! ../language/ast.mjs */ "../../../node_modules/graphql/language/ast.mjs"); var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); var _definition = __webpack_require__(/*! ../type/definition.mjs */ "../../../node_modules/graphql/type/definition.mjs"); -var _directives = __webpack_require__(/*! ../type/directives.mjs */ "../../../node_modules/graphql/type/directives.mjs"); +var _introspection = __webpack_require__(/*! ../type/introspection.mjs */ "../../../node_modules/graphql/type/introspection.mjs"); var _validate = __webpack_require__(/*! ../type/validate.mjs */ "../../../node_modules/graphql/type/validate.mjs"); -var _buildExecutionPlan = __webpack_require__(/*! ./buildExecutionPlan.mjs */ "../../../node_modules/graphql/execution/buildExecutionPlan.mjs"); var _collectFields = __webpack_require__(/*! ./collectFields.mjs */ "../../../node_modules/graphql/execution/collectFields.mjs"); -var _IncrementalPublisher = __webpack_require__(/*! ./IncrementalPublisher.mjs */ "../../../node_modules/graphql/execution/IncrementalPublisher.mjs"); -var _mapAsyncIterable = __webpack_require__(/*! ./mapAsyncIterable.mjs */ "../../../node_modules/graphql/execution/mapAsyncIterable.mjs"); -var _types = __webpack_require__(/*! ./types.mjs */ "../../../node_modules/graphql/execution/types.mjs"); var _values = __webpack_require__(/*! ./values.mjs */ "../../../node_modules/graphql/execution/values.mjs"); -/* eslint-disable max-params */ -// This file contains a lot of such errors but we plan to refactor it anyway -// so just disable it for entire file. /** * A memoized collection of relevant subfields with regard to the return * type. Memoizing ensures the subfields are not repeatedly calculated, which * saves overhead when resolving lists of values. */ -const collectSubfields = (0, _memoize.memoize3)((exeContext, returnType, fieldGroup) => (0, _collectFields.collectSubfields)(exeContext.schema, exeContext.fragments, exeContext.variableValues, exeContext.operation, returnType, fieldGroup)); -const UNEXPECTED_EXPERIMENTAL_DIRECTIVES = 'The provided schema unexpectedly contains experimental directives (@defer or @stream). These directives may only be utilized if experimental execution features are explicitly enabled.'; -const UNEXPECTED_MULTIPLE_PAYLOADS = 'Executing this GraphQL operation would unexpectedly produce multiple payloads (due to @defer or @stream directive)'; + +const collectSubfields = (0, _memoize.memoize3)((exeContext, returnType, fieldNodes) => (0, _collectFields.collectSubfields)(exeContext.schema, exeContext.fragments, exeContext.variableValues, returnType, fieldNodes)); +/** + * Terminology + * + * "Definitions" are the generic name for top-level statements in the document. + * Examples of this include: + * 1) Operations (such as a query) + * 2) Fragments + * + * "Operations" are a generic name for requests in the document. + * Examples of this include: + * 1) query, + * 2) mutation + * + * "Selections" are the definitions that can appear legally and at + * single level of the query. These include: + * 1) field references e.g `a` + * 2) fragment "spreads" e.g. `...c` + * 3) inline fragment "spreads" e.g. `...on Type { a }` + */ + +/** + * Data that must be available at all points during query execution. + * + * Namely, schema of the type system that is currently executing, + * and the fragments defined in the query document + */ + /** * Implements the "Executing requests" section of the GraphQL specification. * @@ -24073,177 +23524,105 @@ const UNEXPECTED_MULTIPLE_PAYLOADS = 'Executing this GraphQL operation would une * * If the arguments to this function do not result in a legal execution context, * a GraphQLError will be thrown immediately explaining the invalid input. - * - * This function does not support incremental delivery (`@defer` and `@stream`). - * If an operation which would defer or stream data is executed with this - * function, it will throw or return a rejected promise. - * Use `experimentalExecuteIncrementally` if you want to support incremental - * delivery. */ function execute(args) { - if (args.schema.getDirective('defer') || args.schema.getDirective('stream')) { - throw new Error(UNEXPECTED_EXPERIMENTAL_DIRECTIVES); - } - const result = experimentalExecuteIncrementally(args); - if (!(0, _isPromise.isPromise)(result)) { - if ('initialResult' in result) { - // This can happen if the operation contains @defer or @stream directives - // and is not validated prior to execution - throw new Error(UNEXPECTED_MULTIPLE_PAYLOADS); - } - return result; - } - return result.then(incrementalResult => { - if ('initialResult' in incrementalResult) { - // This can happen if the operation contains @defer or @stream directives - // and is not validated prior to execution - throw new Error(UNEXPECTED_MULTIPLE_PAYLOADS); - } - return incrementalResult; - }); -} -/** - * Implements the "Executing requests" section of the GraphQL specification, - * including `@defer` and `@stream` as proposed in - * https://github.com/graphql/graphql-spec/pull/742 - * - * This function returns a Promise of an ExperimentalIncrementalExecutionResults - * object. This object either consists of a single ExecutionResult, or an - * object containing an `initialResult` and a stream of `subsequentResults`. - * - * If the arguments to this function do not result in a legal execution context, - * a GraphQLError will be thrown immediately explaining the invalid input. - */ -function experimentalExecuteIncrementally(args) { - // If a valid execution context cannot be created due to incorrect arguments, + // Temporary for v15 to v16 migration. Remove in v17 + arguments.length < 2 || (0, _devAssert.devAssert)(false, 'graphql@16 dropped long-deprecated support for positional arguments, please pass an object instead.'); + const { + schema, + document, + variableValues, + rootValue + } = args; // If arguments are missing or incorrect, throw an error. + + assertValidExecutionArguments(schema, document, variableValues); // If a valid execution context cannot be created due to incorrect arguments, // a "Response" with only errors is returned. - const exeContext = buildExecutionContext(args); - // Return early errors if execution context failed. + + const exeContext = buildExecutionContext(args); // Return early errors if execution context failed. + if (!('schema' in exeContext)) { return { errors: exeContext }; - } - return executeOperation(exeContext); -} -/** - * Implements the "Executing operations" section of the spec. - * - * Returns a Promise that will eventually resolve to the data described by - * The "Response" section of the GraphQL specification. - * - * If errors are encountered while executing a GraphQL field, only that - * field and its descendants will be omitted, and sibling fields will still - * be executed. An execution which encounters errors will still result in a - * resolved Promise. - * - * Errors from sub-fields of a NonNull type may propagate to the top level, - * at which point we still log the error and null the parent field, which - * in this case is the entire response. - */ -function executeOperation(exeContext) { + } // Return a Promise that will eventually resolve to the data described by + // The "Response" section of the GraphQL specification. + // + // If errors are encountered while executing a GraphQL field, only that + // field and its descendants will be omitted, and sibling fields will still + // be executed. An execution which encounters errors will still result in a + // resolved Promise. + // + // Errors from sub-fields of a NonNull type may propagate to the top level, + // at which point we still log the error and null the parent field, which + // in this case is the entire response. + try { const { - operation, - schema, - fragments, - variableValues, - rootValue + operation } = exeContext; - const rootType = schema.getRootType(operation.operation); - if (rootType == null) { - throw new _GraphQLError.GraphQLError(`Schema is not configured to execute ${operation.operation} operation.`, { - nodes: operation + const result = executeOperation(exeContext, operation, rootValue); + if ((0, _isPromise.isPromise)(result)) { + return result.then(data => buildResponse(data, exeContext.errors), error => { + exeContext.errors.push(error); + return buildResponse(null, exeContext.errors); }); } - const collectedFields = (0, _collectFields.collectFields)(schema, fragments, variableValues, rootType, operation); - let groupedFieldSet = collectedFields.groupedFieldSet; - const newDeferUsages = collectedFields.newDeferUsages; - let graphqlWrappedResult; - if (newDeferUsages.length === 0) { - graphqlWrappedResult = executeRootGroupedFieldSet(exeContext, operation.operation, rootType, rootValue, groupedFieldSet, undefined); - } else { - const executionPlan = (0, _buildExecutionPlan.buildExecutionPlan)(groupedFieldSet); - groupedFieldSet = executionPlan.groupedFieldSet; - const newGroupedFieldSets = executionPlan.newGroupedFieldSets; - const newDeferMap = addNewDeferredFragments(newDeferUsages, new Map()); - graphqlWrappedResult = executeRootGroupedFieldSet(exeContext, operation.operation, rootType, rootValue, groupedFieldSet, newDeferMap); - if (newGroupedFieldSets.size > 0) { - const newPendingExecutionGroups = collectExecutionGroups(exeContext, rootType, rootValue, undefined, undefined, newGroupedFieldSets, newDeferMap); - graphqlWrappedResult = withNewExecutionGroups(graphqlWrappedResult, newPendingExecutionGroups); - } - } - if ((0, _isPromise.isPromise)(graphqlWrappedResult)) { - return graphqlWrappedResult.then(resolved => buildDataResponse(exeContext, resolved[0], resolved[1]), error => ({ - data: null, - errors: withError(exeContext.errors, error) - })); - } - return buildDataResponse(exeContext, graphqlWrappedResult[0], graphqlWrappedResult[1]); + return buildResponse(result, exeContext.errors); } catch (error) { - return { - data: null, - errors: withError(exeContext.errors, error) - }; + exeContext.errors.push(error); + return buildResponse(null, exeContext.errors); } } -function withNewExecutionGroups(result, newPendingExecutionGroups) { - if ((0, _isPromise.isPromise)(result)) { - return result.then(resolved => { - addIncrementalDataRecords(resolved, newPendingExecutionGroups); - return resolved; - }); - } - addIncrementalDataRecords(result, newPendingExecutionGroups); - return result; -} -function addIncrementalDataRecords(graphqlWrappedResult, incrementalDataRecords) { - if (incrementalDataRecords === undefined) { - return; - } - if (graphqlWrappedResult[1] === undefined) { - graphqlWrappedResult[1] = [...incrementalDataRecords]; - } else { - graphqlWrappedResult[1].push(...incrementalDataRecords); - } -} -function withError(errors, error) { - return errors === undefined ? [error] : [...errors, error]; -} -function buildDataResponse(exeContext, data, incrementalDataRecords) { - const errors = exeContext.errors; - if (incrementalDataRecords === undefined) { - return errors !== undefined ? { - errors, - data - } : { - data - }; - } - return (0, _IncrementalPublisher.buildIncrementalResponse)(exeContext, data, errors, incrementalDataRecords); -} /** * Also implements the "Executing requests" section of the GraphQL specification. * However, it guarantees to complete synchronously (or throw an error) assuming * that all field resolvers are also synchronous. */ + function executeSync(args) { - const result = experimentalExecuteIncrementally(args); - // Assert that the execution was synchronous. - if ((0, _isPromise.isPromise)(result) || 'initialResult' in result) { + const result = execute(args); // Assert that the execution was synchronous. + + if ((0, _isPromise.isPromise)(result)) { throw new Error('GraphQL execution failed to complete synchronously.'); } return result; } +/** + * Given a completed execution context and data, build the `{ errors, data }` + * response defined by the "Response" section of the GraphQL specification. + */ + +function buildResponse(data, errors) { + return errors.length === 0 ? { + data + } : { + errors, + data + }; +} +/** + * Essential assertions before executing to provide developer feedback for + * improper use of the GraphQL library. + * + * @internal + */ + +function assertValidExecutionArguments(schema, document, rawVariableValues) { + document || (0, _devAssert.devAssert)(false, 'Must provide document.'); // If the schema used for execution is invalid, throw an error. + + (0, _validate.assertValidSchema)(schema); // Variables, if provided, must be an object. + + rawVariableValues == null || (0, _isObjectLike.isObjectLike)(rawVariableValues) || (0, _devAssert.devAssert)(false, 'Variables must be provided as an Object where each property is a variable value. Perhaps look to see if an unparsed JSON string was provided.'); +} /** * Constructs a ExecutionContext object from the arguments passed to * execute, which we will pass throughout the other execution methods. * * Throws a GraphQLError if a valid execution context cannot be created. * - * TODO: consider no longer exporting this function * @internal */ + function buildExecutionContext(args) { var _definition$name, _operation$variableDe; const { @@ -24255,11 +23634,8 @@ function buildExecutionContext(args) { operationName, fieldResolver, typeResolver, - subscribeFieldResolver, - enableEarlyExecution + subscribeFieldResolver } = args; - // If the schema used for execution is invalid, throw an error. - (0, _validate.assertValidSchema)(schema); let operation; const fragments = Object.create(null); for (const definition of document.definitions) { @@ -24277,8 +23653,7 @@ function buildExecutionContext(args) { case _kinds.Kind.FRAGMENT_DEFINITION: fragments[definition.name.value] = definition; break; - default: - // ignore non-executable definitions + default: // ignore non-executable definitions } } if (!operation) { @@ -24286,9 +23661,10 @@ function buildExecutionContext(args) { return [new _GraphQLError.GraphQLError(`Unknown operation named "${operationName}".`)]; } return [new _GraphQLError.GraphQLError('Must provide an operation.')]; - } - // FIXME: https://github.com/graphql/graphql-js/issues/2203 + } // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ + const variableDefinitions = (_operation$variableDe = operation.variableDefinitions) !== null && _operation$variableDe !== void 0 ? _operation$variableDe : []; const coercedVariableValues = (0, _values.getVariableValues)(schema, variableDefinitions, rawVariableValues !== null && rawVariableValues !== void 0 ? rawVariableValues : {}, { maxErrors: 50 @@ -24306,100 +23682,91 @@ function buildExecutionContext(args) { fieldResolver: fieldResolver !== null && fieldResolver !== void 0 ? fieldResolver : defaultFieldResolver, typeResolver: typeResolver !== null && typeResolver !== void 0 ? typeResolver : defaultTypeResolver, subscribeFieldResolver: subscribeFieldResolver !== null && subscribeFieldResolver !== void 0 ? subscribeFieldResolver : defaultFieldResolver, - enableEarlyExecution: enableEarlyExecution === true, - errors: undefined, - cancellableStreams: undefined + errors: [] }; } -function buildPerEventExecutionContext(exeContext, payload) { - return { - ...exeContext, - rootValue: payload, - errors: undefined - }; -} -function executeRootGroupedFieldSet(exeContext, operation, rootType, rootValue, groupedFieldSet, deferMap) { - switch (operation) { +/** + * Implements the "Executing operations" section of the spec. + */ + +function executeOperation(exeContext, operation, rootValue) { + const rootType = exeContext.schema.getRootType(operation.operation); + if (rootType == null) { + throw new _GraphQLError.GraphQLError(`Schema is not configured to execute ${operation.operation} operation.`, { + nodes: operation + }); + } + const rootFields = (0, _collectFields.collectFields)(exeContext.schema, exeContext.fragments, exeContext.variableValues, rootType, operation.selectionSet); + const path = undefined; + switch (operation.operation) { case _ast.OperationTypeNode.QUERY: - return executeFields(exeContext, rootType, rootValue, undefined, groupedFieldSet, undefined, deferMap); + return executeFields(exeContext, rootType, rootValue, path, rootFields); case _ast.OperationTypeNode.MUTATION: - return executeFieldsSerially(exeContext, rootType, rootValue, undefined, groupedFieldSet, undefined, deferMap); + return executeFieldsSerially(exeContext, rootType, rootValue, path, rootFields); case _ast.OperationTypeNode.SUBSCRIPTION: // TODO: deprecate `subscribe` and move all logic here // Temporary solution until we finish merging execute and subscribe together - return executeFields(exeContext, rootType, rootValue, undefined, groupedFieldSet, undefined, deferMap); + return executeFields(exeContext, rootType, rootValue, path, rootFields); } } /** * Implements the "Executing selection sets" section of the spec * for fields that must be executed serially. */ -function executeFieldsSerially(exeContext, parentType, sourceValue, path, groupedFieldSet, incrementalContext, deferMap) { - return (0, _promiseReduce.promiseReduce)(groupedFieldSet, (graphqlWrappedResult, [responseName, fieldGroup]) => { + +function executeFieldsSerially(exeContext, parentType, sourceValue, path, fields) { + return (0, _promiseReduce.promiseReduce)(fields.entries(), (results, [responseName, fieldNodes]) => { const fieldPath = (0, _Path.addPath)(path, responseName, parentType.name); - const result = executeField(exeContext, parentType, sourceValue, fieldGroup, fieldPath, incrementalContext, deferMap); + const result = executeField(exeContext, parentType, sourceValue, fieldNodes, fieldPath); if (result === undefined) { - return graphqlWrappedResult; + return results; } if ((0, _isPromise.isPromise)(result)) { - return result.then(resolved => { - graphqlWrappedResult[0][responseName] = resolved[0]; - addIncrementalDataRecords(graphqlWrappedResult, resolved[1]); - return graphqlWrappedResult; + return result.then(resolvedResult => { + results[responseName] = resolvedResult; + return results; }); } - graphqlWrappedResult[0][responseName] = result[0]; - addIncrementalDataRecords(graphqlWrappedResult, result[1]); - return graphqlWrappedResult; - }, [Object.create(null), undefined]); + results[responseName] = result; + return results; + }, Object.create(null)); } /** * Implements the "Executing selection sets" section of the spec * for fields that may be executed in parallel. */ -function executeFields(exeContext, parentType, sourceValue, path, groupedFieldSet, incrementalContext, deferMap) { + +function executeFields(exeContext, parentType, sourceValue, path, fields) { const results = Object.create(null); - const graphqlWrappedResult = [results, undefined]; let containsPromise = false; try { - for (const [responseName, fieldGroup] of groupedFieldSet) { + for (const [responseName, fieldNodes] of fields.entries()) { const fieldPath = (0, _Path.addPath)(path, responseName, parentType.name); - const result = executeField(exeContext, parentType, sourceValue, fieldGroup, fieldPath, incrementalContext, deferMap); + const result = executeField(exeContext, parentType, sourceValue, fieldNodes, fieldPath); if (result !== undefined) { + results[responseName] = result; if ((0, _isPromise.isPromise)(result)) { - results[responseName] = result.then(resolved => { - addIncrementalDataRecords(graphqlWrappedResult, resolved[1]); - return resolved[0]; - }); containsPromise = true; - } else { - results[responseName] = result[0]; - addIncrementalDataRecords(graphqlWrappedResult, result[1]); } } } } catch (error) { if (containsPromise) { // Ensure that any promises returned by other fields are handled, as they may also reject. - return (0, _promiseForObject.promiseForObject)(results, () => { - /* noop */ - }).finally(() => { + return (0, _promiseForObject.promiseForObject)(results).finally(() => { throw error; }); } throw error; - } - // If there are no promises, we can just return the object and any incrementalDataRecords + } // If there are no promises, we can just return the object + if (!containsPromise) { - return graphqlWrappedResult; - } - // Otherwise, results is a map from field name to the result of resolving that + return results; + } // Otherwise, results is a map from field name to the result of resolving that // field, which is possibly a promise. Return a promise that will return this // same map, but with any promises replaced with the values they resolved to. - return (0, _promiseForObject.promiseForObject)(results, resolved => [resolved, graphqlWrappedResult[1]]); -} -function toNodes(fieldGroup) { - return fieldGroup.map(fieldDetails => fieldDetails.node); + + return (0, _promiseForObject.promiseForObject)(results); } /** * Implements the "Executing fields" section of the spec @@ -24407,49 +23774,51 @@ function toNodes(fieldGroup) { * calling its resolve function, then calls completeValue to complete promises, * serialize scalars, or execute the sub-selection-set for objects. */ -function executeField(exeContext, parentType, source, fieldGroup, path, incrementalContext, deferMap) { + +function executeField(exeContext, parentType, source, fieldNodes, path) { var _fieldDef$resolve; - const fieldName = fieldGroup[0].node.name.value; - const fieldDef = exeContext.schema.getField(parentType, fieldName); + const fieldDef = getFieldDef(exeContext.schema, parentType, fieldNodes[0]); if (!fieldDef) { return; } const returnType = fieldDef.type; const resolveFn = (_fieldDef$resolve = fieldDef.resolve) !== null && _fieldDef$resolve !== void 0 ? _fieldDef$resolve : exeContext.fieldResolver; - const info = buildResolveInfo(exeContext, fieldDef, toNodes(fieldGroup), parentType, path); - // Get the resolve function, regardless of if its result is normal or abrupt (error). + const info = buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path); // Get the resolve function, regardless of if its result is normal or abrupt (error). + try { // Build a JS object of arguments from the field.arguments AST, using the // variables scope to fulfill any variable references. // TODO: find a way to memoize, in case this field is within a List type. - const args = (0, _values.getArgumentValues)(fieldDef, fieldGroup[0].node, exeContext.variableValues); - // The resolve function's optional third argument is a context value that + const args = (0, _values.getArgumentValues)(fieldDef, fieldNodes[0], exeContext.variableValues); // The resolve function's optional third argument is a context value that // is provided to every resolve function within an execution. It is commonly // used to represent an authenticated user, or request-specific caches. + const contextValue = exeContext.contextValue; const result = resolveFn(source, args, contextValue, info); + let completed; if ((0, _isPromise.isPromise)(result)) { - return completePromisedValue(exeContext, returnType, fieldGroup, info, path, result, incrementalContext, deferMap); + completed = result.then(resolved => completeValue(exeContext, returnType, fieldNodes, info, path, resolved)); + } else { + completed = completeValue(exeContext, returnType, fieldNodes, info, path, result); } - const completed = completeValue(exeContext, returnType, fieldGroup, info, path, result, incrementalContext, deferMap); if ((0, _isPromise.isPromise)(completed)) { // Note: we don't rely on a `catch` method, but we do expect "thenable" // to take a second callback for the error case. return completed.then(undefined, rawError => { - handleFieldError(rawError, exeContext, returnType, fieldGroup, path, incrementalContext); - return [null, undefined]; + const error = (0, _locatedError.locatedError)(rawError, fieldNodes, (0, _Path.pathToArray)(path)); + return handleFieldError(error, returnType, exeContext); }); } return completed; } catch (rawError) { - handleFieldError(rawError, exeContext, returnType, fieldGroup, path, incrementalContext); - return [null, undefined]; + const error = (0, _locatedError.locatedError)(rawError, fieldNodes, (0, _Path.pathToArray)(path)); + return handleFieldError(error, returnType, exeContext); } } /** - * TODO: consider no longer exporting this function * @internal */ + function buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path) { // The resolve function's optional fourth argument is a collection of // information about the current execution state. @@ -24466,22 +23835,16 @@ function buildResolveInfo(exeContext, fieldDef, fieldNodes, parentType, path) { variableValues: exeContext.variableValues }; } -function handleFieldError(rawError, exeContext, returnType, fieldGroup, path, incrementalContext) { - const error = (0, _locatedError.locatedError)(rawError, toNodes(fieldGroup), (0, _Path.pathToArray)(path)); +function handleFieldError(error, returnType, exeContext) { // If the field type is non-nullable, then it is resolved without any // protection from errors, however it still properly locates the error. if ((0, _definition.isNonNullType)(returnType)) { throw error; - } - // Otherwise, error protection is applied, logging the error and resolving + } // Otherwise, error protection is applied, logging the error and resolving // a null value for this field if one is encountered. - const context = incrementalContext !== null && incrementalContext !== void 0 ? incrementalContext : exeContext; - let errors = context.errors; - if (errors === undefined) { - errors = []; - context.errors = errors; - } - errors.push(error); + + exeContext.errors.push(error); + return null; } /** * Implements the instructions for completeValue as defined in the @@ -24504,271 +23867,94 @@ function handleFieldError(rawError, exeContext, returnType, fieldGroup, path, in * Otherwise, the field type expects a sub-selection set, and will complete the * value by executing all sub-selections. */ -function completeValue(exeContext, returnType, fieldGroup, info, path, result, incrementalContext, deferMap) { + +function completeValue(exeContext, returnType, fieldNodes, info, path, result) { // If result is an Error, throw a located error. if (result instanceof Error) { throw result; - } - // If field type is NonNull, complete for inner type, and throw field error + } // If field type is NonNull, complete for inner type, and throw field error // if result is null. + if ((0, _definition.isNonNullType)(returnType)) { - const completed = completeValue(exeContext, returnType.ofType, fieldGroup, info, path, result, incrementalContext, deferMap); - if (completed[0] === null) { + const completed = completeValue(exeContext, returnType.ofType, fieldNodes, info, path, result); + if (completed === null) { throw new Error(`Cannot return null for non-nullable field ${info.parentType.name}.${info.fieldName}.`); } return completed; - } - // If result value is null or undefined then return null. + } // If result value is null or undefined then return null. + if (result == null) { - return [null, undefined]; - } - // If field type is List, complete each item in the list with the inner type + return null; + } // If field type is List, complete each item in the list with the inner type + if ((0, _definition.isListType)(returnType)) { - return completeListValue(exeContext, returnType, fieldGroup, info, path, result, incrementalContext, deferMap); - } - // If field type is a leaf type, Scalar or Enum, serialize to a valid value, + return completeListValue(exeContext, returnType, fieldNodes, info, path, result); + } // If field type is a leaf type, Scalar or Enum, serialize to a valid value, // returning null if serialization is not possible. + if ((0, _definition.isLeafType)(returnType)) { - return [completeLeafValue(returnType, result), undefined]; - } - // If field type is an abstract type, Interface or Union, determine the + return completeLeafValue(returnType, result); + } // If field type is an abstract type, Interface or Union, determine the // runtime Object type and complete for that type. + if ((0, _definition.isAbstractType)(returnType)) { - return completeAbstractValue(exeContext, returnType, fieldGroup, info, path, result, incrementalContext, deferMap); - } - // If field type is Object, execute and complete all sub-selections. + return completeAbstractValue(exeContext, returnType, fieldNodes, info, path, result); + } // If field type is Object, execute and complete all sub-selections. + if ((0, _definition.isObjectType)(returnType)) { - return completeObjectValue(exeContext, returnType, fieldGroup, info, path, result, incrementalContext, deferMap); + return completeObjectValue(exeContext, returnType, fieldNodes, info, path, result); } /* c8 ignore next 6 */ // Not reachable, all possible output types have been considered. + false || (0, _invariant.invariant)(false, 'Cannot complete value of unexpected output type: ' + (0, _inspect.inspect)(returnType)); } -async function completePromisedValue(exeContext, returnType, fieldGroup, info, path, result, incrementalContext, deferMap) { - try { - const resolved = await result; - let completed = completeValue(exeContext, returnType, fieldGroup, info, path, resolved, incrementalContext, deferMap); - if ((0, _isPromise.isPromise)(completed)) { - completed = await completed; - } - return completed; - } catch (rawError) { - handleFieldError(rawError, exeContext, returnType, fieldGroup, path, incrementalContext); - return [null, undefined]; - } -} -/** - * Returns an object containing info for streaming if a field should be - * streamed based on the experimental flag, stream directive present and - * not disabled by the "if" argument. - */ -function getStreamUsage(exeContext, fieldGroup, path) { - // do not stream inner lists of multi-dimensional lists - if (typeof path.key === 'number') { - return; - } - // TODO: add test for this case (a streamed list nested under a list). - /* c8 ignore next 7 */ - if (fieldGroup._streamUsage !== undefined) { - return fieldGroup._streamUsage; - } - // validation only allows equivalent streams on multiple fields, so it is - // safe to only check the first fieldNode for the stream directive - const stream = (0, _values.getDirectiveValues)(_directives.GraphQLStreamDirective, fieldGroup[0].node, exeContext.variableValues); - if (!stream) { - return; - } - if (stream.if === false) { - return; - } - typeof stream.initialCount === 'number' || (0, _invariant.invariant)(false, 'initialCount must be a number'); - stream.initialCount >= 0 || (0, _invariant.invariant)(false, 'initialCount must be a positive integer'); - exeContext.operation.operation !== _ast.OperationTypeNode.SUBSCRIPTION || (0, _invariant.invariant)(false, '`@stream` directive not supported on subscription operations. Disable `@stream` by setting the `if` argument to `false`.'); - const streamedFieldGroup = fieldGroup.map(fieldDetails => ({ - node: fieldDetails.node, - deferUsage: undefined - })); - const streamUsage = { - initialCount: stream.initialCount, - label: typeof stream.label === 'string' ? stream.label : undefined, - fieldGroup: streamedFieldGroup - }; - fieldGroup._streamUsage = streamUsage; - return streamUsage; -} -/** - * Complete a async iterator value by completing the result and calling - * recursively until all the results are completed. - */ -async function completeAsyncIteratorValue(exeContext, itemType, fieldGroup, info, path, asyncIterator, incrementalContext, deferMap) { - let containsPromise = false; - const completedResults = []; - const graphqlWrappedResult = [completedResults, undefined]; - let index = 0; - const streamUsage = getStreamUsage(exeContext, fieldGroup, path); - const earlyReturn = asyncIterator.return === undefined ? undefined : asyncIterator.return.bind(asyncIterator); - try { - // eslint-disable-next-line no-constant-condition - while (true) { - if (streamUsage && index >= streamUsage.initialCount) { - const streamItemQueue = buildAsyncStreamItemQueue(index, path, asyncIterator, exeContext, streamUsage.fieldGroup, info, itemType); - let streamRecord; - if (earlyReturn === undefined) { - streamRecord = { - label: streamUsage.label, - path, - streamItemQueue - }; - } else { - streamRecord = { - label: streamUsage.label, - path, - earlyReturn, - streamItemQueue - }; - if (exeContext.cancellableStreams === undefined) { - exeContext.cancellableStreams = new Set(); - } - exeContext.cancellableStreams.add(streamRecord); - } - addIncrementalDataRecords(graphqlWrappedResult, [streamRecord]); - break; - } - const itemPath = (0, _Path.addPath)(path, index, undefined); - let iteration; - try { - // eslint-disable-next-line no-await-in-loop - iteration = await asyncIterator.next(); - } catch (rawError) { - throw (0, _locatedError.locatedError)(rawError, toNodes(fieldGroup), (0, _Path.pathToArray)(path)); - } - // TODO: add test case for stream returning done before initialCount - /* c8 ignore next 3 */ - if (iteration.done) { - break; - } - const item = iteration.value; - // TODO: add tests for stream backed by asyncIterator that returns a promise - /* c8 ignore start */ - if ((0, _isPromise.isPromise)(item)) { - completedResults.push(completePromisedListItemValue(item, graphqlWrappedResult, exeContext, itemType, fieldGroup, info, itemPath, incrementalContext, deferMap)); - containsPromise = true; - } else if ( /* c8 ignore stop */ - completeListItemValue(item, completedResults, graphqlWrappedResult, exeContext, itemType, fieldGroup, info, itemPath, incrementalContext, deferMap) - // TODO: add tests for stream backed by asyncIterator that completes to a promise - /* c8 ignore start */) { - containsPromise = true; - } - /* c8 ignore stop */ - index++; - } - } catch (error) { - if (earlyReturn !== undefined) { - earlyReturn().catch(() => { - /* c8 ignore next 1 */ - // ignore error - }); - } - throw error; - } - return containsPromise ? /* c8 ignore start */Promise.all(completedResults).then(resolved => [resolved, graphqlWrappedResult[1]]) : /* c8 ignore stop */graphqlWrappedResult; -} /** * Complete a list value by completing each item in the list with the * inner type */ -function completeListValue(exeContext, returnType, fieldGroup, info, path, result, incrementalContext, deferMap) { - const itemType = returnType.ofType; - if ((0, _isAsyncIterable.isAsyncIterable)(result)) { - const asyncIterator = result[Symbol.asyncIterator](); - return completeAsyncIteratorValue(exeContext, itemType, fieldGroup, info, path, asyncIterator, incrementalContext, deferMap); - } + +function completeListValue(exeContext, returnType, fieldNodes, info, path, result) { if (!(0, _isIterableObject.isIterableObject)(result)) { throw new _GraphQLError.GraphQLError(`Expected Iterable, but did not find one for field "${info.parentType.name}.${info.fieldName}".`); - } - return completeIterableValue(exeContext, itemType, fieldGroup, info, path, result, incrementalContext, deferMap); -} -function completeIterableValue(exeContext, itemType, fieldGroup, info, path, items, incrementalContext, deferMap) { - // This is specified as a simple map, however we're optimizing the path + } // This is specified as a simple map, however we're optimizing the path // where the list contains no Promises by avoiding creating another Promise. + + const itemType = returnType.ofType; let containsPromise = false; - const completedResults = []; - const graphqlWrappedResult = [completedResults, undefined]; - let index = 0; - const streamUsage = getStreamUsage(exeContext, fieldGroup, path); - const iterator = items[Symbol.iterator](); - let iteration = iterator.next(); - while (!iteration.done) { - const item = iteration.value; - if (streamUsage && index >= streamUsage.initialCount) { - const syncStreamRecord = { - label: streamUsage.label, - path, - streamItemQueue: buildSyncStreamItemQueue(item, index, path, iterator, exeContext, streamUsage.fieldGroup, info, itemType) - }; - addIncrementalDataRecords(graphqlWrappedResult, [syncStreamRecord]); - break; - } + const completedResults = Array.from(result, (item, index) => { // No need to modify the info object containing the path, // since from here on it is not ever accessed by resolver functions. const itemPath = (0, _Path.addPath)(path, index, undefined); - if ((0, _isPromise.isPromise)(item)) { - completedResults.push(completePromisedListItemValue(item, graphqlWrappedResult, exeContext, itemType, fieldGroup, info, itemPath, incrementalContext, deferMap)); - containsPromise = true; - } else if (completeListItemValue(item, completedResults, graphqlWrappedResult, exeContext, itemType, fieldGroup, info, itemPath, incrementalContext, deferMap)) { - containsPromise = true; + try { + let completedItem; + if ((0, _isPromise.isPromise)(item)) { + completedItem = item.then(resolved => completeValue(exeContext, itemType, fieldNodes, info, itemPath, resolved)); + } else { + completedItem = completeValue(exeContext, itemType, fieldNodes, info, itemPath, item); + } + if ((0, _isPromise.isPromise)(completedItem)) { + containsPromise = true; // Note: we don't rely on a `catch` method, but we do expect "thenable" + // to take a second callback for the error case. + + return completedItem.then(undefined, rawError => { + const error = (0, _locatedError.locatedError)(rawError, fieldNodes, (0, _Path.pathToArray)(itemPath)); + return handleFieldError(error, itemType, exeContext); + }); + } + return completedItem; + } catch (rawError) { + const error = (0, _locatedError.locatedError)(rawError, fieldNodes, (0, _Path.pathToArray)(itemPath)); + return handleFieldError(error, itemType, exeContext); } - index++; - iteration = iterator.next(); - } - return containsPromise ? Promise.all(completedResults).then(resolved => [resolved, graphqlWrappedResult[1]]) : graphqlWrappedResult; -} -/** - * Complete a list item value by adding it to the completed results. - * - * Returns true if the value is a Promise. - */ -function completeListItemValue(item, completedResults, parent, exeContext, itemType, fieldGroup, info, itemPath, incrementalContext, deferMap) { - try { - const completedItem = completeValue(exeContext, itemType, fieldGroup, info, itemPath, item, incrementalContext, deferMap); - if ((0, _isPromise.isPromise)(completedItem)) { - // Note: we don't rely on a `catch` method, but we do expect "thenable" - // to take a second callback for the error case. - completedResults.push(completedItem.then(resolved => { - addIncrementalDataRecords(parent, resolved[1]); - return resolved[0]; - }, rawError => { - handleFieldError(rawError, exeContext, itemType, fieldGroup, itemPath, incrementalContext); - return null; - })); - return true; - } - completedResults.push(completedItem[0]); - addIncrementalDataRecords(parent, completedItem[1]); - } catch (rawError) { - handleFieldError(rawError, exeContext, itemType, fieldGroup, itemPath, incrementalContext); - completedResults.push(null); - } - return false; -} -async function completePromisedListItemValue(item, parent, exeContext, itemType, fieldGroup, info, itemPath, incrementalContext, deferMap) { - try { - const resolved = await item; - let completed = completeValue(exeContext, itemType, fieldGroup, info, itemPath, resolved, incrementalContext, deferMap); - if ((0, _isPromise.isPromise)(completed)) { - completed = await completed; - } - addIncrementalDataRecords(parent, completed[1]); - return completed[0]; - } catch (rawError) { - handleFieldError(rawError, exeContext, itemType, fieldGroup, itemPath, incrementalContext); - return null; - } + }); + return containsPromise ? Promise.all(completedResults) : completedResults; } /** * Complete a Scalar or Enum by serializing to a valid value, returning * null if serialization is not possible. */ + function completeLeafValue(returnType, result) { const serializedResult = returnType.serialize(result); if (serializedResult == null) { @@ -24780,24 +23966,23 @@ function completeLeafValue(returnType, result) { * Complete a value of an abstract type by determining the runtime object type * of that value, then complete the value for that type. */ -function completeAbstractValue(exeContext, returnType, fieldGroup, info, path, result, incrementalContext, deferMap) { + +function completeAbstractValue(exeContext, returnType, fieldNodes, info, path, result) { var _returnType$resolveTy; const resolveTypeFn = (_returnType$resolveTy = returnType.resolveType) !== null && _returnType$resolveTy !== void 0 ? _returnType$resolveTy : exeContext.typeResolver; const contextValue = exeContext.contextValue; const runtimeType = resolveTypeFn(result, contextValue, info, returnType); if ((0, _isPromise.isPromise)(runtimeType)) { - return runtimeType.then(resolvedRuntimeType => completeObjectValue(exeContext, ensureValidRuntimeType(resolvedRuntimeType, exeContext, returnType, fieldGroup, info, result), fieldGroup, info, path, result, incrementalContext, deferMap)); + return runtimeType.then(resolvedRuntimeType => completeObjectValue(exeContext, ensureValidRuntimeType(resolvedRuntimeType, exeContext, returnType, fieldNodes, info, result), fieldNodes, info, path, result)); } - return completeObjectValue(exeContext, ensureValidRuntimeType(runtimeType, exeContext, returnType, fieldGroup, info, result), fieldGroup, info, path, result, incrementalContext, deferMap); + return completeObjectValue(exeContext, ensureValidRuntimeType(runtimeType, exeContext, returnType, fieldNodes, info, result), fieldNodes, info, path, result); } -function ensureValidRuntimeType(runtimeTypeName, exeContext, returnType, fieldGroup, info, result) { +function ensureValidRuntimeType(runtimeTypeName, exeContext, returnType, fieldNodes, info, result) { if (runtimeTypeName == null) { - throw new _GraphQLError.GraphQLError(`Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}". Either the "${returnType.name}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`, { - nodes: toNodes(fieldGroup) - }); - } - // releases before 16.0.0 supported returning `GraphQLObjectType` from `resolveType` + throw new _GraphQLError.GraphQLError(`Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}". Either the "${returnType.name}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`, fieldNodes); + } // releases before 16.0.0 supported returning `GraphQLObjectType` from `resolveType` // TODO: remove in 17.0.0 release + if ((0, _definition.isObjectType)(runtimeTypeName)) { throw new _GraphQLError.GraphQLError('Support for returning GraphQLObjectType from resolveType was removed in graphql-js@16.0.0 please return type name instead.'); } @@ -24807,17 +23992,17 @@ function ensureValidRuntimeType(runtimeTypeName, exeContext, returnType, fieldGr const runtimeType = exeContext.schema.getType(runtimeTypeName); if (runtimeType == null) { throw new _GraphQLError.GraphQLError(`Abstract type "${returnType.name}" was resolved to a type "${runtimeTypeName}" that does not exist inside the schema.`, { - nodes: toNodes(fieldGroup) + nodes: fieldNodes }); } if (!(0, _definition.isObjectType)(runtimeType)) { throw new _GraphQLError.GraphQLError(`Abstract type "${returnType.name}" was resolved to a non-object type "${runtimeTypeName}".`, { - nodes: toNodes(fieldGroup) + nodes: fieldNodes }); } if (!exeContext.schema.isSubType(returnType, runtimeType)) { throw new _GraphQLError.GraphQLError(`Runtime Object type "${runtimeType.name}" is not a possible type for "${returnType.name}".`, { - nodes: toNodes(fieldGroup) + nodes: fieldNodes }); } return runtimeType; @@ -24825,92 +24010,34 @@ function ensureValidRuntimeType(runtimeTypeName, exeContext, returnType, fieldGr /** * Complete an Object value by executing all sub-selections. */ -function completeObjectValue(exeContext, returnType, fieldGroup, info, path, result, incrementalContext, deferMap) { - // If there is an isTypeOf predicate function, call it with the + +function completeObjectValue(exeContext, returnType, fieldNodes, info, path, result) { + // Collect sub-fields to execute to complete this value. + const subFieldNodes = collectSubfields(exeContext, returnType, fieldNodes); // If there is an isTypeOf predicate function, call it with the // current result. If isTypeOf returns false, then raise an error rather // than continuing execution. + if (returnType.isTypeOf) { const isTypeOf = returnType.isTypeOf(result, exeContext.contextValue, info); if ((0, _isPromise.isPromise)(isTypeOf)) { return isTypeOf.then(resolvedIsTypeOf => { if (!resolvedIsTypeOf) { - throw invalidReturnTypeError(returnType, result, fieldGroup); + throw invalidReturnTypeError(returnType, result, fieldNodes); } - return collectAndExecuteSubfields(exeContext, returnType, fieldGroup, path, result, incrementalContext, deferMap); + return executeFields(exeContext, returnType, result, path, subFieldNodes); }); } if (!isTypeOf) { - throw invalidReturnTypeError(returnType, result, fieldGroup); + throw invalidReturnTypeError(returnType, result, fieldNodes); } } - return collectAndExecuteSubfields(exeContext, returnType, fieldGroup, path, result, incrementalContext, deferMap); + return executeFields(exeContext, returnType, result, path, subFieldNodes); } -function invalidReturnTypeError(returnType, result, fieldGroup) { +function invalidReturnTypeError(returnType, result, fieldNodes) { return new _GraphQLError.GraphQLError(`Expected value of type "${returnType.name}" but got: ${(0, _inspect.inspect)(result)}.`, { - nodes: toNodes(fieldGroup) + nodes: fieldNodes }); } -/** - * Instantiates new DeferredFragmentRecords for the given path within an - * incremental data record, returning an updated map of DeferUsage - * objects to DeferredFragmentRecords. - * - * Note: As defer directives may be used with operations returning lists, - * a DeferUsage object may correspond to many DeferredFragmentRecords. - * - * DeferredFragmentRecord creation includes the following steps: - * 1. The new DeferredFragmentRecord is instantiated at the given path. - * 2. The parent result record is calculated from the given incremental data - * record. - * 3. The IncrementalPublisher is notified that a new DeferredFragmentRecord - * with the calculated parent has been added; the record will be released only - * after the parent has completed. - * - */ -function addNewDeferredFragments(newDeferUsages, newDeferMap, path) { - // For each new deferUsage object: - for (const newDeferUsage of newDeferUsages) { - const parentDeferUsage = newDeferUsage.parentDeferUsage; - const parent = parentDeferUsage === undefined ? undefined : deferredFragmentRecordFromDeferUsage(parentDeferUsage, newDeferMap); - // Instantiate the new record. - const deferredFragmentRecord = new _types.DeferredFragmentRecord(path, newDeferUsage.label, parent); - // Update the map. - newDeferMap.set(newDeferUsage, deferredFragmentRecord); - } - return newDeferMap; -} -function deferredFragmentRecordFromDeferUsage(deferUsage, deferMap) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return deferMap.get(deferUsage); -} -function collectAndExecuteSubfields(exeContext, returnType, fieldGroup, path, result, incrementalContext, deferMap) { - // Collect sub-fields to execute to complete this value. - const collectedSubfields = collectSubfields(exeContext, returnType, fieldGroup); - let groupedFieldSet = collectedSubfields.groupedFieldSet; - const newDeferUsages = collectedSubfields.newDeferUsages; - if (deferMap === undefined && newDeferUsages.length === 0) { - return executeFields(exeContext, returnType, result, path, groupedFieldSet, incrementalContext, undefined); - } - const subExecutionPlan = buildSubExecutionPlan(groupedFieldSet, incrementalContext === null || incrementalContext === void 0 ? void 0 : incrementalContext.deferUsageSet); - groupedFieldSet = subExecutionPlan.groupedFieldSet; - const newGroupedFieldSets = subExecutionPlan.newGroupedFieldSets; - const newDeferMap = addNewDeferredFragments(newDeferUsages, new Map(deferMap), path); - const subFields = executeFields(exeContext, returnType, result, path, groupedFieldSet, incrementalContext, newDeferMap); - if (newGroupedFieldSets.size > 0) { - const newPendingExecutionGroups = collectExecutionGroups(exeContext, returnType, result, path, incrementalContext === null || incrementalContext === void 0 ? void 0 : incrementalContext.deferUsageSet, newGroupedFieldSets, newDeferMap); - return withNewExecutionGroups(subFields, newPendingExecutionGroups); - } - return subFields; -} -function buildSubExecutionPlan(originalGroupedFieldSet, deferUsageSet) { - let executionPlan = originalGroupedFieldSet._executionPlan; - if (executionPlan !== undefined) { - return executionPlan; - } - executionPlan = (0, _buildExecutionPlan.buildExecutionPlan)(originalGroupedFieldSet, deferUsageSet); - originalGroupedFieldSet._executionPlan = executionPlan; - return executionPlan; -} /** * If a resolveType function is not given, then a default resolve behavior is * used which attempts two strategies: @@ -24921,12 +24048,13 @@ function buildSubExecutionPlan(originalGroupedFieldSet, deferUsageSet) { * Otherwise, test each possible type for the abstract type by calling * isTypeOf for the object being coerced, returning the first type that matches. */ + const defaultTypeResolver = function (value, contextValue, info, abstractType) { // First, look for `__typename`. if ((0, _isObjectLike.isObjectLike)(value) && typeof value.__typename === 'string') { return value.__typename; - } - // Otherwise, test each possible type. + } // Otherwise, test each possible type. + const possibleTypes = info.schema.getPossibleTypes(abstractType); const promisedIsTypeOfResults = []; for (let i = 0; i < possibleTypes.length; i++) { @@ -24968,340 +24096,27 @@ const defaultFieldResolver = function (source, args, contextValue, info) { } }; /** - * Implements the "Subscribe" algorithm described in the GraphQL specification. + * This method looks up the field on the given type definition. + * It has special casing for the three introspection fields, + * __schema, __type and __typename. __typename is special because + * it can always be queried as a field, even in situations where no + * other fields are allowed, like on a Union. __schema and __type + * could get automatically added to the query type, but that would + * require mutating type definitions, which would cause issues. * - * Returns a Promise which resolves to either an AsyncIterator (if successful) - * or an ExecutionResult (error). The promise will be rejected if the schema or - * other arguments to this function are invalid, or if the resolved event stream - * is not an async iterable. - * - * If the client-provided arguments to this function do not result in a - * compliant subscription, a GraphQL Response (ExecutionResult) with descriptive - * errors and no data will be returned. - * - * If the source stream could not be created due to faulty subscription resolver - * logic or underlying systems, the promise will resolve to a single - * ExecutionResult containing `errors` and no `data`. - * - * If the operation succeeded, the promise resolves to an AsyncIterator, which - * yields a stream of ExecutionResults representing the response stream. - * - * This function does not support incremental delivery (`@defer` and `@stream`). - * If an operation which would defer or stream data is executed with this - * function, a field error will be raised at the location of the `@defer` or - * `@stream` directive. - * - * Accepts an object with named arguments. + * @internal */ exports.defaultFieldResolver = defaultFieldResolver; -function subscribe(args) { - // If a valid execution context cannot be created due to incorrect arguments, - // a "Response" with only errors is returned. - const exeContext = buildExecutionContext(args); - // Return early errors if execution context failed. - if (!('schema' in exeContext)) { - return { - errors: exeContext - }; +function getFieldDef(schema, parentType, fieldNode) { + const fieldName = fieldNode.name.value; + if (fieldName === _introspection.SchemaMetaFieldDef.name && schema.getQueryType() === parentType) { + return _introspection.SchemaMetaFieldDef; + } else if (fieldName === _introspection.TypeMetaFieldDef.name && schema.getQueryType() === parentType) { + return _introspection.TypeMetaFieldDef; + } else if (fieldName === _introspection.TypeNameMetaFieldDef.name) { + return _introspection.TypeNameMetaFieldDef; } - const resultOrStream = createSourceEventStreamImpl(exeContext); - if ((0, _isPromise.isPromise)(resultOrStream)) { - return resultOrStream.then(resolvedResultOrStream => mapSourceToResponse(exeContext, resolvedResultOrStream)); - } - return mapSourceToResponse(exeContext, resultOrStream); -} -function mapSourceToResponse(exeContext, resultOrStream) { - if (!(0, _isAsyncIterable.isAsyncIterable)(resultOrStream)) { - return resultOrStream; - } - // For each payload yielded from a subscription, map it over the normal - // GraphQL `execute` function, with `payload` as the rootValue. - // This implements the "MapSourceToResponseEvent" algorithm described in - // the GraphQL specification. The `execute` function provides the - // "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the - // "ExecuteQuery" algorithm, for which `execute` is also used. - return (0, _mapAsyncIterable.mapAsyncIterable)(resultOrStream, payload => executeOperation(buildPerEventExecutionContext(exeContext, payload))); -} -/** - * Implements the "CreateSourceEventStream" algorithm described in the - * GraphQL specification, resolving the subscription source event stream. - * - * Returns a Promise which resolves to either an AsyncIterable (if successful) - * or an ExecutionResult (error). The promise will be rejected if the schema or - * other arguments to this function are invalid, or if the resolved event stream - * is not an async iterable. - * - * If the client-provided arguments to this function do not result in a - * compliant subscription, a GraphQL Response (ExecutionResult) with - * descriptive errors and no data will be returned. - * - * If the the source stream could not be created due to faulty subscription - * resolver logic or underlying systems, the promise will resolve to a single - * ExecutionResult containing `errors` and no `data`. - * - * If the operation succeeded, the promise resolves to the AsyncIterable for the - * event stream returned by the resolver. - * - * A Source Event Stream represents a sequence of events, each of which triggers - * a GraphQL execution for that event. - * - * This may be useful when hosting the stateful subscription service in a - * different process or machine than the stateless GraphQL execution engine, - * or otherwise separating these two steps. For more on this, see the - * "Supporting Subscriptions at Scale" information in the GraphQL specification. - */ -function createSourceEventStream(args) { - // If a valid execution context cannot be created due to incorrect arguments, - // a "Response" with only errors is returned. - const exeContext = buildExecutionContext(args); - // Return early errors if execution context failed. - if (!('schema' in exeContext)) { - return { - errors: exeContext - }; - } - return createSourceEventStreamImpl(exeContext); -} -function createSourceEventStreamImpl(exeContext) { - try { - const eventStream = executeSubscription(exeContext); - if ((0, _isPromise.isPromise)(eventStream)) { - return eventStream.then(undefined, error => ({ - errors: [error] - })); - } - return eventStream; - } catch (error) { - return { - errors: [error] - }; - } -} -function executeSubscription(exeContext) { - const { - schema, - fragments, - operation, - variableValues, - rootValue - } = exeContext; - const rootType = schema.getSubscriptionType(); - if (rootType == null) { - throw new _GraphQLError.GraphQLError('Schema is not configured to execute subscription operation.', { - nodes: operation - }); - } - const { - groupedFieldSet - } = (0, _collectFields.collectFields)(schema, fragments, variableValues, rootType, operation); - const firstRootField = groupedFieldSet.entries().next().value; - const [responseName, fieldGroup] = firstRootField; - const fieldName = fieldGroup[0].node.name.value; - const fieldDef = schema.getField(rootType, fieldName); - const fieldNodes = fieldGroup.map(fieldDetails => fieldDetails.node); - if (!fieldDef) { - throw new _GraphQLError.GraphQLError(`The subscription field "${fieldName}" is not defined.`, { - nodes: fieldNodes - }); - } - const path = (0, _Path.addPath)(undefined, responseName, rootType.name); - const info = buildResolveInfo(exeContext, fieldDef, fieldNodes, rootType, path); - try { - var _fieldDef$subscribe; - // Implements the "ResolveFieldEventStream" algorithm from GraphQL specification. - // It differs from "ResolveFieldValue" due to providing a different `resolveFn`. - // Build a JS object of arguments from the field.arguments AST, using the - // variables scope to fulfill any variable references. - const args = (0, _values.getArgumentValues)(fieldDef, fieldNodes[0], variableValues); - // The resolve function's optional third argument is a context value that - // is provided to every resolve function within an execution. It is commonly - // used to represent an authenticated user, or request-specific caches. - const contextValue = exeContext.contextValue; - // Call the `subscribe()` resolver or the default resolver to produce an - // AsyncIterable yielding raw payloads. - const resolveFn = (_fieldDef$subscribe = fieldDef.subscribe) !== null && _fieldDef$subscribe !== void 0 ? _fieldDef$subscribe : exeContext.subscribeFieldResolver; - const result = resolveFn(rootValue, args, contextValue, info); - if ((0, _isPromise.isPromise)(result)) { - return result.then(assertEventStream).then(undefined, error => { - throw (0, _locatedError.locatedError)(error, fieldNodes, (0, _Path.pathToArray)(path)); - }); - } - return assertEventStream(result); - } catch (error) { - throw (0, _locatedError.locatedError)(error, fieldNodes, (0, _Path.pathToArray)(path)); - } -} -function assertEventStream(result) { - if (result instanceof Error) { - throw result; - } - // Assert field returned an event stream, otherwise yield an error. - if (!(0, _isAsyncIterable.isAsyncIterable)(result)) { - throw new _GraphQLError.GraphQLError('Subscription field must return Async Iterable. ' + `Received: ${(0, _inspect.inspect)(result)}.`); - } - return result; -} -function collectExecutionGroups(exeContext, parentType, sourceValue, path, parentDeferUsages, newGroupedFieldSets, deferMap) { - const newPendingExecutionGroups = []; - for (const [deferUsageSet, groupedFieldSet] of newGroupedFieldSets) { - const deferredFragmentRecords = getDeferredFragmentRecords(deferUsageSet, deferMap); - const pendingExecutionGroup = { - deferredFragmentRecords, - result: undefined - }; - const executor = () => executeExecutionGroup(pendingExecutionGroup, exeContext, parentType, sourceValue, path, groupedFieldSet, { - errors: undefined, - deferUsageSet - }, deferMap); - if (exeContext.enableEarlyExecution) { - pendingExecutionGroup.result = new _BoxedPromiseOrValue.BoxedPromiseOrValue(shouldDefer(parentDeferUsages, deferUsageSet) ? Promise.resolve().then(executor) : executor()); - } else { - pendingExecutionGroup.result = () => new _BoxedPromiseOrValue.BoxedPromiseOrValue(executor()); - } - newPendingExecutionGroups.push(pendingExecutionGroup); - } - return newPendingExecutionGroups; -} -function shouldDefer(parentDeferUsages, deferUsages) { - // If we have a new child defer usage, defer. - // Otherwise, this defer usage was already deferred when it was initially - // encountered, and is now in the midst of executing early, so the new - // deferred grouped fields set can be executed immediately. - return parentDeferUsages === undefined || !Array.from(deferUsages).every(deferUsage => parentDeferUsages.has(deferUsage)); -} -function executeExecutionGroup(pendingExecutionGroup, exeContext, parentType, sourceValue, path, groupedFieldSet, incrementalContext, deferMap) { - let result; - try { - result = executeFields(exeContext, parentType, sourceValue, path, groupedFieldSet, incrementalContext, deferMap); - } catch (error) { - return { - pendingExecutionGroup, - path: (0, _Path.pathToArray)(path), - errors: withError(incrementalContext.errors, error) - }; - } - if ((0, _isPromise.isPromise)(result)) { - return result.then(resolved => buildCompletedExecutionGroup(incrementalContext.errors, pendingExecutionGroup, path, resolved), error => ({ - pendingExecutionGroup, - path: (0, _Path.pathToArray)(path), - errors: withError(incrementalContext.errors, error) - })); - } - return buildCompletedExecutionGroup(incrementalContext.errors, pendingExecutionGroup, path, result); -} -function buildCompletedExecutionGroup(errors, pendingExecutionGroup, path, result) { - return { - pendingExecutionGroup, - path: (0, _Path.pathToArray)(path), - result: errors === undefined ? { - data: result[0] - } : { - data: result[0], - errors - }, - incrementalDataRecords: result[1] - }; -} -function getDeferredFragmentRecords(deferUsages, deferMap) { - return Array.from(deferUsages).map(deferUsage => deferredFragmentRecordFromDeferUsage(deferUsage, deferMap)); -} -function buildSyncStreamItemQueue(initialItem, initialIndex, streamPath, iterator, exeContext, fieldGroup, info, itemType) { - const streamItemQueue = []; - const enableEarlyExecution = exeContext.enableEarlyExecution; - const firstExecutor = () => { - const initialPath = (0, _Path.addPath)(streamPath, initialIndex, undefined); - const firstStreamItem = new _BoxedPromiseOrValue.BoxedPromiseOrValue(completeStreamItem(initialPath, initialItem, exeContext, { - errors: undefined - }, fieldGroup, info, itemType)); - let iteration = iterator.next(); - let currentIndex = initialIndex + 1; - let currentStreamItem = firstStreamItem; - while (!iteration.done) { - // TODO: add test case for early sync termination - /* c8 ignore next 6 */ - if (currentStreamItem instanceof _BoxedPromiseOrValue.BoxedPromiseOrValue) { - const result = currentStreamItem.value; - if (!(0, _isPromise.isPromise)(result) && result.errors !== undefined) { - break; - } - } - const itemPath = (0, _Path.addPath)(streamPath, currentIndex, undefined); - const value = iteration.value; - const currentExecutor = () => completeStreamItem(itemPath, value, exeContext, { - errors: undefined - }, fieldGroup, info, itemType); - currentStreamItem = enableEarlyExecution ? new _BoxedPromiseOrValue.BoxedPromiseOrValue(currentExecutor()) : () => new _BoxedPromiseOrValue.BoxedPromiseOrValue(currentExecutor()); - streamItemQueue.push(currentStreamItem); - iteration = iterator.next(); - currentIndex = initialIndex + 1; - } - streamItemQueue.push(new _BoxedPromiseOrValue.BoxedPromiseOrValue({})); - return firstStreamItem.value; - }; - streamItemQueue.push(enableEarlyExecution ? new _BoxedPromiseOrValue.BoxedPromiseOrValue(Promise.resolve().then(firstExecutor)) : () => new _BoxedPromiseOrValue.BoxedPromiseOrValue(firstExecutor())); - return streamItemQueue; -} -function buildAsyncStreamItemQueue(initialIndex, streamPath, asyncIterator, exeContext, fieldGroup, info, itemType) { - const streamItemQueue = []; - const executor = () => getNextAsyncStreamItemResult(streamItemQueue, streamPath, initialIndex, asyncIterator, exeContext, fieldGroup, info, itemType); - streamItemQueue.push(exeContext.enableEarlyExecution ? new _BoxedPromiseOrValue.BoxedPromiseOrValue(executor()) : () => new _BoxedPromiseOrValue.BoxedPromiseOrValue(executor())); - return streamItemQueue; -} -async function getNextAsyncStreamItemResult(streamItemQueue, streamPath, index, asyncIterator, exeContext, fieldGroup, info, itemType) { - let iteration; - try { - iteration = await asyncIterator.next(); - } catch (error) { - return { - errors: [(0, _locatedError.locatedError)(error, toNodes(fieldGroup), (0, _Path.pathToArray)(streamPath))] - }; - } - if (iteration.done) { - return {}; - } - const itemPath = (0, _Path.addPath)(streamPath, index, undefined); - const result = completeStreamItem(itemPath, iteration.value, exeContext, { - errors: undefined - }, fieldGroup, info, itemType); - const executor = () => getNextAsyncStreamItemResult(streamItemQueue, streamPath, index + 1, asyncIterator, exeContext, fieldGroup, info, itemType); - streamItemQueue.push(exeContext.enableEarlyExecution ? new _BoxedPromiseOrValue.BoxedPromiseOrValue(executor()) : () => new _BoxedPromiseOrValue.BoxedPromiseOrValue(executor())); - return result; -} -function completeStreamItem(itemPath, item, exeContext, incrementalContext, fieldGroup, info, itemType) { - if ((0, _isPromise.isPromise)(item)) { - return completePromisedValue(exeContext, itemType, fieldGroup, info, itemPath, item, incrementalContext, new Map()).then(resolvedItem => buildStreamItemResult(incrementalContext.errors, resolvedItem), error => ({ - errors: withError(incrementalContext.errors, error) - })); - } - let result; - try { - try { - result = completeValue(exeContext, itemType, fieldGroup, info, itemPath, item, incrementalContext, new Map()); - } catch (rawError) { - handleFieldError(rawError, exeContext, itemType, fieldGroup, itemPath, incrementalContext); - result = [null, undefined]; - } - } catch (error) { - return { - errors: withError(incrementalContext.errors, error) - }; - } - if ((0, _isPromise.isPromise)(result)) { - return result.then(undefined, rawError => { - handleFieldError(rawError, exeContext, itemType, fieldGroup, itemPath, incrementalContext); - return [null, undefined]; - }).then(resolvedItem => buildStreamItemResult(incrementalContext.errors, resolvedItem), error => ({ - errors: withError(incrementalContext.errors, error) - })); - } - return buildStreamItemResult(incrementalContext.errors, result); -} -function buildStreamItemResult(errors, result) { - return { - item: result[0], - errors, - incrementalDataRecords: result[1] - }; + return parentType.getFields()[fieldName]; } /***/ }), @@ -25320,7 +24135,7 @@ Object.defineProperty(exports, "__esModule", ({ Object.defineProperty(exports, "createSourceEventStream", ({ enumerable: true, get: function () { - return _execute.createSourceEventStream; + return _subscribe.createSourceEventStream; } })); Object.defineProperty(exports, "defaultFieldResolver", ({ @@ -25347,12 +24162,6 @@ Object.defineProperty(exports, "executeSync", ({ return _execute.executeSync; } })); -Object.defineProperty(exports, "experimentalExecuteIncrementally", ({ - enumerable: true, - get: function () { - return _execute.experimentalExecuteIncrementally; - } -})); Object.defineProperty(exports, "getArgumentValues", ({ enumerable: true, get: function () { @@ -25380,18 +24189,19 @@ Object.defineProperty(exports, "responsePathAsArray", ({ Object.defineProperty(exports, "subscribe", ({ enumerable: true, get: function () { - return _execute.subscribe; + return _subscribe.subscribe; } })); var _Path = __webpack_require__(/*! ../jsutils/Path.mjs */ "../../../node_modules/graphql/jsutils/Path.mjs"); var _execute = __webpack_require__(/*! ./execute.mjs */ "../../../node_modules/graphql/execution/execute.mjs"); +var _subscribe = __webpack_require__(/*! ./subscribe.mjs */ "../../../node_modules/graphql/execution/subscribe.mjs"); var _values = __webpack_require__(/*! ./values.mjs */ "../../../node_modules/graphql/execution/values.mjs"); /***/ }), -/***/ "../../../node_modules/graphql/execution/mapAsyncIterable.mjs": +/***/ "../../../node_modules/graphql/execution/mapAsyncIterator.mjs": /*!********************************************************************!*\ - !*** ../../../node_modules/graphql/execution/mapAsyncIterable.mjs ***! + !*** ../../../node_modules/graphql/execution/mapAsyncIterator.mjs ***! \********************************************************************/ /***/ (function(__unused_webpack_module, exports) { @@ -25400,12 +24210,12 @@ var _values = __webpack_require__(/*! ./values.mjs */ "../../../node_modules/gra Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.mapAsyncIterable = mapAsyncIterable; +exports.mapAsyncIterator = mapAsyncIterator; /** * Given an AsyncIterable and a callback function, return an AsyncIterator * which produces values mapped via calling the callback function. */ -function mapAsyncIterable(iterable, callback) { +function mapAsyncIterator(iterable, callback) { const iterator = iterable[Symbol.asyncIterator](); async function mapResult(result) { if (result.done) { @@ -25455,49 +24265,201 @@ function mapAsyncIterable(iterable, callback) { /***/ }), -/***/ "../../../node_modules/graphql/execution/types.mjs": -/*!*********************************************************!*\ - !*** ../../../node_modules/graphql/execution/types.mjs ***! - \*********************************************************/ -/***/ (function(__unused_webpack_module, exports) { +/***/ "../../../node_modules/graphql/execution/subscribe.mjs": +/*!*************************************************************!*\ + !*** ../../../node_modules/graphql/execution/subscribe.mjs ***! + \*************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.DeferredFragmentRecord = void 0; -exports.isCancellableStreamRecord = isCancellableStreamRecord; -exports.isCompletedExecutionGroup = isCompletedExecutionGroup; -exports.isDeferredFragmentRecord = isDeferredFragmentRecord; -exports.isFailedExecutionGroup = isFailedExecutionGroup; -exports.isPendingExecutionGroup = isPendingExecutionGroup; -function isPendingExecutionGroup(incrementalDataRecord) { - return 'deferredFragmentRecords' in incrementalDataRecord; +exports.createSourceEventStream = createSourceEventStream; +exports.subscribe = subscribe; +var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); +var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); +var _isAsyncIterable = __webpack_require__(/*! ../jsutils/isAsyncIterable.mjs */ "../../../node_modules/graphql/jsutils/isAsyncIterable.mjs"); +var _Path = __webpack_require__(/*! ../jsutils/Path.mjs */ "../../../node_modules/graphql/jsutils/Path.mjs"); +var _GraphQLError = __webpack_require__(/*! ../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); +var _locatedError = __webpack_require__(/*! ../error/locatedError.mjs */ "../../../node_modules/graphql/error/locatedError.mjs"); +var _collectFields = __webpack_require__(/*! ./collectFields.mjs */ "../../../node_modules/graphql/execution/collectFields.mjs"); +var _execute = __webpack_require__(/*! ./execute.mjs */ "../../../node_modules/graphql/execution/execute.mjs"); +var _mapAsyncIterator = __webpack_require__(/*! ./mapAsyncIterator.mjs */ "../../../node_modules/graphql/execution/mapAsyncIterator.mjs"); +var _values = __webpack_require__(/*! ./values.mjs */ "../../../node_modules/graphql/execution/values.mjs"); +/** + * Implements the "Subscribe" algorithm described in the GraphQL specification. + * + * Returns a Promise which resolves to either an AsyncIterator (if successful) + * or an ExecutionResult (error). The promise will be rejected if the schema or + * other arguments to this function are invalid, or if the resolved event stream + * is not an async iterable. + * + * If the client-provided arguments to this function do not result in a + * compliant subscription, a GraphQL Response (ExecutionResult) with + * descriptive errors and no data will be returned. + * + * If the source stream could not be created due to faulty subscription + * resolver logic or underlying systems, the promise will resolve to a single + * ExecutionResult containing `errors` and no `data`. + * + * If the operation succeeded, the promise resolves to an AsyncIterator, which + * yields a stream of ExecutionResults representing the response stream. + * + * Accepts either an object with named arguments, or individual arguments. + */ + +async function subscribe(args) { + // Temporary for v15 to v16 migration. Remove in v17 + arguments.length < 2 || (0, _devAssert.devAssert)(false, 'graphql@16 dropped long-deprecated support for positional arguments, please pass an object instead.'); + const resultOrStream = await createSourceEventStream(args); + if (!(0, _isAsyncIterable.isAsyncIterable)(resultOrStream)) { + return resultOrStream; + } // For each payload yielded from a subscription, map it over the normal + // GraphQL `execute` function, with `payload` as the rootValue. + // This implements the "MapSourceToResponseEvent" algorithm described in + // the GraphQL specification. The `execute` function provides the + // "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the + // "ExecuteQuery" algorithm, for which `execute` is also used. + + const mapSourceToResponse = payload => (0, _execute.execute)({ + ...args, + rootValue: payload + }); // Map every source value to a ExecutionResult value as described above. + + return (0, _mapAsyncIterator.mapAsyncIterator)(resultOrStream, mapSourceToResponse); } -function isCompletedExecutionGroup(subsequentResult) { - return 'pendingExecutionGroup' in subsequentResult; +function toNormalizedArgs(args) { + const firstArg = args[0]; + if (firstArg && 'document' in firstArg) { + return firstArg; + } + return { + schema: firstArg, + // FIXME: when underlying TS bug fixed, see https://github.com/microsoft/TypeScript/issues/31613 + document: args[1], + rootValue: args[2], + contextValue: args[3], + variableValues: args[4], + operationName: args[5], + subscribeFieldResolver: args[6] + }; } -function isFailedExecutionGroup(completedExecutionGroup) { - return completedExecutionGroup.errors !== undefined; -} -/** @internal */ -class DeferredFragmentRecord { - constructor(path, label, parent) { - this.path = path; - this.label = label; - this.parent = parent; - this.pendingExecutionGroups = new Set(); - this.successfulExecutionGroups = new Set(); - this.children = new Set(); +/** + * Implements the "CreateSourceEventStream" algorithm described in the + * GraphQL specification, resolving the subscription source event stream. + * + * Returns a Promise which resolves to either an AsyncIterable (if successful) + * or an ExecutionResult (error). The promise will be rejected if the schema or + * other arguments to this function are invalid, or if the resolved event stream + * is not an async iterable. + * + * If the client-provided arguments to this function do not result in a + * compliant subscription, a GraphQL Response (ExecutionResult) with + * descriptive errors and no data will be returned. + * + * If the the source stream could not be created due to faulty subscription + * resolver logic or underlying systems, the promise will resolve to a single + * ExecutionResult containing `errors` and no `data`. + * + * If the operation succeeded, the promise resolves to the AsyncIterable for the + * event stream returned by the resolver. + * + * A Source Event Stream represents a sequence of events, each of which triggers + * a GraphQL execution for that event. + * + * This may be useful when hosting the stateful subscription service in a + * different process or machine than the stateless GraphQL execution engine, + * or otherwise separating these two steps. For more on this, see the + * "Supporting Subscriptions at Scale" information in the GraphQL specification. + */ + +async function createSourceEventStream(...rawArgs) { + const args = toNormalizedArgs(rawArgs); + const { + schema, + document, + variableValues + } = args; // If arguments are missing or incorrectly typed, this is an internal + // developer mistake which should throw an early error. + + (0, _execute.assertValidExecutionArguments)(schema, document, variableValues); // If a valid execution context cannot be created due to incorrect arguments, + // a "Response" with only errors is returned. + + const exeContext = (0, _execute.buildExecutionContext)(args); // Return early errors if execution context failed. + + if (!('schema' in exeContext)) { + return { + errors: exeContext + }; + } + try { + const eventStream = await executeSubscription(exeContext); // Assert field returned an event stream, otherwise yield an error. + + if (!(0, _isAsyncIterable.isAsyncIterable)(eventStream)) { + throw new Error('Subscription field must return Async Iterable. ' + `Received: ${(0, _inspect.inspect)(eventStream)}.`); + } + return eventStream; + } catch (error) { + // If it GraphQLError, report it as an ExecutionResult, containing only errors and no data. + // Otherwise treat the error as a system-class error and re-throw it. + if (error instanceof _GraphQLError.GraphQLError) { + return { + errors: [error] + }; + } + throw error; } } -exports.DeferredFragmentRecord = DeferredFragmentRecord; -function isDeferredFragmentRecord(deliveryGroup) { - return deliveryGroup instanceof DeferredFragmentRecord; -} -function isCancellableStreamRecord(deliveryGroup) { - return 'earlyReturn' in deliveryGroup; +async function executeSubscription(exeContext) { + const { + schema, + fragments, + operation, + variableValues, + rootValue + } = exeContext; + const rootType = schema.getSubscriptionType(); + if (rootType == null) { + throw new _GraphQLError.GraphQLError('Schema is not configured to execute subscription operation.', { + nodes: operation + }); + } + const rootFields = (0, _collectFields.collectFields)(schema, fragments, variableValues, rootType, operation.selectionSet); + const [responseName, fieldNodes] = [...rootFields.entries()][0]; + const fieldDef = (0, _execute.getFieldDef)(schema, rootType, fieldNodes[0]); + if (!fieldDef) { + const fieldName = fieldNodes[0].name.value; + throw new _GraphQLError.GraphQLError(`The subscription field "${fieldName}" is not defined.`, { + nodes: fieldNodes + }); + } + const path = (0, _Path.addPath)(undefined, responseName, rootType.name); + const info = (0, _execute.buildResolveInfo)(exeContext, fieldDef, fieldNodes, rootType, path); + try { + var _fieldDef$subscribe; + + // Implements the "ResolveFieldEventStream" algorithm from GraphQL specification. + // It differs from "ResolveFieldValue" due to providing a different `resolveFn`. + // Build a JS object of arguments from the field.arguments AST, using the + // variables scope to fulfill any variable references. + const args = (0, _values.getArgumentValues)(fieldDef, fieldNodes[0], variableValues); // The resolve function's optional third argument is a context value that + // is provided to every resolve function within an execution. It is commonly + // used to represent an authenticated user, or request-specific caches. + + const contextValue = exeContext.contextValue; // Call the `subscribe()` resolver or the default resolver to produce an + // AsyncIterable yielding raw payloads. + + const resolveFn = (_fieldDef$subscribe = fieldDef.subscribe) !== null && _fieldDef$subscribe !== void 0 ? _fieldDef$subscribe : exeContext.subscribeFieldResolver; + const eventStream = await resolveFn(rootValue, args, contextValue, info); + if (eventStream instanceof Error) { + throw eventStream; + } + return eventStream; + } catch (error) { + throw (0, _locatedError.locatedError)(error, fieldNodes, (0, _Path.pathToArray)(path)); + } } /***/ }), @@ -25517,6 +24479,7 @@ exports.getArgumentValues = getArgumentValues; exports.getDirectiveValues = getDirectiveValues; exports.getVariableValues = getVariableValues; var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); +var _keyMap = __webpack_require__(/*! ../jsutils/keyMap.mjs */ "../../../node_modules/graphql/jsutils/keyMap.mjs"); var _printPathArray = __webpack_require__(/*! ../jsutils/printPathArray.mjs */ "../../../node_modules/graphql/jsutils/printPathArray.mjs"); var _GraphQLError = __webpack_require__(/*! ../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); @@ -25570,7 +24533,7 @@ function coerceVariableValues(schema, varDefNodes, inputs, onError) { })); continue; } - if (!Object.hasOwn(inputs, varName)) { + if (!hasOwnProperty(inputs, varName)) { if (varDefNode.defaultValue) { coercedValues[varName] = (0, _valueFromAST.valueFromAST)(varDefNode.defaultValue, varType); } else if ((0, _definition.isNonNullType)(varType)) { @@ -25610,18 +24573,20 @@ function coerceVariableValues(schema, varDefNodes, inputs, onError) { * exposed to user code. Care should be taken to not pull values from the * Object prototype. */ + function getArgumentValues(def, node, variableValues) { var _node$arguments; - const coercedValues = {}; - // FIXME: https://github.com/graphql/graphql-js/issues/2203 + const coercedValues = {}; // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ + const argumentNodes = (_node$arguments = node.arguments) !== null && _node$arguments !== void 0 ? _node$arguments : []; - const argNodeMap = new Map(argumentNodes.map(arg => [arg.name.value, arg])); + const argNodeMap = (0, _keyMap.keyMap)(argumentNodes, arg => arg.name.value); for (const argDef of def.args) { const name = argDef.name; const argType = argDef.type; - const argumentNode = argNodeMap.get(name); - if (argumentNode == null) { + const argumentNode = argNodeMap[name]; + if (!argumentNode) { if (argDef.defaultValue !== undefined) { coercedValues[name] = argDef.defaultValue; } else if ((0, _definition.isNonNullType)(argType)) { @@ -25635,7 +24600,7 @@ function getArgumentValues(def, node, variableValues) { let isNull = valueNode.kind === _kinds.Kind.NULL; if (valueNode.kind === _kinds.Kind.VARIABLE) { const variableName = valueNode.name.value; - if (variableValues == null || !Object.hasOwn(variableValues, variableName)) { + if (variableValues == null || !hasOwnProperty(variableValues, variableName)) { if (argDef.defaultValue !== undefined) { coercedValues[name] = argDef.defaultValue; } else if ((0, _definition.isNonNullType)(argType)) { @@ -25676,6 +24641,7 @@ function getArgumentValues(def, node, variableValues) { * exposed to user code. Care should be taken to not pull values from the * Object prototype. */ + function getDirectiveValues(directiveDef, node, variableValues) { var _node$directives; const directiveNode = (_node$directives = node.directives) === null || _node$directives === void 0 ? void 0 : _node$directives.find(directive => directive.name.value === directiveDef.name); @@ -25683,6 +24649,9 @@ function getDirectiveValues(directiveDef, node, variableValues) { return getArgumentValues(directiveDef, directiveNode, variableValues); } } +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} /***/ }), @@ -25699,11 +24668,52 @@ Object.defineProperty(exports, "__esModule", ({ })); exports.graphql = graphql; exports.graphqlSync = graphqlSync; +var _devAssert = __webpack_require__(/*! ./jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); var _isPromise = __webpack_require__(/*! ./jsutils/isPromise.mjs */ "../../../node_modules/graphql/jsutils/isPromise.mjs"); var _parser = __webpack_require__(/*! ./language/parser.mjs */ "../../../node_modules/graphql/language/parser.mjs"); var _validate = __webpack_require__(/*! ./type/validate.mjs */ "../../../node_modules/graphql/type/validate.mjs"); var _validate2 = __webpack_require__(/*! ./validation/validate.mjs */ "../../../node_modules/graphql/validation/validate.mjs"); var _execute = __webpack_require__(/*! ./execution/execute.mjs */ "../../../node_modules/graphql/execution/execute.mjs"); +/** + * This is the primary entry point function for fulfilling GraphQL operations + * by parsing, validating, and executing a GraphQL document along side a + * GraphQL schema. + * + * More sophisticated GraphQL servers, such as those which persist queries, + * may wish to separate the validation and execution phases to a static time + * tooling step, and a server runtime step. + * + * Accepts either an object with named arguments, or individual arguments: + * + * schema: + * The GraphQL type system to use when validating and executing a query. + * source: + * A GraphQL language formatted string representing the requested operation. + * rootValue: + * The value provided as the first argument to resolver functions on the top + * level type (e.g. the query object type). + * contextValue: + * The context value is provided as an argument to resolver functions after + * field arguments. It is used to pass shared information useful at any point + * during executing this query, for example the currently logged in user and + * connections to databases or other services. + * variableValues: + * A mapping of variable name to runtime value to use for all variables + * defined in the requestString. + * operationName: + * The name of the operation to use if requestString contains multiple + * possible operations. Can be omitted if requestString contains only + * one operation. + * fieldResolver: + * A resolver function to use when one is not provided by the schema. + * If not provided, the default field resolver is used (which looks for a + * value or method on the source value with the field's name). + * typeResolver: + * A type resolver function to use when none is provided by the schema. + * If not provided, the default type resolver is used (which looks for a + * `__typename` field or alternatively calls the `isTypeOf` method). + */ + function graphql(args) { // Always return a Promise for a consistent API. return new Promise(resolve => resolve(graphqlImpl(args))); @@ -25714,15 +24724,18 @@ function graphql(args) { * However, it guarantees to complete synchronously (or throw an error) assuming * that all field resolvers are also synchronous. */ + function graphqlSync(args) { - const result = graphqlImpl(args); - // Assert that the execution was synchronous. + const result = graphqlImpl(args); // Assert that the execution was synchronous. + if ((0, _isPromise.isPromise)(result)) { throw new Error('GraphQL execution failed to complete synchronously.'); } return result; } function graphqlImpl(args) { + // Temporary for v15 to v16 migration. Remove in v17 + arguments.length < 2 || (0, _devAssert.devAssert)(false, 'graphql@16 dropped long-deprecated support for positional arguments, please pass an object instead.'); const { schema, source, @@ -25732,15 +24745,15 @@ function graphqlImpl(args) { operationName, fieldResolver, typeResolver - } = args; - // Validate Schema + } = args; // Validate Schema + const schemaValidationErrors = (0, _validate.validateSchema)(schema); if (schemaValidationErrors.length > 0) { return { errors: schemaValidationErrors }; - } - // Parse + } // Parse + let document; try { document = (0, _parser.parse)(source); @@ -25748,15 +24761,15 @@ function graphqlImpl(args) { return { errors: [syntaxError] }; - } - // Validate + } // Validate + const validationErrors = (0, _validate2.validate)(schema, document); if (validationErrors.length > 0) { return { errors: validationErrors }; - } - // Execute + } // Execute + return (0, _execute.execute)({ schema, document, @@ -25848,12 +24861,6 @@ Object.defineProperty(exports, "GraphQLBoolean", ({ return _index.GraphQLBoolean; } })); -Object.defineProperty(exports, "GraphQLDeferDirective", ({ - enumerable: true, - get: function () { - return _index.GraphQLDeferDirective; - } -})); Object.defineProperty(exports, "GraphQLDeprecatedDirective", ({ enumerable: true, get: function () { @@ -25962,12 +24969,6 @@ Object.defineProperty(exports, "GraphQLSpecifiedByDirective", ({ return _index.GraphQLSpecifiedByDirective; } })); -Object.defineProperty(exports, "GraphQLStreamDirective", ({ - enumerable: true, - get: function () { - return _index.GraphQLStreamDirective; - } -})); Object.defineProperty(exports, "GraphQLString", ({ enumerable: true, get: function () { @@ -26430,6 +25431,12 @@ Object.defineProperty(exports, "assertUnionType", ({ return _index.assertUnionType; } })); +Object.defineProperty(exports, "assertValidName", ({ + enumerable: true, + get: function () { + return _index6.assertValidName; + } +})); Object.defineProperty(exports, "assertValidSchema", ({ enumerable: true, get: function () { @@ -26514,12 +25521,6 @@ Object.defineProperty(exports, "executeSync", ({ return _index3.executeSync; } })); -Object.defineProperty(exports, "experimentalExecuteIncrementally", ({ - enumerable: true, - get: function () { - return _index3.experimentalExecuteIncrementally; - } -})); Object.defineProperty(exports, "extendSchema", ({ enumerable: true, get: function () { @@ -26538,6 +25539,12 @@ Object.defineProperty(exports, "findDangerousChanges", ({ return _index6.findDangerousChanges; } })); +Object.defineProperty(exports, "formatError", ({ + enumerable: true, + get: function () { + return _index5.formatError; + } +})); Object.defineProperty(exports, "getArgumentValues", ({ enumerable: true, get: function () { @@ -26586,12 +25593,24 @@ Object.defineProperty(exports, "getOperationAST", ({ return _index6.getOperationAST; } })); +Object.defineProperty(exports, "getOperationRootType", ({ + enumerable: true, + get: function () { + return _index6.getOperationRootType; + } +})); Object.defineProperty(exports, "getVariableValues", ({ enumerable: true, get: function () { return _index3.getVariableValues; } })); +Object.defineProperty(exports, "getVisitFn", ({ + enumerable: true, + get: function () { + return _index2.getVisitFn; + } +})); Object.defineProperty(exports, "graphql", ({ enumerable: true, get: function () { @@ -26712,12 +25731,6 @@ Object.defineProperty(exports, "isNonNullType", ({ return _index.isNonNullType; } })); -Object.defineProperty(exports, "isNullabilityAssertionNode", ({ - enumerable: true, - get: function () { - return _index2.isNullabilityAssertionNode; - } -})); Object.defineProperty(exports, "isNullableType", ({ enumerable: true, get: function () { @@ -26826,6 +25839,12 @@ Object.defineProperty(exports, "isUnionType", ({ return _index.isUnionType; } })); +Object.defineProperty(exports, "isValidNameError", ({ + enumerable: true, + get: function () { + return _index6.isValidNameError; + } +})); Object.defineProperty(exports, "isValueNode", ({ enumerable: true, get: function () { @@ -26880,10 +25899,10 @@ Object.defineProperty(exports, "print", ({ return _index2.print; } })); -Object.defineProperty(exports, "printDirective", ({ +Object.defineProperty(exports, "printError", ({ enumerable: true, get: function () { - return _index6.printDirective; + return _index5.printError; } })); Object.defineProperty(exports, "printIntrospectionSchema", ({ @@ -27053,76 +26072,6 @@ var _index6 = __webpack_require__(/*! ./utilities/index.mjs */ "../../../node_mo /***/ }), -/***/ "../../../node_modules/graphql/jsutils/AccumulatorMap.mjs": -/*!****************************************************************!*\ - !*** ../../../node_modules/graphql/jsutils/AccumulatorMap.mjs ***! - \****************************************************************/ -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.AccumulatorMap = void 0; -/** - * ES6 Map with additional `add` method to accumulate items. - */ -class AccumulatorMap extends Map { - get [Symbol.toStringTag]() { - return 'AccumulatorMap'; - } - add(key, item) { - const group = this.get(key); - if (group === undefined) { - this.set(key, [item]); - } else { - group.push(item); - } - } -} -exports.AccumulatorMap = AccumulatorMap; - -/***/ }), - -/***/ "../../../node_modules/graphql/jsutils/BoxedPromiseOrValue.mjs": -/*!*********************************************************************!*\ - !*** ../../../node_modules/graphql/jsutils/BoxedPromiseOrValue.mjs ***! - \*********************************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.BoxedPromiseOrValue = void 0; -var _isPromise = __webpack_require__(/*! ./isPromise.mjs */ "../../../node_modules/graphql/jsutils/isPromise.mjs"); -/** - * A BoxedPromiseOrValue is a container for a value or promise where the value - * will be updated when the promise resolves. - * - * A BoxedPromiseOrValue may only be used with promises whose possible - * rejection has already been handled, otherwise this will lead to unhandled - * promise rejections. - * - * @internal - * */ -class BoxedPromiseOrValue { - constructor(value) { - this.value = value; - if ((0, _isPromise.isPromise)(value)) { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - value.then(resolved => { - this.value = resolved; - }); - } - } -} -exports.BoxedPromiseOrValue = BoxedPromiseOrValue; - -/***/ }), - /***/ "../../../node_modules/graphql/jsutils/Path.mjs": /*!******************************************************!*\ !*** ../../../node_modules/graphql/jsutils/Path.mjs ***! @@ -27149,6 +26098,7 @@ function addPath(prev, key, typename) { /** * Given a Path, return an Array of the path keys. */ + function pathToArray(path) { const flattened = []; let curr = path; @@ -27161,27 +26111,6 @@ function pathToArray(path) { /***/ }), -/***/ "../../../node_modules/graphql/jsutils/capitalize.mjs": -/*!************************************************************!*\ - !*** ../../../node_modules/graphql/jsutils/capitalize.mjs ***! - \************************************************************/ -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.capitalize = capitalize; -/** - * Converts the first character of string to upper case and the remaining to lower case. - */ -function capitalize(str) { - return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); -} - -/***/ }), - /***/ "../../../node_modules/graphql/jsutils/devAssert.mjs": /*!***********************************************************!*\ !*** ../../../node_modules/graphql/jsutils/devAssert.mjs ***! @@ -27195,7 +26124,8 @@ Object.defineProperty(exports, "__esModule", ({ })); exports.devAssert = devAssert; function devAssert(condition, message) { - if (!condition) { + const booleanCondition = Boolean(condition); + if (!booleanCondition) { throw new Error(message); } } @@ -27206,7 +26136,7 @@ function devAssert(condition, message) { /*!************************************************************!*\ !*** ../../../node_modules/graphql/jsutils/didYouMean.mjs ***! \************************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { +/***/ (function(__unused_webpack_module, exports) { @@ -27214,84 +26144,29 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.didYouMean = didYouMean; -var _formatList = __webpack_require__(/*! ./formatList.mjs */ "../../../node_modules/graphql/jsutils/formatList.mjs"); const MAX_SUGGESTIONS = 5; +/** + * Given [ A, B, C ] return ' Did you mean A, B, or C?'. + */ + function didYouMean(firstArg, secondArg) { - const [subMessage, suggestions] = secondArg ? [firstArg, secondArg] : [undefined, firstArg]; - if (suggestions.length === 0) { - return ''; - } + const [subMessage, suggestionsArg] = secondArg ? [firstArg, secondArg] : [undefined, firstArg]; let message = ' Did you mean '; - if (subMessage != null) { + if (subMessage) { message += subMessage + ' '; } - const suggestionList = (0, _formatList.orList)(suggestions.slice(0, MAX_SUGGESTIONS).map(x => `"${x}"`)); - return message + suggestionList + '?'; -} - -/***/ }), - -/***/ "../../../node_modules/graphql/jsutils/formatList.mjs": -/*!************************************************************!*\ - !*** ../../../node_modules/graphql/jsutils/formatList.mjs ***! - \************************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.andList = andList; -exports.orList = orList; -var _invariant = __webpack_require__(/*! ./invariant.mjs */ "../../../node_modules/graphql/jsutils/invariant.mjs"); -/** - * Given [ A, B, C ] return 'A, B, or C'. - */ -function orList(items) { - return formatList('or', items); -} -/** - * Given [ A, B, C ] return 'A, B, and C'. - */ -function andList(items) { - return formatList('and', items); -} -function formatList(conjunction, items) { - items.length !== 0 || (0, _invariant.invariant)(false); - switch (items.length) { + const suggestions = suggestionsArg.map(x => `"${x}"`); + switch (suggestions.length) { + case 0: + return ''; case 1: - return items[0]; + return message + suggestions[0] + '?'; case 2: - return items[0] + ' ' + conjunction + ' ' + items[1]; + return message + suggestions[0] + ' or ' + suggestions[1] + '?'; } - const allButLast = items.slice(0, -1); - const lastItem = items.at(-1); - return allButLast.join(', ') + ', ' + conjunction + ' ' + lastItem; -} - -/***/ }), - -/***/ "../../../node_modules/graphql/jsutils/getBySet.mjs": -/*!**********************************************************!*\ - !*** ../../../node_modules/graphql/jsutils/getBySet.mjs ***! - \**********************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.getBySet = getBySet; -var _isSameSet = __webpack_require__(/*! ./isSameSet.mjs */ "../../../node_modules/graphql/jsutils/isSameSet.mjs"); -function getBySet(map, setToMatch) { - for (const set of map.keys()) { - if ((0, _isSameSet.isSameSet)(set, setToMatch)) { - return map.get(set); - } - } - return undefined; + const selected = suggestions.slice(0, MAX_SUGGESTIONS); + const lastItem = selected.pop(); + return message + selected.join(', ') + ', or ' + lastItem + '?'; } /***/ }), @@ -27300,7 +26175,7 @@ function getBySet(map, setToMatch) { /*!*********************************************************!*\ !*** ../../../node_modules/graphql/jsutils/groupBy.mjs ***! \*********************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { +/***/ (function(__unused_webpack_module, exports) { @@ -27308,14 +26183,19 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.groupBy = groupBy; -var _AccumulatorMap = __webpack_require__(/*! ./AccumulatorMap.mjs */ "../../../node_modules/graphql/jsutils/AccumulatorMap.mjs"); /** * Groups array items into a Map, given a function to produce grouping key. */ function groupBy(list, keyFn) { - const result = new _AccumulatorMap.AccumulatorMap(); + const result = new Map(); for (const item of list) { - result.add(keyFn(item), item); + const key = keyFn(item); + const group = result.get(key); + if (group === undefined) { + result.set(key, [item]); + } else { + group.push(item); + } } return result; } @@ -27360,6 +26240,7 @@ const MAX_RECURSIVE_DEPTH = 2; /** * Used to print values in error messages. */ + function inspect(value) { return formatValue(value, []); } @@ -27384,8 +26265,8 @@ function formatObjectValue(value, previouslySeenValues) { } const seenValues = [...previouslySeenValues, value]; if (isJSONable(value)) { - const jsonValue = value.toJSON(); - // check for infinite recursion + const jsonValue = value.toJSON(); // check for infinite recursion + if (jsonValue !== value) { return typeof jsonValue === 'string' ? jsonValue : formatValue(jsonValue, seenValues); } @@ -27454,15 +26335,21 @@ Object.defineProperty(exports, "__esModule", ({ })); exports.instanceOf = void 0; var _inspect = __webpack_require__(/*! ./inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); +/* c8 ignore next 3 */ + +const isProduction = globalThis.process && +// eslint-disable-next-line no-undef +"development" === 'production'; /** * A replacement for instanceof which includes an error warning when multi-realm * constructors are detected. * See: https://expressjs.com/en/advanced/best-practice-performance.html#set-node_env-to-production * See: https://webpack.js.org/guides/production/ */ + const instanceOf = exports.instanceOf = /* c8 ignore next 6 */ // FIXME: https://github.com/graphql/graphql-js/issues/2317 -globalThis.process != null && globalThis.process.env.NODE_ENV === 'production' ? function instanceOf(value, constructor) { +isProduction ? function instanceOf(value, constructor) { return value instanceof constructor; } : function instanceOf(value, constructor) { if (value instanceof constructor) { @@ -27470,11 +26357,13 @@ globalThis.process != null && globalThis.process.env.NODE_ENV === 'production' ? } if (typeof value === 'object' && value !== null) { var _value$constructor; + // Prefer Symbol.toStringTag since it is immune to minification. const className = constructor.prototype[Symbol.toStringTag]; const valueClassName = // We still need to support constructor's name to detect conflicts with older versions of this library. - Symbol.toStringTag in value ? value[Symbol.toStringTag] : (_value$constructor = value.constructor) === null || _value$constructor === void 0 ? void 0 : _value$constructor.name; + Symbol.toStringTag in value // @ts-expect-error TS bug see, https://github.com/microsoft/TypeScript/issues/38009 + ? value[Symbol.toStringTag] : (_value$constructor = value.constructor) === null || _value$constructor === void 0 ? void 0 : _value$constructor.name; if (className === valueClassName) { const stringifiedValue = (0, _inspect.inspect)(value); throw new Error(`Cannot use ${className} "${stringifiedValue}" from another module or realm. @@ -27509,7 +26398,8 @@ Object.defineProperty(exports, "__esModule", ({ })); exports.invariant = invariant; function invariant(condition, message) { - if (!condition) { + const booleanCondition = Boolean(condition); + if (!booleanCondition) { throw new Error(message != null ? message : 'Unexpected invariant triggered.'); } } @@ -27617,32 +26507,6 @@ function isPromise(value) { /***/ }), -/***/ "../../../node_modules/graphql/jsutils/isSameSet.mjs": -/*!***********************************************************!*\ - !*** ../../../node_modules/graphql/jsutils/isSameSet.mjs ***! - \***********************************************************/ -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.isSameSet = isSameSet; -function isSameSet(setA, setB) { - if (setA.size !== setB.size) { - return false; - } - for (const item of setA) { - if (!setB.has(item)) { - return false; - } - } - return true; -} - -/***/ }), - /***/ "../../../node_modules/graphql/jsutils/keyMap.mjs": /*!********************************************************!*\ !*** ../../../node_modules/graphql/jsutils/keyMap.mjs ***! @@ -27904,15 +26768,14 @@ exports.promiseForObject = promiseForObject; * This is akin to bluebird's `Promise.props`, but implemented only using * `Promise.all` so it will work with any implementation of ES6 promises. */ -async function promiseForObject(object, callback) { - const keys = Object.keys(object); - const values = Object.values(object); - const resolvedValues = await Promise.all(values); - const resolvedObject = Object.create(null); - for (let i = 0; i < keys.length; ++i) { - resolvedObject[keys[i]] = resolvedValues[i]; - } - return callback(resolvedObject); +function promiseForObject(object) { + return Promise.all(Object.values(object)).then(resolvedValues => { + const resolvedObject = Object.create(null); + for (const [i, key] of Object.keys(object).entries()) { + resolvedObject[key] = resolvedValues[i]; + } + return resolvedObject; + }); } /***/ }), @@ -27947,39 +26810,6 @@ function promiseReduce(values, callbackFn, initialValue) { /***/ }), -/***/ "../../../node_modules/graphql/jsutils/promiseWithResolvers.mjs": -/*!**********************************************************************!*\ - !*** ../../../node_modules/graphql/jsutils/promiseWithResolvers.mjs ***! - \**********************************************************************/ -/***/ (function(__unused_webpack_module, exports) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.promiseWithResolvers = promiseWithResolvers; -/** - * Based on Promise.withResolvers proposal - * https://github.com/tc39/proposal-promise-with-resolvers - */ -function promiseWithResolvers() { - // these are assigned synchronously within the Promise constructor - let resolve; - let reject; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - return { - promise, - resolve, - reject - }; -} - -/***/ }), - /***/ "../../../node_modules/graphql/jsutils/suggestionList.mjs": /*!****************************************************************!*\ !*** ../../../node_modules/graphql/jsutils/suggestionList.mjs ***! @@ -27997,6 +26827,7 @@ var _naturalCompare = __webpack_require__(/*! ./naturalCompare.mjs */ "../../../ * Given an invalid input string and a list of valid options, returns a filtered * list of valid options sorted based on their similarity with the input. */ + function suggestionList(input, options) { const optionsByDistance = Object.create(null); const lexicalDistance = new LexicalDistance(input); @@ -28026,6 +26857,7 @@ function suggestionList(input, options) { * * This distance can be useful for detecting typos in input or sorting */ + class LexicalDistance { constructor(input) { this._input = input; @@ -28037,8 +26869,8 @@ class LexicalDistance { if (this._input === option) { return 0; } - const optionLowerCase = option.toLowerCase(); - // Any case change counts as a single edit + const optionLowerCase = option.toLowerCase(); // Any case change counts as a single edit + if (this._inputLowerCase === optionLowerCase) { return 1; } @@ -28068,7 +26900,8 @@ class LexicalDistance { // delete currentRow[j - 1] + 1, // insert - upRow[j - 1] + cost); + upRow[j - 1] + cost // substitute + ); if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) { // transposition const doubleDiagonalCell = rows[(i - 2) % 3][j - 2]; @@ -28078,8 +26911,8 @@ class LexicalDistance { smallestCell = currentCell; } currentRow[j] = currentCell; - } - // Early exit, since distance can't go smaller than smallest element of the previous row. + } // Early exit, since distance can't go smaller than smallest element of the previous row. + if (smallestCell > threshold) { return undefined; } @@ -28115,6 +26948,7 @@ var _inspect = __webpack_require__(/*! ./inspect.mjs */ "../../../node_modules/g /** * Sometimes a non-error is thrown, wrap it as an Error instance to ensure a consistent Error interface. */ + function toError(thrownValue) { return thrownValue instanceof Error ? thrownValue : new NonErrorThrown(thrownValue); } @@ -28174,6 +27008,25 @@ exports.isNode = isNode; * identify the region of the source from which the AST derived. */ class Location { + /** + * The character offset at which this Node begins. + */ + + /** + * The character offset at which this Node ends. + */ + + /** + * The Token at which this Node begins. + */ + + /** + * The Token at which this Node ends. + */ + + /** + * The Source document the AST represents. + */ constructor(startToken, endToken, source) { this.start = startToken.start; this.end = endToken.end; @@ -28197,14 +27050,45 @@ class Location { */ exports.Location = Location; class Token { - // eslint-disable-next-line max-params + /** + * The kind of Token. + */ + + /** + * The character offset at which this Node begins. + */ + + /** + * The character offset at which this Node ends. + */ + + /** + * The 1-indexed line number on which this Token appears. + */ + + /** + * The 1-indexed column number at which this Token begins. + */ + + /** + * For non-punctuation tokens, represents the interpreted value of the token. + * + * Note: is undefined for punctuation tokens, but typed as string for + * convenience in the parser. + */ + + /** + * Tokens exist as nodes in a double-linked-list amongst all tokens + * including ignored tokens. is always the first node and + * the last. + */ constructor(kind, start, end, line, column, value) { this.kind = kind; this.start = start; this.end = end; this.line = line; - this.column = column; - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.column = column; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.value = value; this.prev = null; this.next = null; @@ -28221,6 +27105,10 @@ class Token { }; } } +/** + * The list of all possible AST node types. + */ + /** * @internal */ @@ -28232,16 +27120,8 @@ const QueryDocumentKeys = exports.QueryDocumentKeys = { VariableDefinition: ['variable', 'type', 'defaultValue', 'directives'], Variable: ['name'], SelectionSet: ['selections'], - Field: ['alias', 'name', 'arguments', 'directives', 'selectionSet', - // Note: Client Controlled Nullability is experimental and may be changed - // or removed in the future. - 'nullabilityAssertion'], + Field: ['alias', 'name', 'arguments', 'directives', 'selectionSet'], Argument: ['name', 'value'], - // Note: Client Controlled Nullability is experimental and may be changed - // or removed in the future. - ListNullabilityOperator: ['nullabilityAssertion'], - NonNullAssertion: ['nullabilityAssertion'], - ErrorBoundary: ['nullabilityAssertion'], FragmentSpread: ['name', 'directives'], InlineFragment: ['typeCondition', 'directives', 'selectionSet'], FragmentDefinition: ['name', @@ -28284,10 +27164,13 @@ const kindValues = new Set(Object.keys(QueryDocumentKeys)); /** * @internal */ + function isNode(maybeNode) { const maybeKind = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.kind; return typeof maybeKind === 'string' && kindValues.has(maybeKind); } +/** Name */ + var OperationTypeNode; (function (OperationTypeNode) { OperationTypeNode['QUERY'] = 'query'; @@ -28320,28 +27203,28 @@ var _characterClasses = __webpack_require__(/*! ./characterClasses.mjs */ "../.. * * @internal */ + function dedentBlockStringLines(lines) { - var _firstNonEmptyLine; + var _firstNonEmptyLine2; let commonIndent = Number.MAX_SAFE_INTEGER; let firstNonEmptyLine = null; let lastNonEmptyLine = -1; for (let i = 0; i < lines.length; ++i) { + var _firstNonEmptyLine; const line = lines[i]; const indent = leadingWhitespace(line); if (indent === line.length) { continue; // skip empty lines } - firstNonEmptyLine ??= i; + firstNonEmptyLine = (_firstNonEmptyLine = firstNonEmptyLine) !== null && _firstNonEmptyLine !== void 0 ? _firstNonEmptyLine : i; lastNonEmptyLine = i; if (i !== 0 && indent < commonIndent) { commonIndent = indent; } } - return lines - // Remove common indentation from all lines but first. - .map((line, i) => i === 0 ? line : line.slice(commonIndent)) - // Remove leading and trailing blank lines. - .slice((_firstNonEmptyLine = firstNonEmptyLine) !== null && _firstNonEmptyLine !== void 0 ? _firstNonEmptyLine : 0, lastNonEmptyLine + 1); + return lines // Remove common indentation from all lines but first. + .map((line, i) => i === 0 ? line : line.slice(commonIndent)) // Remove leading and trailing blank lines. + .slice((_firstNonEmptyLine2 = firstNonEmptyLine) !== null && _firstNonEmptyLine2 !== void 0 ? _firstNonEmptyLine2 : 0, lastNonEmptyLine + 1); } function leadingWhitespace(str) { let i = 0; @@ -28353,6 +27236,7 @@ function leadingWhitespace(str) { /** * @internal */ + function isPrintableAsBlockString(value) { if (value === '') { return true; // empty string is printable @@ -28378,10 +27262,12 @@ function isPrintableAsBlockString(value) { case 0x000f: return false; // Has non-printable characters + case 0x000d: // \r return false; // Has \r or \r\n which will be replaced as \n + case 10: // \n if (isEmptyLine && !seenNonEmptyLine) { @@ -28392,12 +27278,13 @@ function isPrintableAsBlockString(value) { hasIndent = false; break; case 9: // \t + case 32: // - hasIndent ||= isEmptyLine; + hasIndent || (hasIndent = isEmptyLine); break; default: - hasCommonIndent &&= hasIndent; + hasCommonIndent && (hasCommonIndent = hasIndent); isEmptyLine = false; } } @@ -28416,24 +27303,25 @@ function isPrintableAsBlockString(value) { * * @internal */ + function printBlockString(value, options) { - const escapedValue = value.replaceAll('"""', '\\"""'); - // Expand a block string's raw value into independent lines. + const escapedValue = value.replace(/"""/g, '\\"""'); // Expand a block string's raw value into independent lines. + const lines = escapedValue.split(/\r\n|[\n\r]/g); - const isSingleLine = lines.length === 1; - // If common indentation is found we can fix some of those cases by adding leading new line - const forceLeadingNewLine = lines.length > 1 && lines.slice(1).every(line => line.length === 0 || (0, _characterClasses.isWhiteSpace)(line.charCodeAt(0))); - // Trailing triple quotes just looks confusing but doesn't force trailing new line - const hasTrailingTripleQuotes = escapedValue.endsWith('\\"""'); - // Trailing quote (single or double) or slash forces trailing new line + const isSingleLine = lines.length === 1; // If common indentation is found we can fix some of those cases by adding leading new line + + const forceLeadingNewLine = lines.length > 1 && lines.slice(1).every(line => line.length === 0 || (0, _characterClasses.isWhiteSpace)(line.charCodeAt(0))); // Trailing triple quotes just looks confusing but doesn't force trailing new line + + const hasTrailingTripleQuotes = escapedValue.endsWith('\\"""'); // Trailing quote (single or double) or slash forces trailing new line + const hasTrailingQuote = value.endsWith('"') && !hasTrailingTripleQuotes; const hasTrailingSlash = value.endsWith('\\'); const forceTrailingNewline = hasTrailingQuote || hasTrailingSlash; const printAsMultipleLines = !(options !== null && options !== void 0 && options.minimize) && ( // add leading and trailing new lines only if it improves readability !isSingleLine || value.length > 70 || forceTrailingNewline || forceLeadingNewLine || hasTrailingTripleQuotes); - let result = ''; - // Format a multi-line block quote to account for leading space. + let result = ''; // Format a multi-line block quote to account for leading space. + const skipLeadingNewLine = isSingleLine && (0, _characterClasses.isWhiteSpace)(value.charCodeAt(0)); if (printAsMultipleLines && !skipLeadingNewLine || forceLeadingNewLine) { result += '\n'; @@ -28481,6 +27369,7 @@ function isWhiteSpace(code) { * ``` * @internal */ + function isDigit(code) { return code >= 0x0030 && code <= 0x0039; } @@ -28494,6 +27383,7 @@ function isDigit(code) { * ``` * @internal */ + function isLetter(code) { return code >= 0x0061 && code <= 0x007a || // A-Z @@ -28508,6 +27398,7 @@ function isLetter(code) { * ``` * @internal */ + function isNameStart(code) { return isLetter(code) || code === 0x005f; } @@ -28520,6 +27411,7 @@ function isNameStart(code) { * ``` * @internal */ + function isNameContinue(code) { return isLetter(code) || isDigit(code) || code === 0x005f; } @@ -28543,7 +27435,6 @@ exports.DirectiveLocation = void 0; */ var DirectiveLocation; (function (DirectiveLocation) { - /** Request Definitions */ DirectiveLocation['QUERY'] = 'QUERY'; DirectiveLocation['MUTATION'] = 'MUTATION'; DirectiveLocation['SUBSCRIPTION'] = 'SUBSCRIPTION'; @@ -28552,7 +27443,6 @@ var DirectiveLocation; DirectiveLocation['FRAGMENT_SPREAD'] = 'FRAGMENT_SPREAD'; DirectiveLocation['INLINE_FRAGMENT'] = 'INLINE_FRAGMENT'; DirectiveLocation['VARIABLE_DEFINITION'] = 'VARIABLE_DEFINITION'; - /** Type System Definitions */ DirectiveLocation['SCHEMA'] = 'SCHEMA'; DirectiveLocation['SCALAR'] = 'SCALAR'; DirectiveLocation['OBJECT'] = 'OBJECT'; @@ -28566,6 +27456,12 @@ var DirectiveLocation; DirectiveLocation['INPUT_FIELD_DEFINITION'] = 'INPUT_FIELD_DEFINITION'; })(DirectiveLocation || (exports.DirectiveLocation = DirectiveLocation = {})); +/** + * The enum type representing the directive location values. + * + * @deprecated Please use `DirectiveLocation`. Will be remove in v17. + */ + /***/ }), /***/ "../../../node_modules/graphql/language/index.mjs": @@ -28645,6 +27541,12 @@ Object.defineProperty(exports, "getLocation", ({ return _location.getLocation; } })); +Object.defineProperty(exports, "getVisitFn", ({ + enumerable: true, + get: function () { + return _visitor.getVisitFn; + } +})); Object.defineProperty(exports, "isConstValueNode", ({ enumerable: true, get: function () { @@ -28663,12 +27565,6 @@ Object.defineProperty(exports, "isExecutableDefinitionNode", ({ return _predicates.isExecutableDefinitionNode; } })); -Object.defineProperty(exports, "isNullabilityAssertionNode", ({ - enumerable: true, - get: function () { - return _predicates.isNullabilityAssertionNode; - } -})); Object.defineProperty(exports, "isSelectionNode", ({ enumerable: true, get: function () { @@ -28797,24 +27693,16 @@ exports.Kind = void 0; */ var Kind; (function (Kind) { - /** Name */ Kind['NAME'] = 'Name'; - /** Document */ Kind['DOCUMENT'] = 'Document'; Kind['OPERATION_DEFINITION'] = 'OperationDefinition'; Kind['VARIABLE_DEFINITION'] = 'VariableDefinition'; Kind['SELECTION_SET'] = 'SelectionSet'; Kind['FIELD'] = 'Field'; Kind['ARGUMENT'] = 'Argument'; - /** Nullability Modifiers */ - Kind['LIST_NULLABILITY_OPERATOR'] = 'ListNullabilityOperator'; - Kind['NON_NULL_ASSERTION'] = 'NonNullAssertion'; - Kind['ERROR_BOUNDARY'] = 'ErrorBoundary'; - /** Fragments */ Kind['FRAGMENT_SPREAD'] = 'FragmentSpread'; Kind['INLINE_FRAGMENT'] = 'InlineFragment'; Kind['FRAGMENT_DEFINITION'] = 'FragmentDefinition'; - /** Values */ Kind['VARIABLE'] = 'Variable'; Kind['INT'] = 'IntValue'; Kind['FLOAT'] = 'FloatValue'; @@ -28825,16 +27713,12 @@ var Kind; Kind['LIST'] = 'ListValue'; Kind['OBJECT'] = 'ObjectValue'; Kind['OBJECT_FIELD'] = 'ObjectField'; - /** Directives */ Kind['DIRECTIVE'] = 'Directive'; - /** Types */ Kind['NAMED_TYPE'] = 'NamedType'; Kind['LIST_TYPE'] = 'ListType'; Kind['NON_NULL_TYPE'] = 'NonNullType'; - /** Type System Definitions */ Kind['SCHEMA_DEFINITION'] = 'SchemaDefinition'; Kind['OPERATION_TYPE_DEFINITION'] = 'OperationTypeDefinition'; - /** Type Definitions */ Kind['SCALAR_TYPE_DEFINITION'] = 'ScalarTypeDefinition'; Kind['OBJECT_TYPE_DEFINITION'] = 'ObjectTypeDefinition'; Kind['FIELD_DEFINITION'] = 'FieldDefinition'; @@ -28844,11 +27728,8 @@ var Kind; Kind['ENUM_TYPE_DEFINITION'] = 'EnumTypeDefinition'; Kind['ENUM_VALUE_DEFINITION'] = 'EnumValueDefinition'; Kind['INPUT_OBJECT_TYPE_DEFINITION'] = 'InputObjectTypeDefinition'; - /** Directive Definitions */ Kind['DIRECTIVE_DEFINITION'] = 'DirectiveDefinition'; - /** Type System Extensions */ Kind['SCHEMA_EXTENSION'] = 'SchemaExtension'; - /** Type Extensions */ Kind['SCALAR_TYPE_EXTENSION'] = 'ScalarTypeExtension'; Kind['OBJECT_TYPE_EXTENSION'] = 'ObjectTypeExtension'; Kind['INTERFACE_TYPE_EXTENSION'] = 'InterfaceTypeExtension'; @@ -28857,6 +27738,12 @@ var Kind; Kind['INPUT_OBJECT_TYPE_EXTENSION'] = 'InputObjectTypeExtension'; })(Kind || (exports.Kind = Kind = {})); +/** + * The enum type representing the possible kind values of AST nodes. + * + * @deprecated Please use `Kind`. Will be remove in v17. + */ + /***/ }), /***/ "../../../node_modules/graphql/language/lexer.mjs": @@ -28885,7 +27772,23 @@ var _tokenKind = __webpack_require__(/*! ./tokenKind.mjs */ "../../../node_modul * EOF, after which the lexer will repeatedly return the same EOF token * whenever called. */ + class Lexer { + /** + * The previously focused non-ignored token. + */ + + /** + * The currently focused non-ignored token. + */ + + /** + * The (1-indexed) line containing the current token. + */ + + /** + * The character offset at which the current line begins. + */ constructor(source) { const startOfFileToken = new _ast.Token(_tokenKind.TokenKind.SOF, 0, 0, 0, 0); this.source = source; @@ -28900,6 +27803,7 @@ class Lexer { /** * Advances the token stream to the next non-ignored token. */ + advance() { this.lastToken = this.token; const token = this.token = this.lookahead(); @@ -28909,6 +27813,7 @@ class Lexer { * Looks ahead and returns the next non-ignored token, but does not change * the state of Lexer. */ + lookahead() { let token = this.token; if (token.kind !== _tokenKind.TokenKind.EOF) { @@ -28917,10 +27822,10 @@ class Lexer { token = token.next; } else { // Read the next token and form a link in the token linked-list. - const nextToken = readNextToken(this, token.end); - // @ts-expect-error next is only mutable during parsing. - token.next = nextToken; - // @ts-expect-error prev is only mutable during parsing. + const nextToken = readNextToken(this, token.end); // @ts-expect-error next is only mutable during parsing. + + token.next = nextToken; // @ts-expect-error prev is only mutable during parsing. + nextToken.prev = token; token = nextToken; } @@ -28934,7 +27839,7 @@ class Lexer { */ exports.Lexer = Lexer; function isPunctuatorTokenKind(kind) { - return kind === _tokenKind.TokenKind.BANG || kind === _tokenKind.TokenKind.QUESTION_MARK || kind === _tokenKind.TokenKind.DOLLAR || kind === _tokenKind.TokenKind.AMP || kind === _tokenKind.TokenKind.PAREN_L || kind === _tokenKind.TokenKind.PAREN_R || kind === _tokenKind.TokenKind.SPREAD || kind === _tokenKind.TokenKind.COLON || kind === _tokenKind.TokenKind.EQUALS || kind === _tokenKind.TokenKind.AT || kind === _tokenKind.TokenKind.BRACKET_L || kind === _tokenKind.TokenKind.BRACKET_R || kind === _tokenKind.TokenKind.BRACE_L || kind === _tokenKind.TokenKind.PIPE || kind === _tokenKind.TokenKind.BRACE_R; + return kind === _tokenKind.TokenKind.BANG || kind === _tokenKind.TokenKind.DOLLAR || kind === _tokenKind.TokenKind.AMP || kind === _tokenKind.TokenKind.PAREN_L || kind === _tokenKind.TokenKind.PAREN_R || kind === _tokenKind.TokenKind.SPREAD || kind === _tokenKind.TokenKind.COLON || kind === _tokenKind.TokenKind.EQUALS || kind === _tokenKind.TokenKind.AT || kind === _tokenKind.TokenKind.BRACKET_L || kind === _tokenKind.TokenKind.BRACKET_R || kind === _tokenKind.TokenKind.BRACE_L || kind === _tokenKind.TokenKind.PIPE || kind === _tokenKind.TokenKind.BRACE_R; } /** * A Unicode scalar value is any Unicode code point except surrogate code @@ -28944,6 +27849,7 @@ function isPunctuatorTokenKind(kind) { * SourceCharacter :: * - "Any Unicode scalar value" */ + function isUnicodeScalarValue(code) { return code >= 0x0000 && code <= 0xd7ff || code >= 0xe000 && code <= 0x10ffff; } @@ -28955,6 +27861,7 @@ function isUnicodeScalarValue(code) { * encodes a supplementary code point (above U+FFFF), but unpaired surrogate * code points are not valid source characters. */ + function isSupplementaryCodePoint(body, location) { return isLeadingSurrogate(body.charCodeAt(location)) && isTrailingSurrogate(body.charCodeAt(location + 1)); } @@ -28971,6 +27878,7 @@ function isTrailingSurrogate(code) { * Printable ASCII is printed quoted, while other points are printed in Unicode * code point form (ie. U+1234). */ + function printCodePointAt(lexer, location) { const code = lexer.source.body.codePointAt(location); if (code === undefined) { @@ -28979,13 +27887,14 @@ function printCodePointAt(lexer, location) { // Printable ASCII const char = String.fromCodePoint(code); return char === '"' ? "'\"'" : `"${char}"`; - } - // Unicode code point + } // Unicode code point + return 'U+' + code.toString(16).toUpperCase().padStart(4, '0'); } /** * Create a token with line and column location information. */ + function createToken(lexer, kind, start, end, value) { const line = lexer.line; const col = 1 + start - lexer.lineStart; @@ -28998,13 +27907,14 @@ function createToken(lexer, kind, start, end, value) { * punctuators immediately or calls the appropriate helper function for more * complicated tokens. */ + function readNextToken(lexer, start) { const body = lexer.source.body; const bodyLength = body.length; let position = start; while (position < bodyLength) { - const code = body.charCodeAt(position); - // SourceCharacter + const code = body.charCodeAt(position); // SourceCharacter + switch (code) { // Ignored :: // - UnicodeBOM @@ -29021,8 +27931,11 @@ function readNextToken(lexer, start) { // // Comma :: , case 0xfeff: // + case 0x0009: // \t + case 0x0020: // + case 0x002c: // , ++position; @@ -29031,6 +27944,7 @@ function readNextToken(lexer, start) { // - "New Line (U+000A)" // - "Carriage Return (U+000D)" [lookahead != "New Line (U+000A)"] // - "Carriage Return (U+000D)" "New Line (U+000A)" + case 0x000a: // \n ++position; @@ -29048,6 +27962,7 @@ function readNextToken(lexer, start) { lexer.lineStart = position; continue; // Comment + case 0x0023: // # return readComment(lexer, position); @@ -29059,6 +27974,7 @@ function readNextToken(lexer, start) { // - StringValue // // Punctuator :: one of ! $ & ( ) ... : = @ [ ] { | } + case 0x0021: // ! return createToken(lexer, _tokenKind.TokenKind.BANG, position, position + 1); @@ -29104,22 +28020,20 @@ function readNextToken(lexer, start) { case 0x007d: // } return createToken(lexer, _tokenKind.TokenKind.BRACE_R, position, position + 1); - case 0x003f: - // ? - return createToken(lexer, _tokenKind.TokenKind.QUESTION_MARK, position, position + 1); // StringValue + case 0x0022: // " if (body.charCodeAt(position + 1) === 0x0022 && body.charCodeAt(position + 2) === 0x0022) { return readBlockString(lexer, position); } return readString(lexer, position); - } - // IntValue | FloatValue (Digit | -) + } // IntValue | FloatValue (Digit | -) + if ((0, _characterClasses.isDigit)(code) || code === 0x002d) { return readNumber(lexer, position, code); - } - // Name + } // Name + if ((0, _characterClasses.isNameStart)(code)) { return readName(lexer, position); } @@ -29136,17 +28050,18 @@ function readNextToken(lexer, start) { * CommentChar :: SourceCharacter but not LineTerminator * ``` */ + function readComment(lexer, start) { const body = lexer.source.body; const bodyLength = body.length; let position = start + 1; while (position < bodyLength) { - const code = body.charCodeAt(position); - // LineTerminator (\n | \r) + const code = body.charCodeAt(position); // LineTerminator (\n | \r) + if (code === 0x000a || code === 0x000d) { break; - } - // SourceCharacter + } // SourceCharacter + if (isUnicodeScalarValue(code)) { ++position; } else if (isSupplementaryCodePoint(body, position)) { @@ -29186,16 +28101,17 @@ function readComment(lexer, start) { * Sign :: one of + - * ``` */ + function readNumber(lexer, start, firstCode) { const body = lexer.source.body; let position = start; let code = firstCode; - let isFloat = false; - // NegativeSign (-) + let isFloat = false; // NegativeSign (-) + if (code === 0x002d) { code = body.charCodeAt(++position); - } - // Zero (0) + } // Zero (0) + if (code === 0x0030) { code = body.charCodeAt(++position); if ((0, _characterClasses.isDigit)(code)) { @@ -29204,26 +28120,26 @@ function readNumber(lexer, start, firstCode) { } else { position = readDigits(lexer, position, code); code = body.charCodeAt(position); - } - // Full stop (.) + } // Full stop (.) + if (code === 0x002e) { isFloat = true; code = body.charCodeAt(++position); position = readDigits(lexer, position, code); code = body.charCodeAt(position); - } - // E e + } // E e + if (code === 0x0045 || code === 0x0065) { isFloat = true; - code = body.charCodeAt(++position); - // + - + code = body.charCodeAt(++position); // + - + if (code === 0x002b || code === 0x002d) { code = body.charCodeAt(++position); } position = readDigits(lexer, position, code); code = body.charCodeAt(position); - } - // Numbers cannot be followed by . or NameStart + } // Numbers cannot be followed by . or NameStart + if (code === 0x002e || (0, _characterClasses.isNameStart)(code)) { throw (0, _syntaxError.syntaxError)(lexer.source, position, `Invalid number, expected digit but got: ${printCodePointAt(lexer, position)}.`); } @@ -29232,12 +28148,14 @@ function readNumber(lexer, start, firstCode) { /** * Returns the new position in the source after reading one or more digits. */ + function readDigits(lexer, start, firstCode) { if (!(0, _characterClasses.isDigit)(firstCode)) { throw (0, _syntaxError.syntaxError)(lexer.source, start, `Invalid number, expected digit but got: ${printCodePointAt(lexer, start)}.`); } const body = lexer.source.body; let position = start + 1; // +1 to skip first firstCode + while ((0, _characterClasses.isDigit)(body.charCodeAt(position))) { ++position; } @@ -29263,6 +28181,7 @@ function readDigits(lexer, start, firstCode) { * EscapedCharacter :: one of `"` `\` `/` `b` `f` `n` `r` `t` * ``` */ + function readString(lexer, start) { const body = lexer.source.body; const bodyLength = body.length; @@ -29270,13 +28189,13 @@ function readString(lexer, start) { let chunkStart = position; let value = ''; while (position < bodyLength) { - const code = body.charCodeAt(position); - // Closing Quote (") + const code = body.charCodeAt(position); // Closing Quote (") + if (code === 0x0022) { value += body.slice(chunkStart, position); return createToken(lexer, _tokenKind.TokenKind.STRING, start, position + 1, value); - } - // Escape Sequence (\) + } // Escape Sequence (\) + if (code === 0x005c) { value += body.slice(chunkStart, position); const escape = body.charCodeAt(position + 1) === 0x0075 // u @@ -29286,12 +28205,12 @@ function readString(lexer, start) { position += escape.size; chunkStart = position; continue; - } - // LineTerminator (\n | \r) + } // LineTerminator (\n | \r) + if (code === 0x000a || code === 0x000d) { break; - } - // SourceCharacter + } // SourceCharacter + if (isUnicodeScalarValue(code)) { ++position; } else if (isSupplementaryCodePoint(body, position)) { @@ -29301,15 +28220,16 @@ function readString(lexer, start) { } } throw (0, _syntaxError.syntaxError)(lexer.source, position, 'Unterminated string.'); -} +} // The string value and lexed size of an escape sequence. + function readEscapedUnicodeVariableWidth(lexer, position) { const body = lexer.source.body; let point = 0; - let size = 3; - // Cannot be larger than 12 chars (\u{00000000}). + let size = 3; // Cannot be larger than 12 chars (\u{00000000}). + while (size < 12) { - const code = body.charCodeAt(position + size++); - // Closing Brace (}) + const code = body.charCodeAt(position + size++); // Closing Brace (}) + if (code === 0x007d) { // Must be at least 5 chars (\u{0}) and encode a Unicode scalar value. if (size < 5 || !isUnicodeScalarValue(point)) { @@ -29319,8 +28239,8 @@ function readEscapedUnicodeVariableWidth(lexer, position) { value: String.fromCodePoint(point), size }; - } - // Append this hex digit to the code point. + } // Append this hex digit to the code point. + point = point << 4 | readHexDigit(code); if (point < 0) { break; @@ -29336,9 +28256,9 @@ function readEscapedUnicodeFixedWidth(lexer, position) { value: String.fromCodePoint(code), size: 6 }; - } - // GraphQL allows JSON-style surrogate pair escape sequences, but only when + } // GraphQL allows JSON-style surrogate pair escape sequences, but only when // a valid pair is formed. + if (isLeadingSurrogate(code)) { // \u if (body.charCodeAt(position + 6) === 0x005c && body.charCodeAt(position + 7) === 0x0075) { @@ -29366,6 +28286,7 @@ function readEscapedUnicodeFixedWidth(lexer, position) { * * Returns a negative number if any char was not a valid hexadecimal digit. */ + function read16BitHexCode(body, position) { // readHexDigit() returns -1 on error. ORing a negative value with any other // value always produces a negative value. @@ -29385,6 +28306,7 @@ function read16BitHexCode(body, position) { * - `A` `B` `C` `D` `E` `F` * - `a` `b` `c` `d` `e` `f` */ + function readHexDigit(code) { return code >= 0x0030 && code <= 0x0039 // 0-9 ? code - 0x0030 : code >= 0x0041 && code <= 0x0046 // A-F @@ -29403,6 +28325,7 @@ function readHexDigit(code) { * | `r` | U+000D | carriage return | * | `t` | U+0009 | horizontal tab | */ + function readEscapedCharacter(lexer, position) { const body = lexer.source.body; const code = body.charCodeAt(position + 1); @@ -29470,6 +28393,7 @@ function readEscapedCharacter(lexer, position) { * - `\"""` * ``` */ + function readBlockString(lexer, start) { const body = lexer.source.body; const bodyLength = body.length; @@ -29479,8 +28403,8 @@ function readBlockString(lexer, start) { let currentLine = ''; const blockLines = []; while (position < bodyLength) { - const code = body.charCodeAt(position); - // Closing Triple-Quote (""") + const code = body.charCodeAt(position); // Closing Triple-Quote (""") + if (code === 0x0022 && body.charCodeAt(position + 1) === 0x0022 && body.charCodeAt(position + 2) === 0x0022) { currentLine += body.slice(chunkStart, position); blockLines.push(currentLine); @@ -29490,15 +28414,16 @@ function readBlockString(lexer, start) { lexer.line += blockLines.length - 1; lexer.lineStart = lineStart; return token; - } - // Escaped Triple-Quote (\""") + } // Escaped Triple-Quote (\""") + if (code === 0x005c && body.charCodeAt(position + 1) === 0x0022 && body.charCodeAt(position + 2) === 0x0022 && body.charCodeAt(position + 3) === 0x0022) { currentLine += body.slice(chunkStart, position); chunkStart = position + 1; // skip only slash + position += 4; continue; - } - // LineTerminator + } // LineTerminator + if (code === 0x000a || code === 0x000d) { currentLine += body.slice(chunkStart, position); blockLines.push(currentLine); @@ -29511,8 +28436,8 @@ function readBlockString(lexer, start) { chunkStart = position; lineStart = position; continue; - } - // SourceCharacter + } // SourceCharacter + if (isUnicodeScalarValue(code)) { ++position; } else if (isSupplementaryCodePoint(body, position)) { @@ -29531,6 +28456,7 @@ function readBlockString(lexer, start) { * - NameStart NameContinue* [lookahead != NameContinue] * ``` */ + function readName(lexer, start) { const body = lexer.source.body; const bodyLength = body.length; @@ -29562,6 +28488,10 @@ Object.defineProperty(exports, "__esModule", ({ exports.getLocation = getLocation; var _invariant = __webpack_require__(/*! ../jsutils/invariant.mjs */ "../../../node_modules/graphql/jsutils/invariant.mjs"); const LineRegExp = /\r\n|[\n\r]/g; +/** + * Represents a location in a Source. + */ + /** * Takes a Source and a UTF-8 character offset, and returns the corresponding * line and column as a SourceLocation. @@ -29608,6 +28538,10 @@ var _kinds = __webpack_require__(/*! ./kinds.mjs */ "../../../node_modules/graph var _lexer = __webpack_require__(/*! ./lexer.mjs */ "../../../node_modules/graphql/language/lexer.mjs"); var _source = __webpack_require__(/*! ./source.mjs */ "../../../node_modules/graphql/language/source.mjs"); var _tokenKind = __webpack_require__(/*! ./tokenKind.mjs */ "../../../node_modules/graphql/language/tokenKind.mjs"); +/** + * Configuration options to control parser behavior + */ + /** * Given a GraphQL source, parses it into a Document. * Throws GraphQLError if a syntax error is encountered. @@ -29626,6 +28560,7 @@ function parse(source, options) { * * Consider providing the results to the utility function: valueFromAST(). */ + function parseValue(source, options) { const parser = new Parser(source, options); parser.expectToken(_tokenKind.TokenKind.SOF); @@ -29637,6 +28572,7 @@ function parseValue(source, options) { * Similar to parseValue(), but raises a parse error if it encounters a * variable. The return type will be a constant value. */ + function parseConstValue(source, options) { const parser = new Parser(source, options); parser.expectToken(_tokenKind.TokenKind.SOF); @@ -29654,6 +28590,7 @@ function parseConstValue(source, options) { * * Consider providing the results to the utility function: typeFromAST(). */ + function parseType(source, options) { const parser = new Parser(source, options); parser.expectToken(_tokenKind.TokenKind.SOF); @@ -29672,6 +28609,7 @@ function parseType(source, options) { * * @internal */ + class Parser { constructor(source, options = {}) { const sourceObj = (0, _source.isSource)(source) ? source : new _source.Source(source); @@ -29682,17 +28620,19 @@ class Parser { /** * Converts a name lex token into a name parse node. */ + parseName() { const token = this.expectToken(_tokenKind.TokenKind.NAME); return this.node(token, { kind: _kinds.Kind.NAME, value: token.value }); - } - // Implements the parsing rules in the Document section. + } // Implements the parsing rules in the Document section. + /** * Document : Definition+ */ + parseDocument() { return this.node(this._lexer.token, { kind: _kinds.Kind.DOCUMENT, @@ -29722,11 +28662,12 @@ class Parser { * - EnumTypeDefinition * - InputObjectTypeDefinition */ + parseDefinition() { if (this.peek(_tokenKind.TokenKind.BRACE_L)) { return this.parseOperationDefinition(); - } - // Many definitions begin with a description and require a lookahead. + } // Many definitions begin with a description and require a lookahead. + const hasDescription = this.peekDescription(); const keywordToken = hasDescription ? this._lexer.lookahead() : this._lexer.token; if (keywordToken.kind === _tokenKind.TokenKind.NAME) { @@ -29763,13 +28704,14 @@ class Parser { } } throw this.unexpected(keywordToken); - } - // Implements the parsing rules in the Operations section. + } // Implements the parsing rules in the Operations section. + /** * OperationDefinition : * - SelectionSet * - OperationType Name? VariableDefinitions? Directives? SelectionSet */ + parseOperationDefinition() { const start = this._lexer.token; if (this.peek(_tokenKind.TokenKind.BRACE_L)) { @@ -29799,6 +28741,7 @@ class Parser { /** * OperationType : one of query mutation subscription */ + parseOperationType() { const operationToken = this.expectToken(_tokenKind.TokenKind.NAME); switch (operationToken.value) { @@ -29814,12 +28757,14 @@ class Parser { /** * VariableDefinitions : ( VariableDefinition+ ) */ + parseVariableDefinitions() { return this.optionalMany(_tokenKind.TokenKind.PAREN_L, this.parseVariableDefinition, _tokenKind.TokenKind.PAREN_R); } /** * VariableDefinition : Variable : Type DefaultValue? Directives[Const]? */ + parseVariableDefinition() { return this.node(this._lexer.token, { kind: _kinds.Kind.VARIABLE_DEFINITION, @@ -29832,6 +28777,7 @@ class Parser { /** * Variable : $ Name */ + parseVariable() { const start = this._lexer.token; this.expectToken(_tokenKind.TokenKind.DOLLAR); @@ -29845,6 +28791,7 @@ class Parser { * SelectionSet : { Selection+ } * ``` */ + parseSelectionSet() { return this.node(this._lexer.token, { kind: _kinds.Kind.SELECTION_SET, @@ -29857,6 +28804,7 @@ class Parser { * - FragmentSpread * - InlineFragment */ + parseSelection() { return this.peek(_tokenKind.TokenKind.SPREAD) ? this.parseFragment() : this.parseField(); } @@ -29865,6 +28813,7 @@ class Parser { * * Alias : Name : */ + parseField() { const start = this._lexer.token; const nameOrAlias = this.parseName(); @@ -29881,47 +28830,22 @@ class Parser { alias, name, arguments: this.parseArguments(false), - // Experimental support for Client Controlled Nullability changes - // the grammar of Field: - nullabilityAssertion: this.parseNullabilityAssertion(), directives: this.parseDirectives(false), selectionSet: this.peek(_tokenKind.TokenKind.BRACE_L) ? this.parseSelectionSet() : undefined }); } - // TODO: add grammar comment after it finalizes - parseNullabilityAssertion() { - // Note: Client Controlled Nullability is experimental and may be changed or - // removed in the future. - if (this._options.experimentalClientControlledNullability !== true) { - return undefined; - } - const start = this._lexer.token; - let nullabilityAssertion; - if (this.expectOptionalToken(_tokenKind.TokenKind.BRACKET_L)) { - const innerModifier = this.parseNullabilityAssertion(); - this.expectToken(_tokenKind.TokenKind.BRACKET_R); - nullabilityAssertion = this.node(start, { - kind: _kinds.Kind.LIST_NULLABILITY_OPERATOR, - nullabilityAssertion: innerModifier - }); - } - if (this.expectOptionalToken(_tokenKind.TokenKind.BANG)) { - nullabilityAssertion = this.node(start, { - kind: _kinds.Kind.NON_NULL_ASSERTION, - nullabilityAssertion - }); - } else if (this.expectOptionalToken(_tokenKind.TokenKind.QUESTION_MARK)) { - nullabilityAssertion = this.node(start, { - kind: _kinds.Kind.ERROR_BOUNDARY, - nullabilityAssertion - }); - } - return nullabilityAssertion; - } + /** + * Arguments[Const] : ( Argument[?Const]+ ) + */ + parseArguments(isConst) { const item = isConst ? this.parseConstArgument : this.parseArgument; return this.optionalMany(_tokenKind.TokenKind.PAREN_L, item, _tokenKind.TokenKind.PAREN_R); } + /** + * Argument[Const] : Name : Value[?Const] + */ + parseArgument(isConst = false) { const start = this._lexer.token; const name = this.parseName(); @@ -29934,8 +28858,8 @@ class Parser { } parseConstArgument() { return this.parseArgument(true); - } - // Implements the parsing rules in the Fragments section. + } // Implements the parsing rules in the Fragments section. + /** * Corresponds to both FragmentSpread and InlineFragment in the spec. * @@ -29943,6 +28867,7 @@ class Parser { * * InlineFragment : ... TypeCondition? Directives? SelectionSet */ + parseFragment() { const start = this._lexer.token; this.expectToken(_tokenKind.TokenKind.SPREAD); @@ -29967,12 +28892,13 @@ class Parser { * * TypeCondition : NamedType */ + parseFragmentDefinition() { const start = this._lexer.token; - this.expectKeyword('fragment'); - // Legacy support for defining variables within fragments changes + this.expectKeyword('fragment'); // Legacy support for defining variables within fragments changes // the grammar of FragmentDefinition: // - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet + if (this._options.allowLegacyFragmentVariables === true) { return this.node(start, { kind: _kinds.Kind.FRAGMENT_DEFINITION, @@ -29994,12 +28920,33 @@ class Parser { /** * FragmentName : Name but not `on` */ + parseFragmentName() { if (this._lexer.token.value === 'on') { throw this.unexpected(); } return this.parseName(); - } + } // Implements the parsing rules in the Values section. + + /** + * Value[Const] : + * - [~Const] Variable + * - IntValue + * - FloatValue + * - StringValue + * - BooleanValue + * - NullValue + * - EnumValue + * - ListValue[?Const] + * - ObjectValue[?Const] + * + * BooleanValue : one of `true` `false` + * + * NullValue : `null` + * + * EnumValue : Name but not `true`, `false` or `null` + */ + parseValueLiteral(isConst) { const token = this._lexer.token; switch (token.kind) { @@ -30072,6 +29019,12 @@ class Parser { block: token.kind === _tokenKind.TokenKind.BLOCK_STRING }); } + /** + * ListValue[Const] : + * - [ ] + * - [ Value[?Const]+ ] + */ + parseList(isConst) { const item = () => this.parseValueLiteral(isConst); return this.node(this._lexer.token, { @@ -30079,6 +29032,14 @@ class Parser { values: this.any(_tokenKind.TokenKind.BRACKET_L, item, _tokenKind.TokenKind.BRACKET_R) }); } + /** + * ``` + * ObjectValue[Const] : + * - { } + * - { ObjectField[?Const]+ } + * ``` + */ + parseObject(isConst) { const item = () => this.parseObjectField(isConst); return this.node(this._lexer.token, { @@ -30086,6 +29047,10 @@ class Parser { fields: this.any(_tokenKind.TokenKind.BRACE_L, item, _tokenKind.TokenKind.BRACE_R) }); } + /** + * ObjectField[Const] : Name : Value[?Const] + */ + parseObjectField(isConst) { const start = this._lexer.token; const name = this.parseName(); @@ -30095,7 +29060,12 @@ class Parser { name, value: this.parseValueLiteral(isConst) }); - } + } // Implements the parsing rules in the Directives section. + + /** + * Directives[Const] : Directive[?Const]+ + */ + parseDirectives(isConst) { const directives = []; while (this.peek(_tokenKind.TokenKind.AT)) { @@ -30106,6 +29076,12 @@ class Parser { parseConstDirectives() { return this.parseDirectives(true); } + /** + * ``` + * Directive[Const] : @ Name Arguments[?Const]? + * ``` + */ + parseDirective(isConst) { const start = this._lexer.token; this.expectToken(_tokenKind.TokenKind.AT); @@ -30114,14 +29090,15 @@ class Parser { name: this.parseName(), arguments: this.parseArguments(isConst) }); - } - // Implements the parsing rules in the Types section. + } // Implements the parsing rules in the Types section. + /** * Type : * - NamedType * - ListType * - NonNullType */ + parseTypeReference() { const start = this._lexer.token; let type; @@ -30146,19 +29123,21 @@ class Parser { /** * NamedType : Name */ + parseNamedType() { return this.node(this._lexer.token, { kind: _kinds.Kind.NAMED_TYPE, name: this.parseName() }); - } - // Implements the parsing rules in the Type Definition section. + } // Implements the parsing rules in the Type Definition section. + peekDescription() { return this.peek(_tokenKind.TokenKind.STRING) || this.peek(_tokenKind.TokenKind.BLOCK_STRING); } /** * Description : StringValue */ + parseDescription() { if (this.peekDescription()) { return this.parseStringLiteral(); @@ -30169,6 +29148,7 @@ class Parser { * SchemaDefinition : Description? schema Directives[Const]? { OperationTypeDefinition+ } * ``` */ + parseSchemaDefinition() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30185,6 +29165,7 @@ class Parser { /** * OperationTypeDefinition : OperationType : NamedType */ + parseOperationTypeDefinition() { const start = this._lexer.token; const operation = this.parseOperationType(); @@ -30199,6 +29180,7 @@ class Parser { /** * ScalarTypeDefinition : Description? scalar Name Directives[Const]? */ + parseScalarTypeDefinition() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30217,6 +29199,7 @@ class Parser { * Description? * type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition? */ + parseObjectTypeDefinition() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30239,6 +29222,7 @@ class Parser { * - implements `&`? NamedType * - ImplementsInterfaces & NamedType */ + parseImplementsInterfaces() { return this.expectOptionalKeyword('implements') ? this.delimitedMany(_tokenKind.TokenKind.AMP, this.parseNamedType) : []; } @@ -30247,6 +29231,7 @@ class Parser { * FieldsDefinition : { FieldDefinition+ } * ``` */ + parseFieldsDefinition() { return this.optionalMany(_tokenKind.TokenKind.BRACE_L, this.parseFieldDefinition, _tokenKind.TokenKind.BRACE_R); } @@ -30254,6 +29239,7 @@ class Parser { * FieldDefinition : * - Description? Name ArgumentsDefinition? : Type Directives[Const]? */ + parseFieldDefinition() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30274,6 +29260,7 @@ class Parser { /** * ArgumentsDefinition : ( InputValueDefinition+ ) */ + parseArgumentDefs() { return this.optionalMany(_tokenKind.TokenKind.PAREN_L, this.parseInputValueDef, _tokenKind.TokenKind.PAREN_R); } @@ -30281,6 +29268,7 @@ class Parser { * InputValueDefinition : * - Description? Name : Type DefaultValue? Directives[Const]? */ + parseInputValueDef() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30305,6 +29293,7 @@ class Parser { * InterfaceTypeDefinition : * - Description? interface Name Directives[Const]? FieldsDefinition? */ + parseInterfaceTypeDefinition() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30326,6 +29315,7 @@ class Parser { * UnionTypeDefinition : * - Description? union Name Directives[Const]? UnionMemberTypes? */ + parseUnionTypeDefinition() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30346,6 +29336,7 @@ class Parser { * - = `|`? NamedType * - UnionMemberTypes | NamedType */ + parseUnionMemberTypes() { return this.expectOptionalToken(_tokenKind.TokenKind.EQUALS) ? this.delimitedMany(_tokenKind.TokenKind.PIPE, this.parseNamedType) : []; } @@ -30353,6 +29344,7 @@ class Parser { * EnumTypeDefinition : * - Description? enum Name Directives[Const]? EnumValuesDefinition? */ + parseEnumTypeDefinition() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30373,12 +29365,14 @@ class Parser { * EnumValuesDefinition : { EnumValueDefinition+ } * ``` */ + parseEnumValuesDefinition() { return this.optionalMany(_tokenKind.TokenKind.BRACE_L, this.parseEnumValueDefinition, _tokenKind.TokenKind.BRACE_R); } /** * EnumValueDefinition : Description? EnumValue Directives[Const]? */ + parseEnumValueDefinition() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30394,6 +29388,7 @@ class Parser { /** * EnumValue : Name but not `true`, `false` or `null` */ + parseEnumValueName() { if (this._lexer.token.value === 'true' || this._lexer.token.value === 'false' || this._lexer.token.value === 'null') { throw (0, _syntaxError.syntaxError)(this._lexer.source, this._lexer.token.start, `${getTokenDesc(this._lexer.token)} is reserved and cannot be used for an enum value.`); @@ -30404,6 +29399,7 @@ class Parser { * InputObjectTypeDefinition : * - Description? input Name Directives[Const]? InputFieldsDefinition? */ + parseInputObjectTypeDefinition() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30424,6 +29420,7 @@ class Parser { * InputFieldsDefinition : { InputValueDefinition+ } * ``` */ + parseInputFieldsDefinition() { return this.optionalMany(_tokenKind.TokenKind.BRACE_L, this.parseInputValueDef, _tokenKind.TokenKind.BRACE_R); } @@ -30440,6 +29437,7 @@ class Parser { * - EnumTypeExtension * - InputObjectTypeDefinition */ + parseTypeSystemExtension() { const keywordToken = this._lexer.lookahead(); if (keywordToken.kind === _tokenKind.TokenKind.NAME) { @@ -30469,6 +29467,7 @@ class Parser { * - extend schema Directives[Const] * ``` */ + parseSchemaExtension() { const start = this._lexer.token; this.expectKeyword('extend'); @@ -30488,6 +29487,7 @@ class Parser { * ScalarTypeExtension : * - extend scalar Name Directives[Const] */ + parseScalarTypeExtension() { const start = this._lexer.token; this.expectKeyword('extend'); @@ -30509,6 +29509,7 @@ class Parser { * - extend type Name ImplementsInterfaces? Directives[Const] * - extend type Name ImplementsInterfaces */ + parseObjectTypeExtension() { const start = this._lexer.token; this.expectKeyword('extend'); @@ -30534,6 +29535,7 @@ class Parser { * - extend interface Name ImplementsInterfaces? Directives[Const] * - extend interface Name ImplementsInterfaces */ + parseInterfaceTypeExtension() { const start = this._lexer.token; this.expectKeyword('extend'); @@ -30558,6 +29560,7 @@ class Parser { * - extend union Name Directives[Const]? UnionMemberTypes * - extend union Name Directives[Const] */ + parseUnionTypeExtension() { const start = this._lexer.token; this.expectKeyword('extend'); @@ -30580,6 +29583,7 @@ class Parser { * - extend enum Name Directives[Const]? EnumValuesDefinition * - extend enum Name Directives[Const] */ + parseEnumTypeExtension() { const start = this._lexer.token; this.expectKeyword('extend'); @@ -30602,6 +29606,7 @@ class Parser { * - extend input Name Directives[Const]? InputFieldsDefinition * - extend input Name Directives[Const] */ + parseInputObjectTypeExtension() { const start = this._lexer.token; this.expectKeyword('extend'); @@ -30625,6 +29630,7 @@ class Parser { * - Description? directive @ Name ArgumentsDefinition? `repeatable`? on DirectiveLocations * ``` */ + parseDirectiveDefinition() { const start = this._lexer.token; const description = this.parseDescription(); @@ -30649,6 +29655,7 @@ class Parser { * - `|`? DirectiveLocation * - DirectiveLocations | DirectiveLocation */ + parseDirectiveLocations() { return this.delimitedMany(_tokenKind.TokenKind.PIPE, this.parseDirectiveLocation); } @@ -30679,20 +29686,22 @@ class Parser { * `INPUT_OBJECT` * `INPUT_FIELD_DEFINITION` */ + parseDirectiveLocation() { const start = this._lexer.token; const name = this.parseName(); - if (Object.hasOwn(_directiveLocation.DirectiveLocation, name.value)) { + if (Object.prototype.hasOwnProperty.call(_directiveLocation.DirectiveLocation, name.value)) { return name; } throw this.unexpected(start); - } - // Core parsing utility functions + } // Core parsing utility functions + /** * Returns a node that, if configured to do so, sets a "loc" field as a * location object, used to identify the place in the source that created a * given parsed object. */ + node(startToken, node) { if (this._options.noLocation !== true) { node.loc = new _ast.Location(startToken, this._lexer.lastToken, this._lexer.source); @@ -30702,6 +29711,7 @@ class Parser { /** * Determines if the next token is of a given kind */ + peek(kind) { return this._lexer.token.kind === kind; } @@ -30709,6 +29719,7 @@ class Parser { * If the next token is of the given kind, return that token after advancing the lexer. * Otherwise, do not change the parser state and throw an error. */ + expectToken(kind) { const token = this._lexer.token; if (token.kind === kind) { @@ -30721,6 +29732,7 @@ class Parser { * If the next token is of the given kind, return "true" after advancing the lexer. * Otherwise, do not change the parser state and return "false". */ + expectOptionalToken(kind) { const token = this._lexer.token; if (token.kind === kind) { @@ -30733,6 +29745,7 @@ class Parser { * If the next token is a given keyword, advance the lexer. * Otherwise, do not change the parser state and throw an error. */ + expectKeyword(value) { const token = this._lexer.token; if (token.kind === _tokenKind.TokenKind.NAME && token.value === value) { @@ -30745,6 +29758,7 @@ class Parser { * If the next token is a given keyword, return "true" after advancing the lexer. * Otherwise, do not change the parser state and return "false". */ + expectOptionalKeyword(value) { const token = this._lexer.token; if (token.kind === _tokenKind.TokenKind.NAME && token.value === value) { @@ -30756,6 +29770,7 @@ class Parser { /** * Helper function for creating an error when an unexpected lexed token is encountered. */ + unexpected(atToken) { const token = atToken !== null && atToken !== void 0 ? atToken : this._lexer.token; return (0, _syntaxError.syntaxError)(this._lexer.source, token.start, `Unexpected ${getTokenDesc(token)}.`); @@ -30765,6 +29780,7 @@ class Parser { * This list begins with a lex token of openKind and ends with a lex token of closeKind. * Advances the parser to the next lex token after the closing token. */ + any(openKind, parseFn, closeKind) { this.expectToken(openKind); const nodes = []; @@ -30779,6 +29795,7 @@ class Parser { * that begins with a lex token of openKind and ends with a lex token of closeKind. * Advances the parser to the next lex token after the closing token. */ + optionalMany(openKind, parseFn, closeKind) { if (this.expectOptionalToken(openKind)) { const nodes = []; @@ -30794,6 +29811,7 @@ class Parser { * This list begins with a lex token of openKind and ends with a lex token of closeKind. * Advances the parser to the next lex token after the closing token. */ + many(openKind, parseFn, closeKind) { this.expectToken(openKind); const nodes = []; @@ -30807,6 +29825,7 @@ class Parser { * This list may begin with a lex token of delimiterKind followed by items separated by lex tokens of tokenKind. * Advances the parser to the next lex token after last item in the list. */ + delimitedMany(delimiterKind, parseFn) { this.expectOptionalToken(delimiterKind); const nodes = []; @@ -30823,7 +29842,7 @@ class Parser { if (maxTokens !== undefined && token.kind !== _tokenKind.TokenKind.EOF) { ++this._tokenCounter; if (this._tokenCounter > maxTokens) { - throw (0, _syntaxError.syntaxError)(this._lexer.source, token.start, `Document contains more than ${maxTokens} tokens. Parsing aborted.`); + throw (0, _syntaxError.syntaxError)(this._lexer.source, token.start, `Document contains more that ${maxTokens} tokens. Parsing aborted.`); } } } @@ -30839,6 +29858,7 @@ function getTokenDesc(token) { /** * A helper function to describe a token kind as a string for debugging. */ + function getTokenKindDesc(kind) { return (0, _lexer.isPunctuatorTokenKind)(kind) ? `"${kind}"` : kind; } @@ -30859,7 +29879,6 @@ Object.defineProperty(exports, "__esModule", ({ exports.isConstValueNode = isConstValueNode; exports.isDefinitionNode = isDefinitionNode; exports.isExecutableDefinitionNode = isExecutableDefinitionNode; -exports.isNullabilityAssertionNode = isNullabilityAssertionNode; exports.isSelectionNode = isSelectionNode; exports.isTypeDefinitionNode = isTypeDefinitionNode; exports.isTypeExtensionNode = isTypeExtensionNode; @@ -30877,9 +29896,6 @@ function isExecutableDefinitionNode(node) { function isSelectionNode(node) { return node.kind === _kinds.Kind.FIELD || node.kind === _kinds.Kind.FRAGMENT_SPREAD || node.kind === _kinds.Kind.INLINE_FRAGMENT; } -function isNullabilityAssertionNode(node) { - return node.kind === _kinds.Kind.LIST_NULLABILITY_OPERATOR || node.kind === _kinds.Kind.NON_NULL_ASSERTION || node.kind === _kinds.Kind.ERROR_BOUNDARY; -} function isValueNode(node) { return node.kind === _kinds.Kind.VARIABLE || node.kind === _kinds.Kind.INT || node.kind === _kinds.Kind.FLOAT || node.kind === _kinds.Kind.STRING || node.kind === _kinds.Kind.BOOLEAN || node.kind === _kinds.Kind.NULL || node.kind === _kinds.Kind.ENUM || node.kind === _kinds.Kind.LIST || node.kind === _kinds.Kind.OBJECT; } @@ -30927,6 +29943,7 @@ function printLocation(location) { /** * Render a helpful description of the location in the GraphQL Source document. */ + function printSourceLocation(source, sourceLocation) { const firstLineColumnOffset = source.locationOffset.column - 1; const body = ''.padStart(firstLineColumnOffset) + source.body; @@ -30937,8 +29954,8 @@ function printSourceLocation(source, sourceLocation) { const columnNum = sourceLocation.column + columnOffset; const locationStr = `${source.name}:${lineNum}:${columnNum}\n`; const lines = body.split(/\r\n|[\n\r]/g); - const locationLine = lines[lineIndex]; - // Special case for minified documents + const locationLine = lines[lineIndex]; // Special case for minified documents + if (locationLine.length > 120) { const subLineIndex = Math.floor(columnNum / 80); const subLineColumnNum = columnNum % 80; @@ -30978,14 +29995,24 @@ exports.printString = printString; */ function printString(str) { return `"${str.replace(escapedRegExp, escapedReplacer)}"`; -} -// eslint-disable-next-line no-control-regex +} // eslint-disable-next-line no-control-regex + const escapedRegExp = /[\x00-\x1f\x22\x5c\x7f-\x9f]/g; function escapedReplacer(str) { return escapeSequences[str.charCodeAt(0)]; -} -// prettier-ignore -const escapeSequences = ['\\u0000', '\\u0001', '\\u0002', '\\u0003', '\\u0004', '\\u0005', '\\u0006', '\\u0007', '\\b', '\\t', '\\n', '\\u000B', '\\f', '\\r', '\\u000E', '\\u000F', '\\u0010', '\\u0011', '\\u0012', '\\u0013', '\\u0014', '\\u0015', '\\u0016', '\\u0017', '\\u0018', '\\u0019', '\\u001A', '\\u001B', '\\u001C', '\\u001D', '\\u001E', '\\u001F', '', '', '\\"', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '\\\\', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '\\u007F', '\\u0080', '\\u0081', '\\u0082', '\\u0083', '\\u0084', '\\u0085', '\\u0086', '\\u0087', '\\u0088', '\\u0089', '\\u008A', '\\u008B', '\\u008C', '\\u008D', '\\u008E', '\\u008F', '\\u0090', '\\u0091', '\\u0092', '\\u0093', '\\u0094', '\\u0095', '\\u0096', '\\u0097', '\\u0098', '\\u0099', '\\u009A', '\\u009B', '\\u009C', '\\u009D', '\\u009E', '\\u009F']; +} // prettier-ignore + +const escapeSequences = ['\\u0000', '\\u0001', '\\u0002', '\\u0003', '\\u0004', '\\u0005', '\\u0006', '\\u0007', '\\b', '\\t', '\\n', '\\u000B', '\\f', '\\r', '\\u000E', '\\u000F', '\\u0010', '\\u0011', '\\u0012', '\\u0013', '\\u0014', '\\u0015', '\\u0016', '\\u0017', '\\u0018', '\\u0019', '\\u001A', '\\u001B', '\\u001C', '\\u001D', '\\u001E', '\\u001F', '', '', '\\"', '', '', '', '', '', '', '', '', '', '', '', '', '', +// 2F +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +// 3F +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +// 4F +'', '', '', '', '', '', '', '', '', '', '', '', '\\\\', '', '', '', +// 5F +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', +// 6F +'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '\\u007F', '\\u0080', '\\u0081', '\\u0082', '\\u0083', '\\u0084', '\\u0085', '\\u0086', '\\u0087', '\\u0088', '\\u0089', '\\u008A', '\\u008B', '\\u008C', '\\u008D', '\\u008E', '\\u008F', '\\u0090', '\\u0091', '\\u0092', '\\u0093', '\\u0094', '\\u0095', '\\u0096', '\\u0097', '\\u0098', '\\u0099', '\\u009A', '\\u009B', '\\u009C', '\\u009D', '\\u009E', '\\u009F']; /***/ }), @@ -31008,6 +30035,7 @@ var _visitor = __webpack_require__(/*! ./visitor.mjs */ "../../../node_modules/g * Converts an AST into a string, using one set of reasonable * formatting rules. */ + function print(ast) { return (0, _visitor.visit)(ast, printDocASTReducer); } @@ -31026,9 +30054,9 @@ const printDocASTReducer = { OperationDefinition: { leave(node) { const varDefs = wrap('(', join(node.variableDefinitions, ', '), ')'); - const prefix = join([node.operation, join([node.name, varDefs]), join(node.directives, ' ')], ' '); - // Anonymous queries with no directives or variable definitions can use + const prefix = join([node.operation, join([node.name, varDefs]), join(node.directives, ' ')], ' '); // Anonymous queries with no directives or variable definitions can use // the query short form. + return (prefix === 'query' ? '' : prefix + ' ') + node.selectionSet; } }, @@ -31050,19 +30078,15 @@ const printDocASTReducer = { alias, name, arguments: args, - nullabilityAssertion, directives, selectionSet }) { - const prefix = join([wrap('', alias, ': '), name], ''); + const prefix = wrap('', alias, ': ') + name; let argsLine = prefix + wrap('(', join(args, ', '), ')'); if (argsLine.length > MAX_LINE_LENGTH) { argsLine = prefix + wrap('(\n', indent(join(args, '\n')), '\n)'); } - return join([argsLine, - // Note: Client Controlled Nullability is experimental and may be - // changed or removed in the future. - nullabilityAssertion, wrap(' ', join(directives, ' ')), wrap(' ', selectionSet)]); + return join([argsLine, join(directives, ' '), selectionSet], ' '); } }, Argument: { @@ -31071,28 +30095,6 @@ const printDocASTReducer = { value }) => name + ': ' + value }, - // Nullability Modifiers - ListNullabilityOperator: { - leave({ - nullabilityAssertion - }) { - return join(['[', nullabilityAssertion, ']']); - } - }, - NonNullAssertion: { - leave({ - nullabilityAssertion - }) { - return join([nullabilityAssertion, '!']); - } - }, - ErrorBoundary: { - leave({ - nullabilityAssertion - }) { - return join([nullabilityAssertion, '?']); - } - }, // Fragments FragmentSpread: { leave: ({ @@ -31114,8 +30116,8 @@ const printDocASTReducer = { variableDefinitions, directives, selectionSet - }) => - // Note: fragment variable definitions are experimental and may be changed + } // Note: fragment variable definitions are experimental and may be changed + ) => // or removed in the future. `fragment ${name}${wrap('(', join(variableDefinitions, ', '), ')')} ` + `on ${typeCondition} ${wrap('', join(directives, ' '), ' ')}` + selectionSet }, @@ -31134,7 +30136,7 @@ const printDocASTReducer = { leave: ({ value, block: isBlockString - }) => isBlockString === true ? (0, _blockString.printBlockString)(value) : (0, _printString.printString)(value) + }) => isBlockString ? (0, _blockString.printBlockString)(value) : (0, _printString.printString)(value) }, BooleanValue: { leave: ({ @@ -31152,21 +30154,12 @@ const printDocASTReducer = { ListValue: { leave: ({ values - }) => { - const valuesLine = '[' + join(values, ', ') + ']'; - if (valuesLine.length > MAX_LINE_LENGTH) { - return '[\n' + indent(join(values, '\n')) + '\n]'; - } - return valuesLine; - } + }) => '[' + join(values, ', ') + ']' }, ObjectValue: { leave: ({ fields - }) => { - const fieldsLine = '{ ' + join(fields, ', ') + ' }'; - return fieldsLine.length > MAX_LINE_LENGTH ? block(fields) : fieldsLine; - } + }) => '{' + join(fields, ', ') + '}' }, ObjectField: { leave: ({ @@ -31348,6 +30341,7 @@ const printDocASTReducer = { * Given maybeArray, print an empty string if it is null or empty, otherwise * print all items together separated by separator if provided */ + function join(maybeArray, separator = '') { var _maybeArray$filter$jo; return (_maybeArray$filter$jo = maybeArray === null || maybeArray === void 0 ? void 0 : maybeArray.filter(x => x).join(separator)) !== null && _maybeArray$filter$jo !== void 0 ? _maybeArray$filter$jo : ''; @@ -31355,21 +30349,25 @@ function join(maybeArray, separator = '') { /** * Given array, print each item on its own line, wrapped in an indented `{ }` block. */ + function block(array) { return wrap('{\n', indent(join(array, '\n')), '\n}'); } /** * If maybeString is not null or empty, then wrap with start and end, otherwise print an empty string. */ + function wrap(start, maybeString, end = '') { return maybeString != null && maybeString !== '' ? start + maybeString + end : ''; } function indent(str) { - return wrap(' ', str.replaceAll('\n', '\n ')); + return wrap(' ', str.replace(/\n/g, '\n ')); } function hasMultilineItems(maybeArray) { var _maybeArray$some; + // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ return (_maybeArray$some = maybeArray === null || maybeArray === void 0 ? void 0 : maybeArray.some(str => str.includes('\n'))) !== null && _maybeArray$some !== void 0 ? _maybeArray$some : false; } @@ -31390,6 +30388,7 @@ Object.defineProperty(exports, "__esModule", ({ exports.Source = void 0; exports.isSource = isSource; var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); +var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); var _instanceOf = __webpack_require__(/*! ../jsutils/instanceOf.mjs */ "../../../node_modules/graphql/jsutils/instanceOf.mjs"); /** * A representation of source input to GraphQL. The `name` and `locationOffset` parameters are @@ -31403,6 +30402,7 @@ class Source { line: 1, column: 1 }) { + typeof body === 'string' || (0, _devAssert.devAssert)(false, `Body must be a string. Received: ${(0, _inspect.inspect)(body)}.`); this.body = body; this.name = name; this.locationOffset = locationOffset; @@ -31446,7 +30446,6 @@ var TokenKind; TokenKind['SOF'] = ''; TokenKind['EOF'] = ''; TokenKind['BANG'] = '!'; - TokenKind['QUESTION_MARK'] = '?'; TokenKind['DOLLAR'] = '$'; TokenKind['AMP'] = '&'; TokenKind['PAREN_L'] = '('; @@ -31468,6 +30467,12 @@ var TokenKind; TokenKind['COMMENT'] = 'Comment'; })(TokenKind || (exports.TokenKind = TokenKind = {})); +/** + * The enum type representing the token kinds values. + * + * @deprecated Please use `TokenKind`. Will be remove in v17. + */ + /***/ }), /***/ "../../../node_modules/graphql/language/visitor.mjs": @@ -31483,19 +30488,105 @@ Object.defineProperty(exports, "__esModule", ({ })); exports.BREAK = void 0; exports.getEnterLeaveForKind = getEnterLeaveForKind; +exports.getVisitFn = getVisitFn; exports.visit = visit; exports.visitInParallel = visitInParallel; var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); var _ast = __webpack_require__(/*! ./ast.mjs */ "../../../node_modules/graphql/language/ast.mjs"); var _kinds = __webpack_require__(/*! ./kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); +/** + * A visitor is provided to visit, it contains the collection of + * relevant functions to be called during the visitor's traversal. + */ + const BREAK = exports.BREAK = Object.freeze({}); +/** + * visit() will walk through an AST using a depth-first traversal, calling + * the visitor's enter function at each node in the traversal, and calling the + * leave function after visiting that node and all of its child nodes. + * + * By returning different values from the enter and leave functions, the + * behavior of the visitor can be altered, including skipping over a sub-tree of + * the AST (by returning false), editing the AST by returning a value or null + * to remove the value, or to stop the whole traversal by returning BREAK. + * + * When using visit() to edit an AST, the original AST will not be modified, and + * a new version of the AST with the changes applied will be returned from the + * visit function. + * + * ```ts + * const editedAST = visit(ast, { + * enter(node, key, parent, path, ancestors) { + * // @return + * // undefined: no action + * // false: skip visiting this node + * // visitor.BREAK: stop visiting altogether + * // null: delete this node + * // any value: replace this node with the returned value + * }, + * leave(node, key, parent, path, ancestors) { + * // @return + * // undefined: no action + * // false: no action + * // visitor.BREAK: stop visiting altogether + * // null: delete this node + * // any value: replace this node with the returned value + * } + * }); + * ``` + * + * Alternatively to providing enter() and leave() functions, a visitor can + * instead provide functions named the same as the kinds of AST nodes, or + * enter/leave visitors at a named key, leading to three permutations of the + * visitor API: + * + * 1) Named visitors triggered when entering a node of a specific kind. + * + * ```ts + * visit(ast, { + * Kind(node) { + * // enter the "Kind" node + * } + * }) + * ``` + * + * 2) Named visitors that trigger upon entering and leaving a node of a specific kind. + * + * ```ts + * visit(ast, { + * Kind: { + * enter(node) { + * // enter the "Kind" node + * } + * leave(node) { + * // leave the "Kind" node + * } + * } + * }) + * ``` + * + * 3) Generic visitors that trigger upon entering and leaving any node. + * + * ```ts + * visit(ast, { + * enter(node) { + * // enter any node + * }, + * leave(node) { + * // leave any node + * } + * }) + * ``` + */ + function visit(root, visitor, visitorKeys = _ast.QueryDocumentKeys) { const enterLeaveMap = new Map(); for (const kind of Object.values(_kinds.Kind)) { enterLeaveMap.set(kind, getEnterLeaveForKind(visitor, kind)); } /* eslint-disable no-undef-init */ + let stack = undefined; let inArray = Array.isArray(root); let keys = [root]; @@ -31507,6 +30598,7 @@ function visit(root, visitor, visitorKeys = _ast.QueryDocumentKeys) { const path = []; const ancestors = []; /* eslint-enable no-undef-init */ + do { index++; const isLeaving = index === keys.length; @@ -31540,7 +30632,7 @@ function visit(root, visitor, visitorKeys = _ast.QueryDocumentKeys) { edits = stack.edits; inArray = stack.inArray; stack = stack.prev; - } else if (parent != null) { + } else if (parent) { key = inArray ? index : keys[index]; node = parent[key]; if (node === null || node === undefined) { @@ -31580,7 +30672,7 @@ function visit(root, visitor, visitorKeys = _ast.QueryDocumentKeys) { if (isLeaving) { path.pop(); } else { - var _visitorKeys$node$kin; + var _node$kind; stack = { inArray, index, @@ -31589,10 +30681,10 @@ function visit(root, visitor, visitorKeys = _ast.QueryDocumentKeys) { prev: stack }; inArray = Array.isArray(node); - keys = inArray ? node : (_visitorKeys$node$kin = visitorKeys[node.kind]) !== null && _visitorKeys$node$kin !== void 0 ? _visitorKeys$node$kin : []; + keys = inArray ? node : (_node$kind = visitorKeys[node.kind]) !== null && _node$kind !== void 0 ? _node$kind : []; index = -1; edits = []; - if (parent != null) { + if (parent) { ancestors.push(parent); } parent = node; @@ -31600,7 +30692,7 @@ function visit(root, visitor, visitorKeys = _ast.QueryDocumentKeys) { } while (stack !== undefined); if (edits.length !== 0) { // New root - return edits.at(-1)[1]; + return edits[edits.length - 1][1]; } return root; } @@ -31610,6 +30702,7 @@ function visit(root, visitor, visitorKeys = _ast.QueryDocumentKeys) { * * If a prior visitor edits a node, no following visitors will see that node. */ + function visitInParallel(visitors) { const skipping = new Array(visitors.length).fill(null); const mergedVisitor = Object.create(null); @@ -31622,7 +30715,7 @@ function visitInParallel(visitors) { enter, leave } = getEnterLeaveForKind(visitors[i], kind); - hasVisitor ||= enter != null || leave != null; + hasVisitor || (hasVisitor = enter != null || leave != null); enterList[i] = enter; leaveList[i] = leave; } @@ -31670,6 +30763,7 @@ function visitInParallel(visitors) { /** * Given a visitor instance and a node kind, return EnterLeaveVisitor for that kind. */ + function getEnterLeaveForKind(visitor, kind) { const kindVisitor = visitor[kind]; if (typeof kindVisitor === 'object') { @@ -31681,13 +30775,29 @@ function getEnterLeaveForKind(visitor, kind) { enter: kindVisitor, leave: undefined }; - } - // { enter() {}, leave() {} } + } // { enter() {}, leave() {} } + return { enter: visitor.enter, leave: visitor.leave }; } +/** + * Given a visitor instance, if it is leaving or not, and a node kind, return + * the function the visitor runtime should call. + * + * @deprecated Please use `getEnterLeaveForKind` instead. Will be removed in v17 + */ + +/* c8 ignore next 8 */ + +function getVisitFn(visitor, kind, isLeaving) { + const { + enter, + leave + } = getEnterLeaveForKind(visitor, kind); + return isLeaving ? leave : enter; +} /***/ }), @@ -31704,12 +30814,16 @@ Object.defineProperty(exports, "__esModule", ({ })); exports.assertEnumValueName = assertEnumValueName; exports.assertName = assertName; +var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); var _GraphQLError = __webpack_require__(/*! ../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); var _characterClasses = __webpack_require__(/*! ../language/characterClasses.mjs */ "../../../node_modules/graphql/language/characterClasses.mjs"); /** * Upholds the spec rules about naming. */ + function assertName(name) { + name != null || (0, _devAssert.devAssert)(false, 'Must provide name.'); + typeof name === 'string' || (0, _devAssert.devAssert)(false, 'Expected name to be a string.'); if (name.length === 0) { throw new _GraphQLError.GraphQLError('Expected name to be a non-empty string.'); } @@ -31728,6 +30842,7 @@ function assertName(name) { * * @internal */ + function assertEnumValueName(name) { if (name === 'true' || name === 'false' || name === 'null') { throw new _GraphQLError.GraphQLError(`Enum values cannot be named: ${name}`); @@ -31796,6 +30911,7 @@ var _didYouMean = __webpack_require__(/*! ../jsutils/didYouMean.mjs */ "../../.. var _identityFunc = __webpack_require__(/*! ../jsutils/identityFunc.mjs */ "../../../node_modules/graphql/jsutils/identityFunc.mjs"); var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); var _instanceOf = __webpack_require__(/*! ../jsutils/instanceOf.mjs */ "../../../node_modules/graphql/jsutils/instanceOf.mjs"); +var _isObjectLike = __webpack_require__(/*! ../jsutils/isObjectLike.mjs */ "../../../node_modules/graphql/jsutils/isObjectLike.mjs"); var _keyMap = __webpack_require__(/*! ../jsutils/keyMap.mjs */ "../../../node_modules/graphql/jsutils/keyMap.mjs"); var _keyValMap = __webpack_require__(/*! ../jsutils/keyValMap.mjs */ "../../../node_modules/graphql/jsutils/keyValMap.mjs"); var _mapValue = __webpack_require__(/*! ../jsutils/mapValue.mjs */ "../../../node_modules/graphql/jsutils/mapValue.mjs"); @@ -31818,6 +30934,7 @@ function assertType(type) { /** * There are predicates for each kind of GraphQL type. */ + function isScalarType(type) { return (0, _instanceOf.instanceOf)(type, GraphQLScalarType); } @@ -31890,6 +31007,10 @@ function assertNonNullType(type) { } return type; } +/** + * These types may be used as input types for arguments and directives. + */ + function isInputType(type) { return isScalarType(type) || isEnumType(type) || isInputObjectType(type) || isWrappingType(type) && isInputType(type.ofType); } @@ -31899,6 +31020,10 @@ function assertInputType(type) { } return type; } +/** + * These types may be used as output types as the result of fields. + */ + function isOutputType(type) { return isScalarType(type) || isObjectType(type) || isInterfaceType(type) || isUnionType(type) || isEnumType(type) || isWrappingType(type) && isOutputType(type.ofType); } @@ -31908,6 +31033,10 @@ function assertOutputType(type) { } return type; } +/** + * These types may describe types which may be leaf values. + */ + function isLeafType(type) { return isScalarType(type) || isEnumType(type); } @@ -31917,6 +31046,10 @@ function assertLeafType(type) { } return type; } +/** + * These types may describe the parent context of a selection set. + */ + function isCompositeType(type) { return isObjectType(type) || isInterfaceType(type) || isUnionType(type); } @@ -31926,6 +31059,10 @@ function assertCompositeType(type) { } return type; } +/** + * These types may describe the parent context of a selection set. + */ + function isAbstractType(type) { return isInterfaceType(type) || isUnionType(type); } @@ -31954,8 +31091,10 @@ function assertAbstractType(type) { * }) * ``` */ + class GraphQLList { constructor(ofType) { + isType(ofType) || (0, _devAssert.devAssert)(false, `Expected ${(0, _inspect.inspect)(ofType)} to be a GraphQL type.`); this.ofType = ofType; } get [Symbol.toStringTag]() { @@ -31992,6 +31131,7 @@ class GraphQLList { exports.GraphQLList = GraphQLList; class GraphQLNonNull { constructor(ofType) { + isNullableType(ofType) || (0, _devAssert.devAssert)(false, `Expected ${(0, _inspect.inspect)(ofType)} to be a GraphQL nullable type.`); this.ofType = ofType; } get [Symbol.toStringTag]() { @@ -32004,6 +31144,9 @@ class GraphQLNonNull { return this.toString(); } } +/** + * These types wrap and modify other types + */ exports.GraphQLNonNull = GraphQLNonNull; function isWrappingType(type) { return isListType(type) || isNonNullType(type); @@ -32014,6 +31157,10 @@ function assertWrappingType(type) { } return type; } +/** + * These types can all accept null as a value. + */ + function isNullableType(type) { return isType(type) && !isNonNullType(type); } @@ -32028,6 +31175,10 @@ function getNullableType(type) { return isNonNullType(type) ? type.ofType : type; } } +/** + * These named types do not include modifiers like List or NonNull. + */ + function isNamedType(type) { return isScalarType(type) || isObjectType(type) || isInterfaceType(type) || isUnionType(type) || isEnumType(type) || isInputObjectType(type); } @@ -32046,12 +31197,27 @@ function getNamedType(type) { return unwrappedType; } } +/** + * Used while defining GraphQL types to allow for circular references in + * otherwise immutable type definitions. + */ + function resolveReadonlyArrayThunk(thunk) { return typeof thunk === 'function' ? thunk() : thunk; } function resolveObjMapThunk(thunk) { return typeof thunk === 'function' ? thunk() : thunk; } +/** + * Custom extensions + * + * @remarks + * Use a unique identifier name for your extension, for example the name of + * your library or project. Do not use a shortened identifier as this increases + * the risk of conflicts. We recommend you add at most one extension field, + * an object which can contain all the values you need. + */ + /** * Scalar Type Definition * @@ -32096,6 +31262,8 @@ class GraphQLScalarType { this.extensions = (0, _toObjMap.toObjMap)(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = (_config$extensionASTN = config.extensionASTNodes) !== null && _config$extensionASTN !== void 0 ? _config$extensionASTN : []; + config.specifiedByURL == null || typeof config.specifiedByURL === 'string' || (0, _devAssert.devAssert)(false, `${this.name} must provide "specifiedByURL" as a string, ` + `but got: ${(0, _inspect.inspect)(config.specifiedByURL)}.`); + config.serialize == null || typeof config.serialize === 'function' || (0, _devAssert.devAssert)(false, `${this.name} must provide "serialize" function. If this custom Scalar is also used as an input type, ensure "parseValue" and "parseLiteral" functions are also provided.`); if (config.parseLiteral) { typeof config.parseValue === 'function' && typeof config.parseLiteral === 'function' || (0, _devAssert.devAssert)(false, `${this.name} must provide both "parseValue" and "parseLiteral" functions.`); } @@ -32123,6 +31291,7 @@ class GraphQLScalarType { return this.toString(); } } + /** * Object Type Definition * @@ -32173,10 +31342,9 @@ class GraphQLObjectType { this.extensions = (0, _toObjMap.toObjMap)(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = (_config$extensionASTN2 = config.extensionASTNodes) !== null && _config$extensionASTN2 !== void 0 ? _config$extensionASTN2 : []; - // prettier-ignore - // FIXME: blocked by https://github.com/prettier/prettier/issues/14625 - this._fields = defineFieldMap.bind(undefined, config.fields); - this._interfaces = defineInterfaces.bind(undefined, config.interfaces); + this._fields = () => defineFieldMap(config); + this._interfaces = () => defineInterfaces(config); + config.isTypeOf == null || typeof config.isTypeOf === 'function' || (0, _devAssert.devAssert)(false, `${this.name} must provide "isTypeOf" as a function, ` + `but got: ${(0, _inspect.inspect)(config.isTypeOf)}.`); } get [Symbol.toStringTag]() { return 'GraphQLObjectType'; @@ -32213,14 +31381,21 @@ class GraphQLObjectType { } } exports.GraphQLObjectType = GraphQLObjectType; -function defineInterfaces(interfaces) { - return resolveReadonlyArrayThunk(interfaces !== null && interfaces !== void 0 ? interfaces : []); +function defineInterfaces(config) { + var _config$interfaces; + const interfaces = resolveReadonlyArrayThunk((_config$interfaces = config.interfaces) !== null && _config$interfaces !== void 0 ? _config$interfaces : []); + Array.isArray(interfaces) || (0, _devAssert.devAssert)(false, `${config.name} interfaces must be an Array or a function which returns an Array.`); + return interfaces; } -function defineFieldMap(fields) { - const fieldMap = resolveObjMapThunk(fields); +function defineFieldMap(config) { + const fieldMap = resolveObjMapThunk(config.fields); + isPlainObj(fieldMap) || (0, _devAssert.devAssert)(false, `${config.name} fields must be an object with field names as keys or a function which returns such an object.`); return (0, _mapValue.mapValue)(fieldMap, (fieldConfig, fieldName) => { var _fieldConfig$args; + isPlainObj(fieldConfig) || (0, _devAssert.devAssert)(false, `${config.name}.${fieldName} field config must be an object.`); + fieldConfig.resolve == null || typeof fieldConfig.resolve === 'function' || (0, _devAssert.devAssert)(false, `${config.name}.${fieldName} field resolver must be a function if ` + `provided, but got: ${(0, _inspect.inspect)(fieldConfig.resolve)}.`); const argsConfig = (_fieldConfig$args = fieldConfig.args) !== null && _fieldConfig$args !== void 0 ? _fieldConfig$args : {}; + isPlainObj(argsConfig) || (0, _devAssert.devAssert)(false, `${config.name}.${fieldName} args must be an object with argument names as keys.`); return { name: (0, _assertName.assertName)(fieldName), description: fieldConfig.description, @@ -32234,8 +31409,8 @@ function defineFieldMap(fields) { }; }); } -function defineArguments(args) { - return Object.entries(args).map(([argName, argConfig]) => ({ +function defineArguments(config) { + return Object.entries(config).map(([argName, argConfig]) => ({ name: (0, _assertName.assertName)(argName), description: argConfig.description, type: argConfig.type, @@ -32245,6 +31420,9 @@ function defineArguments(args) { astNode: argConfig.astNode })); } +function isPlainObj(obj) { + return (0, _isObjectLike.isObjectLike)(obj) && !Array.isArray(obj); +} function fieldsToFieldsConfig(fields) { return (0, _mapValue.mapValue)(fields, field => ({ description: field.description, @@ -32260,6 +31438,7 @@ function fieldsToFieldsConfig(fields) { /** * @internal */ + function argsToArgsConfig(args) { return (0, _keyValMap.keyValMap)(args, arg => arg.name, arg => ({ description: arg.description, @@ -32273,6 +31452,7 @@ function argsToArgsConfig(args) { function isRequiredArgument(arg) { return isNonNullType(arg.type) && arg.defaultValue === undefined; } + /** * Interface Type Definition * @@ -32301,10 +31481,9 @@ class GraphQLInterfaceType { this.extensions = (0, _toObjMap.toObjMap)(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = (_config$extensionASTN3 = config.extensionASTNodes) !== null && _config$extensionASTN3 !== void 0 ? _config$extensionASTN3 : []; - // prettier-ignore - // FIXME: blocked by https://github.com/prettier/prettier/issues/14625 - this._fields = defineFieldMap.bind(undefined, config.fields); - this._interfaces = defineInterfaces.bind(undefined, config.interfaces); + this._fields = defineFieldMap.bind(undefined, config); + this._interfaces = defineInterfaces.bind(undefined, config); + config.resolveType == null || typeof config.resolveType === 'function' || (0, _devAssert.devAssert)(false, `${this.name} must provide "resolveType" as a function, ` + `but got: ${(0, _inspect.inspect)(config.resolveType)}.`); } get [Symbol.toStringTag]() { return 'GraphQLInterfaceType'; @@ -32340,6 +31519,7 @@ class GraphQLInterfaceType { return this.toString(); } } + /** * Union Type Definition * @@ -32374,7 +31554,8 @@ class GraphQLUnionType { this.extensions = (0, _toObjMap.toObjMap)(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = (_config$extensionASTN4 = config.extensionASTNodes) !== null && _config$extensionASTN4 !== void 0 ? _config$extensionASTN4 : []; - this._types = defineTypes.bind(undefined, config.types); + this._types = defineTypes.bind(undefined, config); + config.resolveType == null || typeof config.resolveType === 'function' || (0, _devAssert.devAssert)(false, `${this.name} must provide "resolveType" as a function, ` + `but got: ${(0, _inspect.inspect)(config.resolveType)}.`); } get [Symbol.toStringTag]() { return 'GraphQLUnionType'; @@ -32404,19 +31585,12 @@ class GraphQLUnionType { } } exports.GraphQLUnionType = GraphQLUnionType; -function defineTypes(types) { - return resolveReadonlyArrayThunk(types); -} -function enumValuesFromConfig(values) { - return Object.entries(values).map(([valueName, valueConfig]) => ({ - name: (0, _assertName.assertEnumValueName)(valueName), - description: valueConfig.description, - value: valueConfig.value !== undefined ? valueConfig.value : valueName, - deprecationReason: valueConfig.deprecationReason, - extensions: (0, _toObjMap.toObjMap)(valueConfig.extensions), - astNode: valueConfig.astNode - })); +function defineTypes(config) { + const types = resolveReadonlyArrayThunk(config.types); + Array.isArray(types) || (0, _devAssert.devAssert)(false, `Must provide Array of types or a function which returns such an array for Union ${config.name}.`); + return types; } + /** * Enum Type Definition * @@ -32440,7 +31614,8 @@ function enumValuesFromConfig(values) { * Note: If a value is not provided in a definition, the name of the enum value * will be used as its internal value. */ -class GraphQLEnumType /* */ { +class GraphQLEnumType { + /* */ constructor(config) { var _config$extensionASTN5; this.name = (0, _assertName.assertName)(config.name); @@ -32448,7 +31623,7 @@ class GraphQLEnumType /* */ { this.extensions = (0, _toObjMap.toObjMap)(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = (_config$extensionASTN5 = config.extensionASTNodes) !== null && _config$extensionASTN5 !== void 0 ? _config$extensionASTN5 : []; - this._values = typeof config.values === 'function' ? config.values : enumValuesFromConfig(config.values); + this._values = typeof config.values === 'function' ? config.values : defineEnumValues(this.name, config.values); this._valueLookup = null; this._nameLookup = null; } @@ -32457,7 +31632,7 @@ class GraphQLEnumType /* */ { } getValues() { if (typeof this._values === 'function') { - this._values = enumValuesFromConfig(this._values()); + this._values = defineEnumValues(this.name, this._values()); } return this._values; } @@ -32467,7 +31642,7 @@ class GraphQLEnumType /* */ { } return this._nameLookup[name]; } - serialize(outputValue /* T */) { + serialize(outputValue) { if (this._valueLookup === null) { this._valueLookup = new Map(this.getValues().map(enumValue => [enumValue.value, enumValue])); } @@ -32477,7 +31652,8 @@ class GraphQLEnumType /* */ { } return enumValue.name; } - parseValue(inputValue) { + parseValue(inputValue) /* T */ + { if (typeof inputValue !== 'string') { const valueStr = (0, _inspect.inspect)(inputValue); throw new _GraphQLError.GraphQLError(`Enum "${this.name}" cannot represent non-string value: ${valueStr}.` + didYouMeanEnumValue(this, valueStr)); @@ -32488,7 +31664,8 @@ class GraphQLEnumType /* */ { } return enumValue.value; } - parseLiteral(valueNode, _variables) { + parseLiteral(valueNode, _variables) /* T */ + { // Note: variables will be resolved to a value before calling this function. if (valueNode.kind !== _kinds.Kind.ENUM) { const valueStr = (0, _printer.print)(valueNode); @@ -32535,6 +31712,21 @@ function didYouMeanEnumValue(enumType, unknownValueStr) { const suggestedValues = (0, _suggestionList.suggestionList)(unknownValueStr, allNames); return (0, _didYouMean.didYouMean)('the enum value', suggestedValues); } +function defineEnumValues(typeName, valueMap) { + isPlainObj(valueMap) || (0, _devAssert.devAssert)(false, `${typeName} values must be an object with value names as keys.`); + return Object.entries(valueMap).map(([valueName, valueConfig]) => { + isPlainObj(valueConfig) || (0, _devAssert.devAssert)(false, `${typeName}.${valueName} must refer to an object with a "value" key ` + `representing an internal value but got: ${(0, _inspect.inspect)(valueConfig)}.`); + return { + name: (0, _assertName.assertEnumValueName)(valueName), + description: valueConfig.description, + value: valueConfig.value !== undefined ? valueConfig.value : valueName, + deprecationReason: valueConfig.deprecationReason, + extensions: (0, _toObjMap.toObjMap)(valueConfig.extensions), + astNode: valueConfig.astNode + }; + }); +} + /** * Input Object Type Definition * @@ -32565,7 +31757,7 @@ class GraphQLInputObjectType { this.astNode = config.astNode; this.extensionASTNodes = (_config$extensionASTN6 = config.extensionASTNodes) !== null && _config$extensionASTN6 !== void 0 ? _config$extensionASTN6 : []; this.isOneOf = (_config$isOneOf = config.isOneOf) !== null && _config$isOneOf !== void 0 ? _config$isOneOf : false; - this._fields = defineInputFieldMap.bind(undefined, config.fields); + this._fields = defineInputFieldMap.bind(undefined, config); } get [Symbol.toStringTag]() { return 'GraphQLInputObjectType'; @@ -32603,17 +31795,21 @@ class GraphQLInputObjectType { } } exports.GraphQLInputObjectType = GraphQLInputObjectType; -function defineInputFieldMap(fields) { - const fieldMap = resolveObjMapThunk(fields); - return (0, _mapValue.mapValue)(fieldMap, (fieldConfig, fieldName) => ({ - name: (0, _assertName.assertName)(fieldName), - description: fieldConfig.description, - type: fieldConfig.type, - defaultValue: fieldConfig.defaultValue, - deprecationReason: fieldConfig.deprecationReason, - extensions: (0, _toObjMap.toObjMap)(fieldConfig.extensions), - astNode: fieldConfig.astNode - })); +function defineInputFieldMap(config) { + const fieldMap = resolveObjMapThunk(config.fields); + isPlainObj(fieldMap) || (0, _devAssert.devAssert)(false, `${config.name} fields must be an object with field names as keys or a function which returns such an object.`); + return (0, _mapValue.mapValue)(fieldMap, (fieldConfig, fieldName) => { + !('resolve' in fieldConfig) || (0, _devAssert.devAssert)(false, `${config.name}.${fieldName} field has a resolve property, but Input Types cannot define resolvers.`); + return { + name: (0, _assertName.assertName)(fieldName), + description: fieldConfig.description, + type: fieldConfig.type, + defaultValue: fieldConfig.defaultValue, + deprecationReason: fieldConfig.deprecationReason, + extensions: (0, _toObjMap.toObjMap)(fieldConfig.extensions), + astNode: fieldConfig.astNode + }; + }); } function isRequiredInputField(field) { return isNonNullType(field.type) && field.defaultValue === undefined; @@ -32632,13 +31828,15 @@ function isRequiredInputField(field) { Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.GraphQLStreamDirective = exports.GraphQLSpecifiedByDirective = exports.GraphQLSkipDirective = exports.GraphQLOneOfDirective = exports.GraphQLIncludeDirective = exports.GraphQLDirective = exports.GraphQLDeprecatedDirective = exports.GraphQLDeferDirective = exports.DEFAULT_DEPRECATION_REASON = void 0; +exports.GraphQLSpecifiedByDirective = exports.GraphQLSkipDirective = exports.GraphQLOneOfDirective = exports.GraphQLIncludeDirective = exports.GraphQLDirective = exports.GraphQLDeprecatedDirective = exports.DEFAULT_DEPRECATION_REASON = void 0; exports.assertDirective = assertDirective; exports.isDirective = isDirective; exports.isSpecifiedDirective = isSpecifiedDirective; exports.specifiedDirectives = void 0; +var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); var _instanceOf = __webpack_require__(/*! ../jsutils/instanceOf.mjs */ "../../../node_modules/graphql/jsutils/instanceOf.mjs"); +var _isObjectLike = __webpack_require__(/*! ../jsutils/isObjectLike.mjs */ "../../../node_modules/graphql/jsutils/isObjectLike.mjs"); var _toObjMap = __webpack_require__(/*! ../jsutils/toObjMap.mjs */ "../../../node_modules/graphql/jsutils/toObjMap.mjs"); var _directiveLocation = __webpack_require__(/*! ../language/directiveLocation.mjs */ "../../../node_modules/graphql/language/directiveLocation.mjs"); var _assertName = __webpack_require__(/*! ./assertName.mjs */ "../../../node_modules/graphql/type/assertName.mjs"); @@ -32647,6 +31845,7 @@ var _scalars = __webpack_require__(/*! ./scalars.mjs */ "../../../node_modules/g /** * Test if the given value is a GraphQL directive. */ + function isDirective(directive) { return (0, _instanceOf.instanceOf)(directive, GraphQLDirective); } @@ -32656,6 +31855,16 @@ function assertDirective(directive) { } return directive; } +/** + * Custom extensions + * + * @remarks + * Use a unique identifier name for your extension, for example the name of + * your library or project. Do not use a shortened identifier as this increases + * the risk of conflicts. We recommend you add at most one extension field, + * an object which can contain all the values you need. + */ + /** * Directives are used by the GraphQL runtime as a way of modifying execution * behavior. Type system creators will usually not create these directly. @@ -32669,7 +31878,9 @@ class GraphQLDirective { this.isRepeatable = (_config$isRepeatable = config.isRepeatable) !== null && _config$isRepeatable !== void 0 ? _config$isRepeatable : false; this.extensions = (0, _toObjMap.toObjMap)(config.extensions); this.astNode = config.astNode; + Array.isArray(config.locations) || (0, _devAssert.devAssert)(false, `@${config.name} locations must be an Array.`); const args = (_config$args = config.args) !== null && _config$args !== void 0 ? _config$args : {}; + (0, _isObjectLike.isObjectLike)(args) && !Array.isArray(args) || (0, _devAssert.devAssert)(false, `@${config.name} args must be an object with argument names as keys.`); this.args = (0, _definition.defineArguments)(args); } get [Symbol.toStringTag]() { @@ -32693,6 +31904,7 @@ class GraphQLDirective { return this.toString(); } } + /** * Used to conditionally include fields or fragments. */ @@ -32711,6 +31923,7 @@ const GraphQLIncludeDirective = exports.GraphQLIncludeDirective = new GraphQLDir /** * Used to conditionally skip (exclude) fields or fragments. */ + const GraphQLSkipDirective = exports.GraphQLSkipDirective = new GraphQLDirective({ name: 'skip', description: 'Directs the executor to skip this field or fragment when the `if` argument is true.', @@ -32722,56 +31935,15 @@ const GraphQLSkipDirective = exports.GraphQLSkipDirective = new GraphQLDirective } } }); -/** - * Used to conditionally defer fragments. - */ -const GraphQLDeferDirective = exports.GraphQLDeferDirective = new GraphQLDirective({ - name: 'defer', - description: 'Directs the executor to defer this fragment when the `if` argument is true or undefined.', - locations: [_directiveLocation.DirectiveLocation.FRAGMENT_SPREAD, _directiveLocation.DirectiveLocation.INLINE_FRAGMENT], - args: { - if: { - type: new _definition.GraphQLNonNull(_scalars.GraphQLBoolean), - description: 'Deferred when true or undefined.', - defaultValue: true - }, - label: { - type: _scalars.GraphQLString, - description: 'Unique name' - } - } -}); -/** - * Used to conditionally stream list fields. - */ -const GraphQLStreamDirective = exports.GraphQLStreamDirective = new GraphQLDirective({ - name: 'stream', - description: 'Directs the executor to stream plural fields when the `if` argument is true or undefined.', - locations: [_directiveLocation.DirectiveLocation.FIELD], - args: { - if: { - type: new _definition.GraphQLNonNull(_scalars.GraphQLBoolean), - description: 'Stream when true or undefined.', - defaultValue: true - }, - label: { - type: _scalars.GraphQLString, - description: 'Unique name' - }, - initialCount: { - defaultValue: 0, - type: _scalars.GraphQLInt, - description: 'Number of items to return immediately' - } - } -}); /** * Constant string used for default reason for a deprecation. */ + const DEFAULT_DEPRECATION_REASON = exports.DEFAULT_DEPRECATION_REASON = 'No longer supported'; /** * Used to declare element of a GraphQL schema as deprecated. */ + const GraphQLDeprecatedDirective = exports.GraphQLDeprecatedDirective = new GraphQLDirective({ name: 'deprecated', description: 'Marks an element of a GraphQL schema as no longer supported.', @@ -32787,6 +31959,7 @@ const GraphQLDeprecatedDirective = exports.GraphQLDeprecatedDirective = new Grap /** * Used to provide a URL for specifying the behavior of custom scalar definitions. */ + const GraphQLSpecifiedByDirective = exports.GraphQLSpecifiedByDirective = new GraphQLDirective({ name: 'specifiedBy', description: 'Exposes a URL that specifies the behavior of this scalar.', @@ -32801,6 +31974,7 @@ const GraphQLSpecifiedByDirective = exports.GraphQLSpecifiedByDirective = new Gr /** * Used to indicate an Input Object is a OneOf Input Object. */ + const GraphQLOneOfDirective = exports.GraphQLOneOfDirective = new GraphQLDirective({ name: 'oneOf', description: 'Indicates exactly one field must be supplied and this field must not be `null`.', @@ -32810,6 +31984,7 @@ const GraphQLOneOfDirective = exports.GraphQLOneOfDirective = new GraphQLDirecti /** * The full list of specified directives. */ + const specifiedDirectives = exports.specifiedDirectives = Object.freeze([GraphQLIncludeDirective, GraphQLSkipDirective, GraphQLDeprecatedDirective, GraphQLSpecifiedByDirective, GraphQLOneOfDirective]); function isSpecifiedDirective(directive) { return specifiedDirectives.some(({ @@ -32854,12 +32029,6 @@ Object.defineProperty(exports, "GraphQLBoolean", ({ return _scalars.GraphQLBoolean; } })); -Object.defineProperty(exports, "GraphQLDeferDirective", ({ - enumerable: true, - get: function () { - return _directives.GraphQLDeferDirective; - } -})); Object.defineProperty(exports, "GraphQLDeprecatedDirective", ({ enumerable: true, get: function () { @@ -32962,12 +32131,6 @@ Object.defineProperty(exports, "GraphQLSpecifiedByDirective", ({ return _directives.GraphQLSpecifiedByDirective; } })); -Object.defineProperty(exports, "GraphQLStreamDirective", ({ - enumerable: true, - get: function () { - return _directives.GraphQLStreamDirective; - } -})); Object.defineProperty(exports, "GraphQLString", ({ enumerable: true, get: function () { @@ -33474,7 +32637,7 @@ const __Directive = exports.__Directive = new _definition.GraphQLObjectType({ resolve(field, { includeDeprecated }) { - return includeDeprecated === true ? field.args : field.args.filter(arg => arg.deprecationReason == null); + return includeDeprecated ? field.args : field.args.filter(arg => arg.deprecationReason == null); } } }) @@ -33594,6 +32757,7 @@ const __Type = exports.__Type = new _definition.GraphQLObjectType({ } /* c8 ignore next 3 */ // Not reachable, all possible types have been considered) + false || (0, _invariant.invariant)(false, `Unexpected type: "${(0, _inspect.inspect)(type)}".`); } }, @@ -33603,9 +32767,8 @@ const __Type = exports.__Type = new _definition.GraphQLObjectType({ }, description: { type: _scalars.GraphQLString, - resolve: type => - // FIXME: add test case - /* c8 ignore next */ + resolve: (type // FIXME: add test case + ) => /* c8 ignore next */ 'description' in type ? type.description : undefined }, specifiedByURL: { @@ -33625,7 +32788,7 @@ const __Type = exports.__Type = new _definition.GraphQLObjectType({ }) { if ((0, _definition.isObjectType)(type) || (0, _definition.isInterfaceType)(type)) { const fields = Object.values(type.getFields()); - return includeDeprecated === true ? fields : fields.filter(field => field.deprecationReason == null); + return includeDeprecated ? fields : fields.filter(field => field.deprecationReason == null); } } }, @@ -33660,7 +32823,7 @@ const __Type = exports.__Type = new _definition.GraphQLObjectType({ }) { if ((0, _definition.isEnumType)(type)) { const values = type.getValues(); - return includeDeprecated === true ? values : values.filter(field => field.deprecationReason == null); + return includeDeprecated ? values : values.filter(field => field.deprecationReason == null); } } }, @@ -33677,7 +32840,7 @@ const __Type = exports.__Type = new _definition.GraphQLObjectType({ }) { if ((0, _definition.isInputObjectType)(type)) { const values = Object.values(type.getFields()); - return includeDeprecated === true ? values : values.filter(field => field.deprecationReason == null); + return includeDeprecated ? values : values.filter(field => field.deprecationReason == null); } } }, @@ -33718,7 +32881,7 @@ const __Field = exports.__Field = new _definition.GraphQLObjectType({ resolve(field, { includeDeprecated }) { - return includeDeprecated === true ? field.args : field.args.filter(arg => arg.deprecationReason == null); + return includeDeprecated ? field.args : field.args.filter(arg => arg.deprecationReason == null); } }, type: { @@ -33848,6 +33011,7 @@ const __TypeKind = exports.__TypeKind = new _definition.GraphQLEnumType({ * Note that these are GraphQLField and not GraphQLFieldConfig, * so the format for args is different. */ + const SchemaMetaFieldDef = exports.SchemaMetaFieldDef = { name: '__schema', type: new _definition.GraphQLNonNull(__Schema), @@ -33927,11 +33091,13 @@ var _definition = __webpack_require__(/*! ./definition.mjs */ "../../../node_mod * Maximum possible Int value as per GraphQL Spec (32-bit signed integer). * n.b. This differs from JavaScript's numbers that are IEEE 754 doubles safe up-to 2^53 - 1 * */ + const GRAPHQL_MAX_INT = exports.GRAPHQL_MAX_INT = 2147483647; /** * Minimum possible Int value as per GraphQL Spec (32-bit signed integer). * n.b. This differs from JavaScript's numbers that are IEEE 754 doubles safe starting at -(2^53 - 1) * */ + const GRAPHQL_MIN_INT = exports.GRAPHQL_MIN_INT = -2147483648; const GraphQLInt = exports.GraphQLInt = new _definition.GraphQLScalarType({ name: 'Int', @@ -34002,9 +33168,7 @@ const GraphQLFloat = exports.GraphQLFloat = new _definition.GraphQLScalarType({ }, parseLiteral(valueNode) { if (valueNode.kind !== _kinds.Kind.FLOAT && valueNode.kind !== _kinds.Kind.INT) { - throw new _GraphQLError.GraphQLError(`Float cannot represent non numeric value: ${(0, _printer.print)(valueNode)}`, { - nodes: valueNode - }); + throw new _GraphQLError.GraphQLError(`Float cannot represent non numeric value: ${(0, _printer.print)(valueNode)}`, valueNode); } return parseFloat(valueNode.value); } @@ -34013,9 +33177,9 @@ const GraphQLString = exports.GraphQLString = new _definition.GraphQLScalarType( name: 'String', description: 'The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.', serialize(outputValue) { - const coercedValue = serializeObject(outputValue); - // Serialize string, boolean and number values to a string, but do not + const coercedValue = serializeObject(outputValue); // Serialize string, boolean and number values to a string, but do not // attempt to coerce object, function, symbol, or other types as strings. + if (typeof coercedValue === 'string') { return coercedValue; } @@ -34106,10 +33270,10 @@ function isSpecifiedScalarType(type) { return specifiedScalarTypes.some(({ name }) => type.name === name); -} -// Support serializing objects with custom valueOf() or toJSON() functions - +} // Support serializing objects with custom valueOf() or toJSON() functions - // a common way to represent a complex value which can be represented as // a string (ex: MongoDB id objects). + function serializeObject(outputValue) { if ((0, _isObjectLike.isObjectLike)(outputValue)) { if (typeof outputValue.valueOf === 'function') { @@ -34141,8 +33305,10 @@ Object.defineProperty(exports, "__esModule", ({ exports.GraphQLSchema = void 0; exports.assertSchema = assertSchema; exports.isSchema = isSchema; +var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); var _instanceOf = __webpack_require__(/*! ../jsutils/instanceOf.mjs */ "../../../node_modules/graphql/jsutils/instanceOf.mjs"); +var _isObjectLike = __webpack_require__(/*! ../jsutils/isObjectLike.mjs */ "../../../node_modules/graphql/jsutils/isObjectLike.mjs"); var _toObjMap = __webpack_require__(/*! ../jsutils/toObjMap.mjs */ "../../../node_modules/graphql/jsutils/toObjMap.mjs"); var _ast = __webpack_require__(/*! ../language/ast.mjs */ "../../../node_modules/graphql/language/ast.mjs"); var _definition = __webpack_require__(/*! ./definition.mjs */ "../../../node_modules/graphql/type/definition.mjs"); @@ -34151,6 +33317,7 @@ var _introspection = __webpack_require__(/*! ./introspection.mjs */ "../../../no /** * Test if the given value is a GraphQL schema. */ + function isSchema(schema) { return (0, _instanceOf.instanceOf)(schema, GraphQLSchema); } @@ -34160,6 +33327,16 @@ function assertSchema(schema) { } return schema; } +/** + * Custom extensions + * + * @remarks + * Use a unique identifier name for your extension, for example the name of + * your library or project. Do not use a shortened identifier as this increases + * the risk of conflicts. We recommend you add at most one extension field, + * an object which can contain all the values you need. + */ + /** * Schema Definition * @@ -34229,22 +33406,28 @@ function assertSchema(schema) { * ``` */ class GraphQLSchema { + // Used as a cache for validateSchema(). constructor(config) { var _config$extensionASTN, _config$directives; + // If this schema was built from a source known to be valid, then it may be // marked with assumeValid to avoid an additional type system validation. - this.__validationErrors = config.assumeValid === true ? [] : undefined; + this.__validationErrors = config.assumeValid === true ? [] : undefined; // Check for common mistakes during construction to produce early errors. + + (0, _isObjectLike.isObjectLike)(config) || (0, _devAssert.devAssert)(false, 'Must provide configuration object.'); + !config.types || Array.isArray(config.types) || (0, _devAssert.devAssert)(false, `"types" must be Array if provided but got: ${(0, _inspect.inspect)(config.types)}.`); + !config.directives || Array.isArray(config.directives) || (0, _devAssert.devAssert)(false, '"directives" must be Array if provided but got: ' + `${(0, _inspect.inspect)(config.directives)}.`); this.description = config.description; this.extensions = (0, _toObjMap.toObjMap)(config.extensions); this.astNode = config.astNode; this.extensionASTNodes = (_config$extensionASTN = config.extensionASTNodes) !== null && _config$extensionASTN !== void 0 ? _config$extensionASTN : []; this._queryType = config.query; this._mutationType = config.mutation; - this._subscriptionType = config.subscription; - // Provide specified directives (e.g. @include and @skip) by default. - this._directives = (_config$directives = config.directives) !== null && _config$directives !== void 0 ? _config$directives : _directives.specifiedDirectives; - // To preserve order of user-provided types, we add first to add them to + this._subscriptionType = config.subscription; // Provide specified directives (e.g. @include and @skip) by default. + + this._directives = (_config$directives = config.directives) !== null && _config$directives !== void 0 ? _config$directives : _directives.specifiedDirectives; // To preserve order of user-provided types, we add first to add them to // the set of "collected" types, so `collectReferencedTypes` ignore them. + const allReferencedTypes = new Set(config.types); if (config.types != null) { for (const type of config.types) { @@ -34271,17 +33454,18 @@ class GraphQLSchema { } } } - collectReferencedTypes(_introspection.__Schema, allReferencedTypes); - // Storing the resulting map for reference by the schema. + collectReferencedTypes(_introspection.__Schema, allReferencedTypes); // Storing the resulting map for reference by the schema. + this._typeMap = Object.create(null); - this._subTypeMap = new Map(); - // Keep track of all implementations by interface name. + this._subTypeMap = Object.create(null); // Keep track of all implementations by interface name. + this._implementationsMap = Object.create(null); for (const namedType of allReferencedTypes) { if (namedType == null) { continue; } const typeName = namedType.name; + typeName || (0, _devAssert.devAssert)(false, 'One of the provided types for building the Schema is missing a name.'); if (this._typeMap[typeName] !== undefined) { throw new Error(`Schema must contain uniquely named types but contains multiple types named "${typeName}".`); } @@ -34356,17 +33540,25 @@ class GraphQLSchema { }; } isSubType(abstractType, maybeSubType) { - let set = this._subTypeMap.get(abstractType); - if (set === undefined) { + let map = this._subTypeMap[abstractType.name]; + if (map === undefined) { + map = Object.create(null); if ((0, _definition.isUnionType)(abstractType)) { - set = new Set(abstractType.getTypes()); + for (const type of abstractType.getTypes()) { + map[type.name] = true; + } } else { const implementations = this.getImplementations(abstractType); - set = new Set([...implementations.objects, ...implementations.interfaces]); + for (const type of implementations.objects) { + map[type.name] = true; + } + for (const type of implementations.interfaces) { + map[type.name] = true; + } } - this._subTypeMap.set(abstractType, set); + this._subTypeMap[abstractType.name] = map; } - return set.has(maybeSubType); + return map[maybeSubType.name] !== undefined; } getDirectives() { return this._directives; @@ -34374,33 +33566,6 @@ class GraphQLSchema { getDirective(name) { return this.getDirectives().find(directive => directive.name === name); } - /** - * This method looks up the field on the given type definition. - * It has special casing for the three introspection fields, `__schema`, - * `__type` and `__typename`. - * - * `__typename` is special because it can always be queried as a field, even - * in situations where no other fields are allowed, like on a Union. - * - * `__schema` and `__type` could get automatically added to the query type, - * but that would require mutating type definitions, which would cause issues. - */ - getField(parentType, fieldName) { - switch (fieldName) { - case _introspection.SchemaMetaFieldDef.name: - return this.getQueryType() === parentType ? _introspection.SchemaMetaFieldDef : undefined; - case _introspection.TypeMetaFieldDef.name: - return this.getQueryType() === parentType ? _introspection.TypeMetaFieldDef : undefined; - case _introspection.TypeNameMetaFieldDef.name: - return _introspection.TypeNameMetaFieldDef; - } - // this function is part "hot" path inside executor and check presence - // of 'getFields' is faster than to use `!isUnionType` - if ('getFields' in parentType) { - return parentType.getFields()[fieldName]; - } - return undefined; - } toConfig() { return { description: this.description, @@ -34459,9 +33624,6 @@ Object.defineProperty(exports, "__esModule", ({ })); exports.assertValidSchema = assertValidSchema; exports.validateSchema = validateSchema; -var _AccumulatorMap = __webpack_require__(/*! ../jsutils/AccumulatorMap.mjs */ "../../../node_modules/graphql/jsutils/AccumulatorMap.mjs"); -var _capitalize = __webpack_require__(/*! ../jsutils/capitalize.mjs */ "../../../node_modules/graphql/jsutils/capitalize.mjs"); -var _formatList = __webpack_require__(/*! ../jsutils/formatList.mjs */ "../../../node_modules/graphql/jsutils/formatList.mjs"); var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); var _GraphQLError = __webpack_require__(/*! ../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); var _ast = __webpack_require__(/*! ../language/ast.mjs */ "../../../node_modules/graphql/language/ast.mjs"); @@ -34477,20 +33639,21 @@ var _schema = __webpack_require__(/*! ./schema.mjs */ "../../../node_modules/gra * Validation runs synchronously, returning an array of encountered errors, or * an empty array if no errors were encountered and the Schema is valid. */ + function validateSchema(schema) { // First check to ensure the provided value is in fact a GraphQLSchema. - (0, _schema.assertSchema)(schema); - // If this Schema has already been validated, return the previous results. + (0, _schema.assertSchema)(schema); // If this Schema has already been validated, return the previous results. + if (schema.__validationErrors) { return schema.__validationErrors; - } - // Validate the schema, producing a list of errors. + } // Validate the schema, producing a list of errors. + const context = new SchemaValidationContext(schema); validateRootTypes(context); validateDirectives(context); - validateTypes(context); - // Persist the results of validation before returning to ensure validation + validateTypes(context); // Persist the results of validation before returning to ensure validation // does not run multiple times for this schema. + const errors = context.getErrors(); schema.__validationErrors = errors; return errors; @@ -34499,6 +33662,7 @@ function validateSchema(schema) { * Utility function which asserts a schema is valid by throwing an error if * it is invalid. */ + function assertValidSchema(schema) { const errors = validateSchema(schema); if (errors.length !== 0) { @@ -34522,28 +33686,22 @@ class SchemaValidationContext { } function validateRootTypes(context) { const schema = context.schema; - if (schema.getQueryType() == null) { + const queryType = schema.getQueryType(); + if (!queryType) { context.reportError('Query root type must be provided.', schema.astNode); + } else if (!(0, _definition.isObjectType)(queryType)) { + var _getOperationTypeNode; + context.reportError(`Query root type must be Object type, it cannot be ${(0, _inspect.inspect)(queryType)}.`, (_getOperationTypeNode = getOperationTypeNode(schema, _ast.OperationTypeNode.QUERY)) !== null && _getOperationTypeNode !== void 0 ? _getOperationTypeNode : queryType.astNode); } - const rootTypesMap = new _AccumulatorMap.AccumulatorMap(); - for (const operationType of Object.values(_ast.OperationTypeNode)) { - const rootType = schema.getRootType(operationType); - if (rootType != null) { - if (!(0, _definition.isObjectType)(rootType)) { - var _getOperationTypeNode; - const operationTypeStr = (0, _capitalize.capitalize)(operationType); - const rootTypeStr = (0, _inspect.inspect)(rootType); - context.reportError(operationType === _ast.OperationTypeNode.QUERY ? `${operationTypeStr} root type must be Object type, it cannot be ${rootTypeStr}.` : `${operationTypeStr} root type must be Object type if provided, it cannot be ${rootTypeStr}.`, (_getOperationTypeNode = getOperationTypeNode(schema, operationType)) !== null && _getOperationTypeNode !== void 0 ? _getOperationTypeNode : rootType.astNode); - } else { - rootTypesMap.add(rootType, operationType); - } - } + const mutationType = schema.getMutationType(); + if (mutationType && !(0, _definition.isObjectType)(mutationType)) { + var _getOperationTypeNode2; + context.reportError('Mutation root type must be Object type if provided, it cannot be ' + `${(0, _inspect.inspect)(mutationType)}.`, (_getOperationTypeNode2 = getOperationTypeNode(schema, _ast.OperationTypeNode.MUTATION)) !== null && _getOperationTypeNode2 !== void 0 ? _getOperationTypeNode2 : mutationType.astNode); } - for (const [rootType, operationTypes] of rootTypesMap) { - if (operationTypes.length > 1) { - const operationList = (0, _formatList.andList)(operationTypes); - context.reportError(`All root types must be different, "${rootType.name}" type is used as ${operationList} root types.`, operationTypes.map(operationType => getOperationTypeNode(schema, operationType))); - } + const subscriptionType = schema.getSubscriptionType(); + if (subscriptionType && !(0, _definition.isObjectType)(subscriptionType)) { + var _getOperationTypeNode3; + context.reportError('Subscription root type must be Object type if provided, it cannot be ' + `${(0, _inspect.inspect)(subscriptionType)}.`, (_getOperationTypeNode3 = getOperationTypeNode(schema, _ast.OperationTypeNode.SUBSCRIPTION)) !== null && _getOperationTypeNode3 !== void 0 ? _getOperationTypeNode3 : subscriptionType.astNode); } } function getOperationTypeNode(schema, operation) { @@ -34552,7 +33710,9 @@ function getOperationTypeNode(schema, operation) { // FIXME: https://github.com/graphql/graphql-js/issues/2203 schemaNode => { var _schemaNode$operation; - return /* c8 ignore next */(_schemaNode$operation = schemaNode === null || schemaNode === void 0 ? void 0 : schemaNode.operationTypes) !== null && _schemaNode$operation !== void 0 ? _schemaNode$operation : []; + return /* c8 ignore next */( + (_schemaNode$operation = schemaNode === null || schemaNode === void 0 ? void 0 : schemaNode.operationTypes) !== null && _schemaNode$operation !== void 0 ? _schemaNode$operation : [] + ); }).find(operationNode => operationNode.operation === operation)) === null || _flatMap$find === void 0 ? void 0 : _flatMap$find.type; } function validateDirectives(context) { @@ -34561,17 +33721,15 @@ function validateDirectives(context) { if (!(0, _directives.isDirective)(directive)) { context.reportError(`Expected directive but got: ${(0, _inspect.inspect)(directive)}.`, directive === null || directive === void 0 ? void 0 : directive.astNode); continue; - } - // Ensure they are named correctly. - validateName(context, directive); - if (directive.locations.length === 0) { - context.reportError(`Directive @${directive.name} must include 1 or more locations.`, directive.astNode); - } + } // Ensure they are named correctly. + + validateName(context, directive); // TODO: Ensure proper locations. // Ensure the arguments are valid. + for (const arg of directive.args) { // Ensure they are named correctly. - validateName(context, arg); - // Ensure the type is an input type. + validateName(context, arg); // Ensure the type is an input type. + if (!(0, _definition.isInputType)(arg.type)) { context.reportError(`The type of @${directive.name}(${arg.name}:) must be Input Type ` + `but got: ${(0, _inspect.inspect)(arg.type)}.`, arg.astNode); } @@ -34596,20 +33754,20 @@ function validateTypes(context) { if (!(0, _definition.isNamedType)(type)) { context.reportError(`Expected GraphQL named type but got: ${(0, _inspect.inspect)(type)}.`, type.astNode); continue; - } - // Ensure it is named correctly (excluding introspection types). + } // Ensure it is named correctly (excluding introspection types). + if (!(0, _introspection.isIntrospectionType)(type)) { validateName(context, type); } if ((0, _definition.isObjectType)(type)) { // Ensure fields are valid - validateFields(context, type); - // Ensure objects implement the interfaces they claim to. + validateFields(context, type); // Ensure objects implement the interfaces they claim to. + validateInterfaces(context, type); } else if ((0, _definition.isInterfaceType)(type)) { // Ensure fields are valid. - validateFields(context, type); - // Ensure interfaces implement the interfaces they claim to. + validateFields(context, type); // Ensure interfaces implement the interfaces they claim to. + validateInterfaces(context, type); } else if ((0, _definition.isUnionType)(type)) { // Ensure Unions include valid member types. @@ -34619,32 +33777,32 @@ function validateTypes(context) { validateEnumValues(context, type); } else if ((0, _definition.isInputObjectType)(type)) { // Ensure Input Object fields are valid. - validateInputFields(context, type); - // Ensure Input Objects do not contain non-nullable circular references + validateInputFields(context, type); // Ensure Input Objects do not contain non-nullable circular references + validateInputObjectCircularRefs(type); } } } function validateFields(context, type) { - const fields = Object.values(type.getFields()); - // Objects and Interfaces both must define one or more fields. + const fields = Object.values(type.getFields()); // Objects and Interfaces both must define one or more fields. + if (fields.length === 0) { context.reportError(`Type ${type.name} must define one or more fields.`, [type.astNode, ...type.extensionASTNodes]); } for (const field of fields) { // Ensure they are named correctly. - validateName(context, field); - // Ensure the type is an output type + validateName(context, field); // Ensure the type is an output type + if (!(0, _definition.isOutputType)(field.type)) { var _field$astNode; context.reportError(`The type of ${type.name}.${field.name} must be Output Type ` + `but got: ${(0, _inspect.inspect)(field.type)}.`, (_field$astNode = field.astNode) === null || _field$astNode === void 0 ? void 0 : _field$astNode.type); - } - // Ensure the arguments are valid + } // Ensure the arguments are valid + for (const arg of field.args) { - const argName = arg.name; - // Ensure they are named correctly. - validateName(context, arg); - // Ensure the type is an input type + const argName = arg.name; // Ensure they are named correctly. + + validateName(context, arg); // Ensure the type is an input type + if (!(0, _definition.isInputType)(arg.type)) { var _arg$astNode2; context.reportError(`The type of ${type.name}.${field.name}(${argName}:) must be Input ` + `Type but got: ${(0, _inspect.inspect)(arg.type)}.`, (_arg$astNode2 = arg.astNode) === null || _arg$astNode2 === void 0 ? void 0 : _arg$astNode2.type); @@ -34657,7 +33815,7 @@ function validateFields(context, type) { } } function validateInterfaces(context, type) { - const ifaceTypeNames = new Set(); + const ifaceTypeNames = Object.create(null); for (const iface of type.getInterfaces()) { if (!(0, _definition.isInterfaceType)(iface)) { context.reportError(`Type ${(0, _inspect.inspect)(type)} must only implement Interface types, ` + `it cannot implement ${(0, _inspect.inspect)(iface)}.`, getAllImplementsInterfaceNodes(type, iface)); @@ -34667,51 +33825,50 @@ function validateInterfaces(context, type) { context.reportError(`Type ${type.name} cannot implement itself because it would create a circular reference.`, getAllImplementsInterfaceNodes(type, iface)); continue; } - if (ifaceTypeNames.has(iface.name)) { + if (ifaceTypeNames[iface.name]) { context.reportError(`Type ${type.name} can only implement ${iface.name} once.`, getAllImplementsInterfaceNodes(type, iface)); continue; } - ifaceTypeNames.add(iface.name); + ifaceTypeNames[iface.name] = true; validateTypeImplementsAncestors(context, type, iface); validateTypeImplementsInterface(context, type, iface); } } function validateTypeImplementsInterface(context, type, iface) { - const typeFieldMap = type.getFields(); - // Assert each interface field is implemented. + const typeFieldMap = type.getFields(); // Assert each interface field is implemented. + for (const ifaceField of Object.values(iface.getFields())) { const fieldName = ifaceField.name; - const typeField = typeFieldMap[fieldName]; - // Assert interface field exists on type. - if (typeField == null) { + const typeField = typeFieldMap[fieldName]; // Assert interface field exists on type. + + if (!typeField) { context.reportError(`Interface field ${iface.name}.${fieldName} expected but ${type.name} does not provide it.`, [ifaceField.astNode, type.astNode, ...type.extensionASTNodes]); continue; - } - // Assert interface field type is satisfied by type field type, by being + } // Assert interface field type is satisfied by type field type, by being // a valid subtype. (covariant) + if (!(0, _typeComparators.isTypeSubTypeOf)(context.schema, typeField.type, ifaceField.type)) { var _ifaceField$astNode, _typeField$astNode; context.reportError(`Interface field ${iface.name}.${fieldName} expects type ` + `${(0, _inspect.inspect)(ifaceField.type)} but ${type.name}.${fieldName} ` + `is type ${(0, _inspect.inspect)(typeField.type)}.`, [(_ifaceField$astNode = ifaceField.astNode) === null || _ifaceField$astNode === void 0 ? void 0 : _ifaceField$astNode.type, (_typeField$astNode = typeField.astNode) === null || _typeField$astNode === void 0 ? void 0 : _typeField$astNode.type]); - } - // Assert each interface field arg is implemented. + } // Assert each interface field arg is implemented. + for (const ifaceArg of ifaceField.args) { const argName = ifaceArg.name; - const typeArg = typeField.args.find(arg => arg.name === argName); - // Assert interface field arg exists on object field. + const typeArg = typeField.args.find(arg => arg.name === argName); // Assert interface field arg exists on object field. + if (!typeArg) { context.reportError(`Interface field argument ${iface.name}.${fieldName}(${argName}:) expected but ${type.name}.${fieldName} does not provide it.`, [ifaceArg.astNode, typeField.astNode]); continue; - } - // Assert interface field arg type matches object field arg type. + } // Assert interface field arg type matches object field arg type. // (invariant) // TODO: change to contravariant? + if (!(0, _typeComparators.isEqualType)(ifaceArg.type, typeArg.type)) { var _ifaceArg$astNode, _typeArg$astNode; context.reportError(`Interface field argument ${iface.name}.${fieldName}(${argName}:) ` + `expects type ${(0, _inspect.inspect)(ifaceArg.type)} but ` + `${type.name}.${fieldName}(${argName}:) is type ` + `${(0, _inspect.inspect)(typeArg.type)}.`, [(_ifaceArg$astNode = ifaceArg.astNode) === null || _ifaceArg$astNode === void 0 ? void 0 : _ifaceArg$astNode.type, (_typeArg$astNode = typeArg.astNode) === null || _typeArg$astNode === void 0 ? void 0 : _typeArg$astNode.type]); - } - // TODO: validate default values? - } - // Assert additional arguments must not be required. + } // TODO: validate default values? + } // Assert additional arguments must not be required. + for (const typeArg of typeField.args) { const argName = typeArg.name; const ifaceArg = ifaceField.args.find(arg => arg.name === argName); @@ -34734,13 +33891,13 @@ function validateUnionMembers(context, union) { if (memberTypes.length === 0) { context.reportError(`Union type ${union.name} must define one or more member types.`, [union.astNode, ...union.extensionASTNodes]); } - const includedTypeNames = new Set(); + const includedTypeNames = Object.create(null); for (const memberType of memberTypes) { - if (includedTypeNames.has(memberType.name)) { + if (includedTypeNames[memberType.name]) { context.reportError(`Union type ${union.name} can only include type ${memberType.name} once.`, getUnionMemberTypeNodes(union, memberType.name)); continue; } - includedTypeNames.add(memberType.name); + includedTypeNames[memberType.name] = true; if (!(0, _definition.isObjectType)(memberType)) { context.reportError(`Union type ${union.name} can only include Object types, ` + `it cannot include ${(0, _inspect.inspect)(memberType)}.`, getUnionMemberTypeNodes(union, String(memberType))); } @@ -34760,12 +33917,12 @@ function validateInputFields(context, inputObj) { const fields = Object.values(inputObj.getFields()); if (fields.length === 0) { context.reportError(`Input Object type ${inputObj.name} must define one or more fields.`, [inputObj.astNode, ...inputObj.extensionASTNodes]); - } - // Ensure the arguments are valid + } // Ensure the arguments are valid + for (const field of fields) { // Ensure they are named correctly. - validateName(context, field); - // Ensure the type is an input type + validateName(context, field); // Ensure the type is an input type + if (!(0, _definition.isInputType)(field.type)) { var _field$astNode2; context.reportError(`The type of ${inputObj.name}.${field.name} must be Input Type ` + `but got: ${(0, _inspect.inspect)(field.type)}.`, (_field$astNode2 = field.astNode) === null || _field$astNode2 === void 0 ? void 0 : _field$astNode2.type); @@ -34792,20 +33949,20 @@ function createInputObjectCircularRefsValidator(context) { // Modified copy of algorithm from 'src/validation/rules/NoFragmentCycles.js'. // Tracks already visited types to maintain O(N) and to ensure that cycles // are not redundantly reported. - const visitedTypes = new Set(); - // Array of types nodes used to produce meaningful errors - const fieldPath = []; - // Position in the type path + const visitedTypes = Object.create(null); // Array of types nodes used to produce meaningful errors + + const fieldPath = []; // Position in the type path + const fieldPathIndexByTypeName = Object.create(null); - return detectCycleRecursive; - // This does a straight-forward DFS to find cycles. + return detectCycleRecursive; // This does a straight-forward DFS to find cycles. // It does not terminate when a cycle was found but continues to explore // the graph to find all possible cycles. + function detectCycleRecursive(inputObj) { - if (visitedTypes.has(inputObj)) { + if (visitedTypes[inputObj.name]) { return; } - visitedTypes.add(inputObj); + visitedTypes[inputObj.name] = true; fieldPathIndexByTypeName[inputObj.name] = fieldPath.length; const fields = Object.values(inputObj.getFields()); for (const field of fields) { @@ -34831,11 +33988,13 @@ function getAllImplementsInterfaceNodes(type, iface) { astNode, extensionASTNodes } = type; - const nodes = astNode != null ? [astNode, ...extensionASTNodes] : extensionASTNodes; - // FIXME: https://github.com/graphql/graphql-js/issues/2203 + const nodes = astNode != null ? [astNode, ...extensionASTNodes] : extensionASTNodes; // FIXME: https://github.com/graphql/graphql-js/issues/2203 + return nodes.flatMap(typeNode => { var _typeNode$interfaces; - return /* c8 ignore next */(_typeNode$interfaces = typeNode.interfaces) !== null && _typeNode$interfaces !== void 0 ? _typeNode$interfaces : []; + return /* c8 ignore next */( + (_typeNode$interfaces = typeNode.interfaces) !== null && _typeNode$interfaces !== void 0 ? _typeNode$interfaces : [] + ); }).filter(ifaceNode => ifaceNode.name.value === iface.name); } function getUnionMemberTypeNodes(union, typeName) { @@ -34843,11 +34002,13 @@ function getUnionMemberTypeNodes(union, typeName) { astNode, extensionASTNodes } = union; - const nodes = astNode != null ? [astNode, ...extensionASTNodes] : extensionASTNodes; - // FIXME: https://github.com/graphql/graphql-js/issues/2203 + const nodes = astNode != null ? [astNode, ...extensionASTNodes] : extensionASTNodes; // FIXME: https://github.com/graphql/graphql-js/issues/2203 + return nodes.flatMap(unionNode => { var _unionNode$types; - return /* c8 ignore next */(_unionNode$types = unionNode.types) !== null && _unionNode$types !== void 0 ? _unionNode$types : []; + return /* c8 ignore next */( + (_unionNode$types = unionNode.types) !== null && _unionNode$types !== void 0 ? _unionNode$types : [] + ); }).filter(typeNode => typeNode.name.value === typeName); } function getDeprecatedDirectiveNode(definitionNode) { @@ -34874,12 +34035,14 @@ var _ast = __webpack_require__(/*! ../language/ast.mjs */ "../../../node_modules var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); var _visitor = __webpack_require__(/*! ../language/visitor.mjs */ "../../../node_modules/graphql/language/visitor.mjs"); var _definition = __webpack_require__(/*! ../type/definition.mjs */ "../../../node_modules/graphql/type/definition.mjs"); +var _introspection = __webpack_require__(/*! ../type/introspection.mjs */ "../../../node_modules/graphql/type/introspection.mjs"); var _typeFromAST = __webpack_require__(/*! ./typeFromAST.mjs */ "../../../node_modules/graphql/utilities/typeFromAST.mjs"); /** * TypeInfo is a utility class which, given a GraphQL schema, can keep track * of the current field and type definitions at any point in a GraphQL document * AST during a recursive descent by calling `enter(node)` and `leave(node)`. */ + class TypeInfo { constructor(schema, /** @@ -34914,22 +34077,34 @@ class TypeInfo { return 'TypeInfo'; } getType() { - return this._typeStack.at(-1); + if (this._typeStack.length > 0) { + return this._typeStack[this._typeStack.length - 1]; + } } getParentType() { - return this._parentTypeStack.at(-1); + if (this._parentTypeStack.length > 0) { + return this._parentTypeStack[this._parentTypeStack.length - 1]; + } } getInputType() { - return this._inputTypeStack.at(-1); + if (this._inputTypeStack.length > 0) { + return this._inputTypeStack[this._inputTypeStack.length - 1]; + } } getParentInputType() { - return this._inputTypeStack.at(-2); + if (this._inputTypeStack.length > 1) { + return this._inputTypeStack[this._inputTypeStack.length - 2]; + } } getFieldDef() { - return this._fieldDefStack.at(-1); + if (this._fieldDefStack.length > 0) { + return this._fieldDefStack[this._fieldDefStack.length - 1]; + } } getDefaultValue() { - return this._defaultValueStack.at(-1); + if (this._defaultValueStack.length > 0) { + return this._defaultValueStack[this._defaultValueStack.length - 1]; + } } getDirective() { return this._directive; @@ -34941,11 +34116,11 @@ class TypeInfo { return this._enumValue; } enter(node) { - const schema = this._schema; - // Note: many of the types below are explicitly typed as "unknown" to drop + const schema = this._schema; // Note: many of the types below are explicitly typed as "unknown" to drop // any assumptions of a valid schema to ensure runtime types are properly // checked before continuing since TypeInfo is used as part of validation // which occurs before guarantees of schema and document validity. + switch (node.kind) { case _kinds.Kind.SELECTION_SET: { @@ -35011,8 +34186,8 @@ class TypeInfo { case _kinds.Kind.LIST: { const listType = (0, _definition.getNullableType)(this.getInputType()); - const itemType = (0, _definition.isListType)(listType) ? listType.ofType : listType; - // List positions never have a default value. + const itemType = (0, _definition.isListType)(listType) ? listType.ofType : listType; // List positions never have a default value. + this._defaultValueStack.push(undefined); this._inputTypeStack.push((0, _definition.isInputType)(itemType) ? itemType : undefined); break; @@ -35024,7 +34199,7 @@ class TypeInfo { let inputField; if ((0, _definition.isInputObjectType)(objectType)) { inputField = objectType.getFields()[node.name.value]; - if (inputField != null) { + if (inputField) { inputFieldType = inputField.type; } } @@ -35042,8 +34217,7 @@ class TypeInfo { this._enumValue = enumValue; break; } - default: - // Ignore other nodes + default: // Ignore other nodes } } leave(node) { @@ -35079,19 +34253,37 @@ class TypeInfo { case _kinds.Kind.ENUM: this._enumValue = null; break; - default: - // Ignore other nodes + default: // Ignore other nodes } } } + +/** + * Not exactly the same as the executor's definition of getFieldDef, in this + * statically evaluated environment we do not always have an Object type, + * and need to handle Interface and Union types. + */ exports.TypeInfo = TypeInfo; function getFieldDef(schema, parentType, fieldNode) { - return schema.getField(parentType, fieldNode.name.value); + const name = fieldNode.name.value; + if (name === _introspection.SchemaMetaFieldDef.name && schema.getQueryType() === parentType) { + return _introspection.SchemaMetaFieldDef; + } + if (name === _introspection.TypeMetaFieldDef.name && schema.getQueryType() === parentType) { + return _introspection.TypeMetaFieldDef; + } + if (name === _introspection.TypeNameMetaFieldDef.name && (0, _definition.isCompositeType)(parentType)) { + return _introspection.TypeNameMetaFieldDef; + } + if ((0, _definition.isObjectType)(parentType) || (0, _definition.isInterfaceType)(parentType)) { + return parentType.getFields()[name]; + } } /** * Creates a new visitor instance which maintains a provided TypeInfo instance * along with visiting visitor. */ + function visitWithTypeInfo(typeInfo, visitor) { return { enter(...args) { @@ -35124,6 +34316,56 @@ function visitWithTypeInfo(typeInfo, visitor) { /***/ }), +/***/ "../../../node_modules/graphql/utilities/assertValidName.mjs": +/*!*******************************************************************!*\ + !*** ../../../node_modules/graphql/utilities/assertValidName.mjs ***! + \*******************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports.assertValidName = assertValidName; +exports.isValidNameError = isValidNameError; +var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); +var _GraphQLError = __webpack_require__(/*! ../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); +var _assertName = __webpack_require__(/*! ../type/assertName.mjs */ "../../../node_modules/graphql/type/assertName.mjs"); +/* c8 ignore start */ + +/** + * Upholds the spec rules about naming. + * @deprecated Please use `assertName` instead. Will be removed in v17 + */ + +function assertValidName(name) { + const error = isValidNameError(name); + if (error) { + throw error; + } + return name; +} +/** + * Returns an Error if a name is invalid. + * @deprecated Please use `assertName` instead. Will be removed in v17 + */ + +function isValidNameError(name) { + typeof name === 'string' || (0, _devAssert.devAssert)(false, 'Expected name to be a string.'); + if (name.startsWith('__')) { + return new _GraphQLError.GraphQLError(`Name "${name}" must not begin with "__", which is reserved by GraphQL introspection.`); + } + try { + (0, _assertName.assertName)(name); + } catch (error) { + return error; + } +} +/* c8 ignore stop */ + +/***/ }), + /***/ "../../../node_modules/graphql/utilities/astFromValue.mjs": /*!****************************************************************!*\ !*** ../../../node_modules/graphql/utilities/astFromValue.mjs ***! @@ -35164,6 +34406,7 @@ var _scalars = __webpack_require__(/*! ../type/scalars.mjs */ "../../../node_mod * | null | NullValue | * */ + function astFromValue(value, type) { if ((0, _definition.isNonNullType)(type)) { const astValue = astFromValue(value, type.ofType); @@ -35171,19 +34414,19 @@ function astFromValue(value, type) { return null; } return astValue; - } - // only explicit null, not undefined, NaN + } // only explicit null, not undefined, NaN + if (value === null) { return { kind: _kinds.Kind.NULL }; - } - // undefined + } // undefined + if (value === undefined) { return null; - } - // Convert JavaScript array to GraphQL list. If the GraphQLType is a list, but + } // Convert JavaScript array to GraphQL list. If the GraphQLType is a list, but // the value is not an array, convert the value using the list's item type. + if ((0, _definition.isListType)(type)) { const itemType = type.ofType; if ((0, _isIterableObject.isIterableObject)(value)) { @@ -35200,9 +34443,9 @@ function astFromValue(value, type) { }; } return astFromValue(value, itemType); - } - // Populate the fields of the input object by creating ASTs from each value + } // Populate the fields of the input object by creating ASTs from each value // in the JavaScript object according to the fields in the input type. + if ((0, _definition.isInputObjectType)(type)) { if (!(0, _isObjectLike.isObjectLike)(value)) { return null; @@ -35232,15 +34475,15 @@ function astFromValue(value, type) { const serialized = type.serialize(value); if (serialized == null) { return null; - } - // Others serialize based on their corresponding JavaScript scalar types. + } // Others serialize based on their corresponding JavaScript scalar types. + if (typeof serialized === 'boolean') { return { kind: _kinds.Kind.BOOLEAN, value: serialized }; - } - // JavaScript numbers can be Int or Float values. + } // JavaScript numbers can be Int or Float values. + if (typeof serialized === 'number' && Number.isFinite(serialized)) { const stringNum = String(serialized); return integerStringRegExp.test(stringNum) ? { @@ -35258,8 +34501,8 @@ function astFromValue(value, type) { kind: _kinds.Kind.ENUM, value: serialized }; - } - // ID types can use Int literals. + } // ID types can use Int literals. + if (type === _scalars.GraphQLID && integerStringRegExp.test(serialized)) { return { kind: _kinds.Kind.INT, @@ -35275,6 +34518,7 @@ function astFromValue(value, type) { } /* c8 ignore next 3 */ // Not reachable, all possible types have been considered. + false || (0, _invariant.invariant)(false, 'Unexpected input type: ' + (0, _inspect.inspect)(type)); } /** @@ -35282,6 +34526,7 @@ function astFromValue(value, type) { * - NegativeSign? 0 * - NegativeSign? NonZeroDigit ( Digit+ )? */ + const integerStringRegExp = /^-?(?:0|[1-9][0-9]*)$/; /***/ }), @@ -35299,6 +34544,8 @@ Object.defineProperty(exports, "__esModule", ({ })); exports.buildASTSchema = buildASTSchema; exports.buildSchema = buildSchema; +var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); +var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); var _parser = __webpack_require__(/*! ../language/parser.mjs */ "../../../node_modules/graphql/language/parser.mjs"); var _directives = __webpack_require__(/*! ../type/directives.mjs */ "../../../node_modules/graphql/type/directives.mjs"); var _schema = __webpack_require__(/*! ../type/schema.mjs */ "../../../node_modules/graphql/type/schema.mjs"); @@ -35315,6 +34562,7 @@ var _extendSchema = __webpack_require__(/*! ./extendSchema.mjs */ "../../../node * has no resolve methods, so execution will use default resolvers. */ function buildASTSchema(documentAST, options) { + documentAST != null && documentAST.kind === _kinds.Kind.DOCUMENT || (0, _devAssert.devAssert)(false, 'Must provide valid Document AST.'); if ((options === null || options === void 0 ? void 0 : options.assumeValid) !== true && (options === null || options === void 0 ? void 0 : options.assumeValidSDL) !== true) { (0, _validate.assertValidSDL)(documentAST); } @@ -35360,6 +34608,7 @@ function buildASTSchema(documentAST, options) { * A helper function to build a GraphQLSchema directly from a source * document. */ + function buildSchema(source, options) { const document = (0, _parser.parse)(source, { noLocation: options === null || options === void 0 ? void 0 : options.noLocation, @@ -35408,50 +34657,49 @@ var _valueFromAST = __webpack_require__(/*! ./valueFromAST.mjs */ "../../../node * This function expects a complete introspection result. Don't forget to check * the "errors" field of a server response before calling this function. */ + function buildClientSchema(introspection, options) { - // Even though the `introspection` argument is typed, in most cases it's received - // as an untyped value from the server, so we will do an additional check here. - (0, _isObjectLike.isObjectLike)(introspection) && (0, _isObjectLike.isObjectLike)(introspection.__schema) || (0, _devAssert.devAssert)(false, `Invalid or incomplete introspection result. Ensure that you are passing "data" property of introspection response and no "errors" was returned alongside: ${(0, _inspect.inspect)(introspection)}.`); - // Get the schema from the introspection result. - const schemaIntrospection = introspection.__schema; - // Iterate through all types, getting the type definition for each. - const typeMap = new Map(schemaIntrospection.types.map(typeIntrospection => [typeIntrospection.name, buildType(typeIntrospection)])); - // Include standard types only if they are used. + (0, _isObjectLike.isObjectLike)(introspection) && (0, _isObjectLike.isObjectLike)(introspection.__schema) || (0, _devAssert.devAssert)(false, `Invalid or incomplete introspection result. Ensure that you are passing "data" property of introspection response and no "errors" was returned alongside: ${(0, _inspect.inspect)(introspection)}.`); // Get the schema from the introspection result. + + const schemaIntrospection = introspection.__schema; // Iterate through all types, getting the type definition for each. + + const typeMap = (0, _keyValMap.keyValMap)(schemaIntrospection.types, typeIntrospection => typeIntrospection.name, typeIntrospection => buildType(typeIntrospection)); // Include standard types only if they are used. + for (const stdType of [..._scalars.specifiedScalarTypes, ..._introspection.introspectionTypes]) { - if (typeMap.has(stdType.name)) { - typeMap.set(stdType.name, stdType); + if (typeMap[stdType.name]) { + typeMap[stdType.name] = stdType; } - } - // Get the root Query, Mutation, and Subscription types. - const queryType = schemaIntrospection.queryType != null ? getObjectType(schemaIntrospection.queryType) : null; - const mutationType = schemaIntrospection.mutationType != null ? getObjectType(schemaIntrospection.mutationType) : null; - const subscriptionType = schemaIntrospection.subscriptionType != null ? getObjectType(schemaIntrospection.subscriptionType) : null; - // Get the directives supported by Introspection, assuming empty-set if + } // Get the root Query, Mutation, and Subscription types. + + const queryType = schemaIntrospection.queryType ? getObjectType(schemaIntrospection.queryType) : null; + const mutationType = schemaIntrospection.mutationType ? getObjectType(schemaIntrospection.mutationType) : null; + const subscriptionType = schemaIntrospection.subscriptionType ? getObjectType(schemaIntrospection.subscriptionType) : null; // Get the directives supported by Introspection, assuming empty-set if // directives were not queried for. - const directives = schemaIntrospection.directives != null ? schemaIntrospection.directives.map(buildDirective) : []; - // Then produce and return a Schema with these types. + + const directives = schemaIntrospection.directives ? schemaIntrospection.directives.map(buildDirective) : []; // Then produce and return a Schema with these types. + return new _schema.GraphQLSchema({ description: schemaIntrospection.description, query: queryType, mutation: mutationType, subscription: subscriptionType, - types: [...typeMap.values()], + types: Object.values(typeMap), directives, assumeValid: options === null || options === void 0 ? void 0 : options.assumeValid - }); - // Given a type reference in introspection, return the GraphQLType instance. + }); // Given a type reference in introspection, return the GraphQLType instance. // preferring cached instances before building new instances. + function getType(typeRef) { if (typeRef.kind === _introspection.TypeKind.LIST) { const itemRef = typeRef.ofType; - if (itemRef == null) { + if (!itemRef) { throw new Error('Decorated type deeper than introspection query.'); } return new _definition.GraphQLList(getType(itemRef)); } if (typeRef.kind === _introspection.TypeKind.NON_NULL) { const nullableRef = typeRef.ofType; - if (nullableRef == null) { + if (!nullableRef) { throw new Error('Decorated type deeper than introspection query.'); } const nullableType = getType(nullableRef); @@ -35464,8 +34712,8 @@ function buildClientSchema(introspection, options) { if (!typeName) { throw new Error(`Unknown type reference: ${(0, _inspect.inspect)(typeRef)}.`); } - const type = typeMap.get(typeName); - if (type == null) { + const type = typeMap[typeName]; + if (!type) { throw new Error(`Invalid or incomplete schema, unknown type: ${typeName}. Ensure that a full introspection query is used in order to build a client schema.`); } return type; @@ -35475,9 +34723,9 @@ function buildClientSchema(introspection, options) { } function getInterfaceType(typeRef) { return (0, _definition.assertInterfaceType)(getNamedType(typeRef)); - } - // Given a type's introspection result, construct the correct + } // Given a type's introspection result, construct the correct // GraphQLType instance. + function buildType(type) { // eslint-disable-next-line @typescript-eslint/prefer-optional-chain if (type != null && type.name != null && type.kind != null) { @@ -35514,7 +34762,7 @@ function buildClientSchema(introspection, options) { if (implementingIntrospection.interfaces === null && implementingIntrospection.kind === _introspection.TypeKind.INTERFACE) { return []; } - if (implementingIntrospection.interfaces == null) { + if (!implementingIntrospection.interfaces) { const implementingIntrospectionStr = (0, _inspect.inspect)(implementingIntrospection); throw new Error(`Introspection result missing interfaces: ${implementingIntrospectionStr}.`); } @@ -35537,7 +34785,7 @@ function buildClientSchema(introspection, options) { }); } function buildUnionDef(unionIntrospection) { - if (unionIntrospection.possibleTypes == null) { + if (!unionIntrospection.possibleTypes) { const unionIntrospectionStr = (0, _inspect.inspect)(unionIntrospection); throw new Error(`Introspection result missing possibleTypes: ${unionIntrospectionStr}.`); } @@ -35548,7 +34796,7 @@ function buildClientSchema(introspection, options) { }); } function buildEnumDef(enumIntrospection) { - if (enumIntrospection.enumValues == null) { + if (!enumIntrospection.enumValues) { const enumIntrospectionStr = (0, _inspect.inspect)(enumIntrospection); throw new Error(`Introspection result missing enumValues: ${enumIntrospectionStr}.`); } @@ -35562,7 +34810,7 @@ function buildClientSchema(introspection, options) { }); } function buildInputObjectDef(inputObjectIntrospection) { - if (inputObjectIntrospection.inputFields == null) { + if (!inputObjectIntrospection.inputFields) { const inputObjectIntrospectionStr = (0, _inspect.inspect)(inputObjectIntrospection); throw new Error(`Introspection result missing inputFields: ${inputObjectIntrospectionStr}.`); } @@ -35574,7 +34822,7 @@ function buildClientSchema(introspection, options) { }); } function buildFieldDefMap(typeIntrospection) { - if (typeIntrospection.fields == null) { + if (!typeIntrospection.fields) { throw new Error(`Introspection result missing fields: ${(0, _inspect.inspect)(typeIntrospection)}.`); } return (0, _keyValMap.keyValMap)(typeIntrospection.fields, fieldIntrospection => fieldIntrospection.name, buildField); @@ -35585,7 +34833,7 @@ function buildClientSchema(introspection, options) { const typeStr = (0, _inspect.inspect)(type); throw new Error(`Introspection must provide output type for fields, but received: ${typeStr}.`); } - if (fieldIntrospection.args == null) { + if (!fieldIntrospection.args) { const fieldIntrospectionStr = (0, _inspect.inspect)(fieldIntrospection); throw new Error(`Introspection result missing field args: ${fieldIntrospectionStr}.`); } @@ -35614,11 +34862,11 @@ function buildClientSchema(introspection, options) { }; } function buildDirective(directiveIntrospection) { - if (directiveIntrospection.args == null) { + if (!directiveIntrospection.args) { const directiveIntrospectionStr = (0, _inspect.inspect)(directiveIntrospection); throw new Error(`Introspection result missing directive args: ${directiveIntrospectionStr}.`); } - if (directiveIntrospection.locations == null) { + if (!directiveIntrospection.locations) { const directiveIntrospectionStr = (0, _inspect.inspect)(directiveIntrospection); throw new Error(`Introspection result missing directive locations: ${directiveIntrospectionStr}.`); } @@ -35689,8 +34937,8 @@ function coerceInputValueImpl(inputValue, type, onError, path) { const itemPath = (0, _Path.addPath)(path, index, undefined); return coerceInputValueImpl(itemValue, itemType, onError, itemPath); }); - } - // Lists accept a non-list value as a list of one. + } // Lists accept a non-list value as a list of one. + return [coerceInputValueImpl(inputValue, itemType, onError, path)]; } if ((0, _definition.isInputObjectType)(type)) { @@ -35712,10 +34960,10 @@ function coerceInputValueImpl(inputValue, type, onError, path) { continue; } coercedValue[field.name] = coerceInputValueImpl(fieldValue, field.type, onError, (0, _Path.addPath)(path, field.name, type.name)); - } - // Ensure every provided field is defined. + } // Ensure every provided field is defined. + for (const fieldName of Object.keys(inputValue)) { - if (fieldDefs[fieldName] == null) { + if (!fieldDefs[fieldName]) { const suggestions = (0, _suggestionList.suggestionList)(fieldName, Object.keys(type.getFields())); onError((0, _Path.pathToArray)(path), inputValue, new _GraphQLError.GraphQLError(`Field "${fieldName}" is not defined by type "${type.name}".` + (0, _didYouMean.didYouMean)(suggestions))); } @@ -35734,10 +34982,10 @@ function coerceInputValueImpl(inputValue, type, onError, path) { return coercedValue; } if ((0, _definition.isLeafType)(type)) { - let parseResult; - // Scalars and Enums determine if an input value is valid via parseValue(), + let parseResult; // Scalars and Enums determine if a input value is valid via parseValue(), // which can throw to indicate failure. If it throws, maintain a reference // to the original error. + try { parseResult = type.parseValue(inputValue); } catch (error) { @@ -35757,6 +35005,7 @@ function coerceInputValueImpl(inputValue, type, onError, path) { } /* c8 ignore next 3 */ // Not reachable, all possible types have been considered. + false || (0, _invariant.invariant)(false, 'Unexpected input type: ' + (0, _inspect.inspect)(type)); } @@ -35780,6 +35029,7 @@ var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_mod * concatenate the ASTs together into batched AST, useful for validating many * GraphQL source files which together represent one conceptual application. */ + function concatAST(documents) { const definitions = []; for (const doc of documents) { @@ -35806,11 +35056,13 @@ Object.defineProperty(exports, "__esModule", ({ })); exports.extendSchema = extendSchema; exports.extendSchemaImpl = extendSchemaImpl; -var _AccumulatorMap = __webpack_require__(/*! ../jsutils/AccumulatorMap.mjs */ "../../../node_modules/graphql/jsutils/AccumulatorMap.mjs"); +var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); var _invariant = __webpack_require__(/*! ../jsutils/invariant.mjs */ "../../../node_modules/graphql/jsutils/invariant.mjs"); +var _keyMap = __webpack_require__(/*! ../jsutils/keyMap.mjs */ "../../../node_modules/graphql/jsutils/keyMap.mjs"); var _mapValue = __webpack_require__(/*! ../jsutils/mapValue.mjs */ "../../../node_modules/graphql/jsutils/mapValue.mjs"); var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); +var _predicates = __webpack_require__(/*! ../language/predicates.mjs */ "../../../node_modules/graphql/language/predicates.mjs"); var _definition = __webpack_require__(/*! ../type/definition.mjs */ "../../../node_modules/graphql/type/definition.mjs"); var _directives = __webpack_require__(/*! ../type/directives.mjs */ "../../../node_modules/graphql/type/directives.mjs"); var _introspection = __webpack_require__(/*! ../type/introspection.mjs */ "../../../node_modules/graphql/type/introspection.mjs"); @@ -35833,6 +35085,7 @@ var _valueFromAST = __webpack_require__(/*! ./valueFromAST.mjs */ "../../../node */ function extendSchema(schema, documentAST, options) { (0, _schema.assertSchema)(schema); + documentAST != null && documentAST.kind === _kinds.Kind.DOCUMENT || (0, _devAssert.devAssert)(false, 'Must provide valid Document AST.'); if ((options === null || options === void 0 ? void 0 : options.assumeValid) !== true && (options === null || options === void 0 ? void 0 : options.assumeValidSDL) !== true) { (0, _validate.assertValidSDLExtension)(documentAST, schema); } @@ -35843,77 +35096,47 @@ function extendSchema(schema, documentAST, options) { /** * @internal */ + function extendSchemaImpl(schemaConfig, documentAST, options) { - var _schemaDef$descriptio, _schemaDef, _schemaDef$descriptio2, _schemaDef2, _options$assumeValid; + var _schemaDef, _schemaDef$descriptio, _schemaDef2, _options$assumeValid; + // Collect the type definitions and extensions found in the document. const typeDefs = []; - const scalarExtensions = new _AccumulatorMap.AccumulatorMap(); - const objectExtensions = new _AccumulatorMap.AccumulatorMap(); - const interfaceExtensions = new _AccumulatorMap.AccumulatorMap(); - const unionExtensions = new _AccumulatorMap.AccumulatorMap(); - const enumExtensions = new _AccumulatorMap.AccumulatorMap(); - const inputObjectExtensions = new _AccumulatorMap.AccumulatorMap(); - // New directives and types are separate because a directives and types can + const typeExtensionsMap = Object.create(null); // New directives and types are separate because a directives and types can // have the same name. For example, a type named "skip". + const directiveDefs = []; - let schemaDef; - // Schema extensions are collected which may add additional operation types. + let schemaDef; // Schema extensions are collected which may add additional operation types. + const schemaExtensions = []; - let isSchemaChanged = false; for (const def of documentAST.definitions) { - switch (def.kind) { - case _kinds.Kind.SCHEMA_DEFINITION: - schemaDef = def; - break; - case _kinds.Kind.SCHEMA_EXTENSION: - schemaExtensions.push(def); - break; - case _kinds.Kind.DIRECTIVE_DEFINITION: - directiveDefs.push(def); - break; - // Type Definitions - case _kinds.Kind.SCALAR_TYPE_DEFINITION: - case _kinds.Kind.OBJECT_TYPE_DEFINITION: - case _kinds.Kind.INTERFACE_TYPE_DEFINITION: - case _kinds.Kind.UNION_TYPE_DEFINITION: - case _kinds.Kind.ENUM_TYPE_DEFINITION: - case _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION: - typeDefs.push(def); - break; - // Type System Extensions - case _kinds.Kind.SCALAR_TYPE_EXTENSION: - scalarExtensions.add(def.name.value, def); - break; - case _kinds.Kind.OBJECT_TYPE_EXTENSION: - objectExtensions.add(def.name.value, def); - break; - case _kinds.Kind.INTERFACE_TYPE_EXTENSION: - interfaceExtensions.add(def.name.value, def); - break; - case _kinds.Kind.UNION_TYPE_EXTENSION: - unionExtensions.add(def.name.value, def); - break; - case _kinds.Kind.ENUM_TYPE_EXTENSION: - enumExtensions.add(def.name.value, def); - break; - case _kinds.Kind.INPUT_OBJECT_TYPE_EXTENSION: - inputObjectExtensions.add(def.name.value, def); - break; - default: - continue; + if (def.kind === _kinds.Kind.SCHEMA_DEFINITION) { + schemaDef = def; + } else if (def.kind === _kinds.Kind.SCHEMA_EXTENSION) { + schemaExtensions.push(def); + } else if ((0, _predicates.isTypeDefinitionNode)(def)) { + typeDefs.push(def); + } else if ((0, _predicates.isTypeExtensionNode)(def)) { + const extendedTypeName = def.name.value; + const existingTypeExtensions = typeExtensionsMap[extendedTypeName]; + typeExtensionsMap[extendedTypeName] = existingTypeExtensions ? existingTypeExtensions.concat([def]) : [def]; + } else if (def.kind === _kinds.Kind.DIRECTIVE_DEFINITION) { + directiveDefs.push(def); } - isSchemaChanged = true; - } - // If this document contains no new types, extensions, or directives then + } // If this document contains no new types, extensions, or directives then // return the same unmodified GraphQLSchema instance. - if (!isSchemaChanged) { + + if (Object.keys(typeExtensionsMap).length === 0 && typeDefs.length === 0 && directiveDefs.length === 0 && schemaExtensions.length === 0 && schemaDef == null) { return schemaConfig; } - const typeMap = new Map(schemaConfig.types.map(type => [type.name, extendNamedType(type)])); + const typeMap = Object.create(null); + for (const existingType of schemaConfig.types) { + typeMap[existingType.name] = extendNamedType(existingType); + } for (const typeNode of typeDefs) { - var _stdTypeMap$get; + var _stdTypeMap$name; const name = typeNode.name.value; - typeMap.set(name, (_stdTypeMap$get = stdTypeMap.get(name)) !== null && _stdTypeMap$get !== void 0 ? _stdTypeMap$get : buildType(typeNode)); + typeMap[name] = (_stdTypeMap$name = stdTypeMap[name]) !== null && _stdTypeMap$name !== void 0 ? _stdTypeMap$name : buildType(typeNode); } const operationTypes = { // Get the extended root operation types. @@ -35923,20 +35146,20 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { // Then, incorporate schema definition and all schema extensions. ...(schemaDef && getOperationTypes([schemaDef])), ...getOperationTypes(schemaExtensions) - }; - // Then produce and return a Schema config with these types. + }; // Then produce and return a Schema config with these types. + return { - description: (_schemaDef$descriptio = (_schemaDef = schemaDef) === null || _schemaDef === void 0 ? void 0 : (_schemaDef$descriptio2 = _schemaDef.description) === null || _schemaDef$descriptio2 === void 0 ? void 0 : _schemaDef$descriptio2.value) !== null && _schemaDef$descriptio !== void 0 ? _schemaDef$descriptio : schemaConfig.description, + description: (_schemaDef = schemaDef) === null || _schemaDef === void 0 ? void 0 : (_schemaDef$descriptio = _schemaDef.description) === null || _schemaDef$descriptio === void 0 ? void 0 : _schemaDef$descriptio.value, ...operationTypes, - types: Array.from(typeMap.values()), + types: Object.values(typeMap), directives: [...schemaConfig.directives.map(replaceDirective), ...directiveDefs.map(buildDirective)], - extensions: schemaConfig.extensions, + extensions: Object.create(null), astNode: (_schemaDef2 = schemaDef) !== null && _schemaDef2 !== void 0 ? _schemaDef2 : schemaConfig.astNode, extensionASTNodes: schemaConfig.extensionASTNodes.concat(schemaExtensions), assumeValid: (_options$assumeValid = options === null || options === void 0 ? void 0 : options.assumeValid) !== null && _options$assumeValid !== void 0 ? _options$assumeValid : false - }; - // Below are functions used for producing this schema that have closed over + }; // Below are functions used for producing this schema that have closed over // this scope and have access to the schema, cache, and newly defined types. + function replaceType(type) { if ((0, _definition.isListType)(type)) { // @ts-expect-error @@ -35945,21 +35168,17 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { if ((0, _definition.isNonNullType)(type)) { // @ts-expect-error return new _definition.GraphQLNonNull(replaceType(type.ofType)); - } - // @ts-expect-error FIXME + } // @ts-expect-error FIXME + return replaceNamedType(type); } function replaceNamedType(type) { // Note: While this could make early assertions to get the correctly // typed values, that would throw immediately while type system // validation with validateSchema() will produce more actionable results. - return typeMap.get(type.name); + return typeMap[type.name]; } function replaceDirective(directive) { - if ((0, _directives.isSpecifiedDirective)(directive)) { - // Builtin directives are not extended. - return directive; - } const config = directive.toConfig(); return new _directives.GraphQLDirective({ ...config, @@ -35991,12 +35210,13 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { } /* c8 ignore next 3 */ // Not reachable, all possible type definition nodes have been considered. + false || (0, _invariant.invariant)(false, 'Unexpected type: ' + (0, _inspect.inspect)(type)); } function extendInputObjectType(type) { - var _inputObjectExtension; + var _typeExtensionsMap$co; const config = type.toConfig(); - const extensions = (_inputObjectExtension = inputObjectExtensions.get(config.name)) !== null && _inputObjectExtension !== void 0 ? _inputObjectExtension : []; + const extensions = (_typeExtensionsMap$co = typeExtensionsMap[config.name]) !== null && _typeExtensionsMap$co !== void 0 ? _typeExtensionsMap$co : []; return new _definition.GraphQLInputObjectType({ ...config, fields: () => ({ @@ -36010,9 +35230,9 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { }); } function extendEnumType(type) { - var _enumExtensions$get; + var _typeExtensionsMap$ty; const config = type.toConfig(); - const extensions = (_enumExtensions$get = enumExtensions.get(type.name)) !== null && _enumExtensions$get !== void 0 ? _enumExtensions$get : []; + const extensions = (_typeExtensionsMap$ty = typeExtensionsMap[type.name]) !== null && _typeExtensionsMap$ty !== void 0 ? _typeExtensionsMap$ty : []; return new _definition.GraphQLEnumType({ ...config, values: { @@ -36023,9 +35243,9 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { }); } function extendScalarType(type) { - var _scalarExtensions$get; + var _typeExtensionsMap$co2; const config = type.toConfig(); - const extensions = (_scalarExtensions$get = scalarExtensions.get(config.name)) !== null && _scalarExtensions$get !== void 0 ? _scalarExtensions$get : []; + const extensions = (_typeExtensionsMap$co2 = typeExtensionsMap[config.name]) !== null && _typeExtensionsMap$co2 !== void 0 ? _typeExtensionsMap$co2 : []; let specifiedByURL = config.specifiedByURL; for (const extensionNode of extensions) { var _getSpecifiedByURL; @@ -36038,9 +35258,9 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { }); } function extendObjectType(type) { - var _objectExtensions$get; + var _typeExtensionsMap$co3; const config = type.toConfig(); - const extensions = (_objectExtensions$get = objectExtensions.get(config.name)) !== null && _objectExtensions$get !== void 0 ? _objectExtensions$get : []; + const extensions = (_typeExtensionsMap$co3 = typeExtensionsMap[config.name]) !== null && _typeExtensionsMap$co3 !== void 0 ? _typeExtensionsMap$co3 : []; return new _definition.GraphQLObjectType({ ...config, interfaces: () => [...type.getInterfaces().map(replaceNamedType), ...buildInterfaces(extensions)], @@ -36052,9 +35272,9 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { }); } function extendInterfaceType(type) { - var _interfaceExtensions$; + var _typeExtensionsMap$co4; const config = type.toConfig(); - const extensions = (_interfaceExtensions$ = interfaceExtensions.get(config.name)) !== null && _interfaceExtensions$ !== void 0 ? _interfaceExtensions$ : []; + const extensions = (_typeExtensionsMap$co4 = typeExtensionsMap[config.name]) !== null && _typeExtensionsMap$co4 !== void 0 ? _typeExtensionsMap$co4 : []; return new _definition.GraphQLInterfaceType({ ...config, interfaces: () => [...type.getInterfaces().map(replaceNamedType), ...buildInterfaces(extensions)], @@ -36066,9 +35286,9 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { }); } function extendUnionType(type) { - var _unionExtensions$get; + var _typeExtensionsMap$co5; const config = type.toConfig(); - const extensions = (_unionExtensions$get = unionExtensions.get(config.name)) !== null && _unionExtensions$get !== void 0 ? _unionExtensions$get : []; + const extensions = (_typeExtensionsMap$co5 = typeExtensionsMap[config.name]) !== null && _typeExtensionsMap$co5 !== void 0 ? _typeExtensionsMap$co5 : []; return new _definition.GraphQLUnionType({ ...config, types: () => [...type.getTypes().map(replaceNamedType), ...buildUnionTypes(extensions)], @@ -36092,8 +35312,10 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { const opTypes = {}; for (const node of nodes) { var _node$operationTypes; + // FIXME: https://github.com/graphql/graphql-js/issues/2203 - const operationTypesNodes = /* c8 ignore next */(_node$operationTypes = node.operationTypes) !== null && _node$operationTypes !== void 0 ? _node$operationTypes : []; + const operationTypesNodes = /* c8 ignore next */ + (_node$operationTypes = node.operationTypes) !== null && _node$operationTypes !== void 0 ? _node$operationTypes : []; for (const operationType of operationTypesNodes) { // Note: While this could make early assertions to get the correctly // typed values below, that would throw immediately while type system @@ -36105,9 +35327,9 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { return opTypes; } function getNamedType(node) { - var _stdTypeMap$get2; + var _stdTypeMap$name2; const name = node.name.value; - const type = (_stdTypeMap$get2 = stdTypeMap.get(name)) !== null && _stdTypeMap$get2 !== void 0 ? _stdTypeMap$get2 : typeMap.get(name); + const type = (_stdTypeMap$name2 = stdTypeMap[name]) !== null && _stdTypeMap$name2 !== void 0 ? _stdTypeMap$name2 : typeMap[name]; if (type === undefined) { throw new Error(`Unknown type: "${name}".`); } @@ -36140,8 +35362,10 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { const fieldConfigMap = Object.create(null); for (const node of nodes) { var _node$fields; + // FIXME: https://github.com/graphql/graphql-js/issues/2203 - const nodeFields = /* c8 ignore next */(_node$fields = node.fields) !== null && _node$fields !== void 0 ? _node$fields : []; + const nodeFields = /* c8 ignore next */ + (_node$fields = node.fields) !== null && _node$fields !== void 0 ? _node$fields : []; for (const field of nodeFields) { var _field$description; fieldConfigMap[field.name.value] = { @@ -36160,10 +35384,12 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { } function buildArgumentMap(args) { // FIXME: https://github.com/graphql/graphql-js/issues/2203 - const argsNodes = /* c8 ignore next */args !== null && args !== void 0 ? args : []; + const argsNodes = /* c8 ignore next */ + args !== null && args !== void 0 ? args : []; const argConfigMap = Object.create(null); for (const arg of argsNodes) { var _arg$description; + // Note: While this could make assertions to get the correctly typed // value, that would throw immediately while type system validation // with validateSchema() will produce more actionable results. @@ -36182,10 +35408,13 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { const inputFieldMap = Object.create(null); for (const node of nodes) { var _node$fields2; + // FIXME: https://github.com/graphql/graphql-js/issues/2203 - const fieldsNodes = /* c8 ignore next */(_node$fields2 = node.fields) !== null && _node$fields2 !== void 0 ? _node$fields2 : []; + const fieldsNodes = /* c8 ignore next */ + (_node$fields2 = node.fields) !== null && _node$fields2 !== void 0 ? _node$fields2 : []; for (const field of fieldsNodes) { var _field$description2; + // Note: While this could make assertions to get the correctly typed // value, that would throw immediately while type system validation // with validateSchema() will produce more actionable results. @@ -36205,8 +35434,10 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { const enumValueMap = Object.create(null); for (const node of nodes) { var _node$values; + // FIXME: https://github.com/graphql/graphql-js/issues/2203 - const valuesNodes = /* c8 ignore next */(_node$values = node.values) !== null && _node$values !== void 0 ? _node$values : []; + const valuesNodes = /* c8 ignore next */ + (_node$values = node.values) !== null && _node$values !== void 0 ? _node$values : []; for (const value of valuesNodes) { var _value$description; enumValueMap[value.name.value] = { @@ -36227,7 +35458,9 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { // FIXME: https://github.com/graphql/graphql-js/issues/2203 node => { var _node$interfaces$map, _node$interfaces; - return /* c8 ignore next */(_node$interfaces$map = (_node$interfaces = node.interfaces) === null || _node$interfaces === void 0 ? void 0 : _node$interfaces.map(getNamedType)) !== null && _node$interfaces$map !== void 0 ? _node$interfaces$map : []; + return /* c8 ignore next */( + (_node$interfaces$map = (_node$interfaces = node.interfaces) === null || _node$interfaces === void 0 ? void 0 : _node$interfaces.map(getNamedType)) !== null && _node$interfaces$map !== void 0 ? _node$interfaces$map : [] + ); }); } function buildUnionTypes(nodes) { @@ -36239,16 +35472,19 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { // FIXME: https://github.com/graphql/graphql-js/issues/2203 node => { var _node$types$map, _node$types; - return /* c8 ignore next */(_node$types$map = (_node$types = node.types) === null || _node$types === void 0 ? void 0 : _node$types.map(getNamedType)) !== null && _node$types$map !== void 0 ? _node$types$map : []; + return /* c8 ignore next */( + (_node$types$map = (_node$types = node.types) === null || _node$types === void 0 ? void 0 : _node$types.map(getNamedType)) !== null && _node$types$map !== void 0 ? _node$types$map : [] + ); }); } function buildType(astNode) { + var _typeExtensionsMap$na; const name = astNode.name.value; + const extensionASTNodes = (_typeExtensionsMap$na = typeExtensionsMap[name]) !== null && _typeExtensionsMap$na !== void 0 ? _typeExtensionsMap$na : []; switch (astNode.kind) { case _kinds.Kind.OBJECT_TYPE_DEFINITION: { - var _objectExtensions$get2, _astNode$description; - const extensionASTNodes = (_objectExtensions$get2 = objectExtensions.get(name)) !== null && _objectExtensions$get2 !== void 0 ? _objectExtensions$get2 : []; + var _astNode$description; const allNodes = [astNode, ...extensionASTNodes]; return new _definition.GraphQLObjectType({ name, @@ -36261,8 +35497,7 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { } case _kinds.Kind.INTERFACE_TYPE_DEFINITION: { - var _interfaceExtensions$2, _astNode$description2; - const extensionASTNodes = (_interfaceExtensions$2 = interfaceExtensions.get(name)) !== null && _interfaceExtensions$2 !== void 0 ? _interfaceExtensions$2 : []; + var _astNode$description2; const allNodes = [astNode, ...extensionASTNodes]; return new _definition.GraphQLInterfaceType({ name, @@ -36275,8 +35510,7 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { } case _kinds.Kind.ENUM_TYPE_DEFINITION: { - var _enumExtensions$get2, _astNode$description3; - const extensionASTNodes = (_enumExtensions$get2 = enumExtensions.get(name)) !== null && _enumExtensions$get2 !== void 0 ? _enumExtensions$get2 : []; + var _astNode$description3; const allNodes = [astNode, ...extensionASTNodes]; return new _definition.GraphQLEnumType({ name, @@ -36288,8 +35522,7 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { } case _kinds.Kind.UNION_TYPE_DEFINITION: { - var _unionExtensions$get2, _astNode$description4; - const extensionASTNodes = (_unionExtensions$get2 = unionExtensions.get(name)) !== null && _unionExtensions$get2 !== void 0 ? _unionExtensions$get2 : []; + var _astNode$description4; const allNodes = [astNode, ...extensionASTNodes]; return new _definition.GraphQLUnionType({ name, @@ -36301,8 +35534,7 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { } case _kinds.Kind.SCALAR_TYPE_DEFINITION: { - var _scalarExtensions$get2, _astNode$description5; - const extensionASTNodes = (_scalarExtensions$get2 = scalarExtensions.get(name)) !== null && _scalarExtensions$get2 !== void 0 ? _scalarExtensions$get2 : []; + var _astNode$description5; return new _definition.GraphQLScalarType({ name, description: (_astNode$description5 = astNode.description) === null || _astNode$description5 === void 0 ? void 0 : _astNode$description5.value, @@ -36313,8 +35545,7 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { } case _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION: { - var _inputObjectExtension2, _astNode$description6; - const extensionASTNodes = (_inputObjectExtension2 = inputObjectExtensions.get(name)) !== null && _inputObjectExtension2 !== void 0 ? _inputObjectExtension2 : []; + var _astNode$description6; const allNodes = [astNode, ...extensionASTNodes]; return new _definition.GraphQLInputObjectType({ name, @@ -36328,27 +35559,30 @@ function extendSchemaImpl(schemaConfig, documentAST, options) { } } } -const stdTypeMap = new Map([..._scalars.specifiedScalarTypes, ..._introspection.introspectionTypes].map(type => [type.name, type])); +const stdTypeMap = (0, _keyMap.keyMap)([..._scalars.specifiedScalarTypes, ..._introspection.introspectionTypes], type => type.name); /** * Given a field or enum value node, returns the string value for the * deprecation reason. */ + function getDeprecationReason(node) { - const deprecated = (0, _values.getDirectiveValues)(_directives.GraphQLDeprecatedDirective, node); - // @ts-expect-error validated by `getDirectiveValues` + const deprecated = (0, _values.getDirectiveValues)(_directives.GraphQLDeprecatedDirective, node); // @ts-expect-error validated by `getDirectiveValues` + return deprecated === null || deprecated === void 0 ? void 0 : deprecated.reason; } /** * Given a scalar node, returns the string value for the specifiedByURL. */ + function getSpecifiedByURL(node) { - const specifiedBy = (0, _values.getDirectiveValues)(_directives.GraphQLSpecifiedByDirective, node); - // @ts-expect-error validated by `getDirectiveValues` + const specifiedBy = (0, _values.getDirectiveValues)(_directives.GraphQLSpecifiedByDirective, node); // @ts-expect-error validated by `getDirectiveValues` + return specifiedBy === null || specifiedBy === void 0 ? void 0 : specifiedBy.url; } /** * Given an input object node, returns if the node should be OneOf. */ + function isOneOf(node) { return Boolean((0, _values.getDirectiveValues)(_directives.GraphQLOneOfDirective, node)); } @@ -36417,6 +35651,7 @@ function findBreakingChanges(oldSchema, newSchema) { * Given two schemas, returns an Array containing descriptions of all the types * of potentially dangerous changes covered by the other functions down below. */ + function findDangerousChanges(oldSchema, newSchema) { // @ts-expect-error return findSchemaChanges(oldSchema, newSchema).filter(change => change.type in DangerousChangeType); @@ -36685,8 +35920,8 @@ function isChangeSafeForInputObjectFieldOrFieldArg(oldType, newType) { // moving from non-null to nullable of the same underlying type is safe !(0, _definition.isNonNullType)(newType) && isChangeSafeForInputObjectFieldOrFieldArg(oldType.ofType, newType) ); - } - // if they're both named types, see if their names are equivalent + } // if they're both named types, see if their names are equivalent + return (0, _definition.isNamedType)(newType) && oldType.name === newType.name; } function typeKindName(type) { @@ -36710,6 +35945,7 @@ function typeKindName(type) { } /* c8 ignore next 3 */ // Not reachable, all possible types have been considered. + false || (0, _invariant.invariant)(false, 'Unexpected type: ' + (0, _inspect.inspect)(type)); } function stringifyValue(value, type) { @@ -36912,6 +36148,7 @@ var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_mod * name. If a name is not provided, an operation is only returned if only one is * provided in the document. */ + function getOperationAST(documentAST, operationName) { let operation = null; for (const definition of documentAST.definitions) { @@ -36935,6 +36172,59 @@ function getOperationAST(documentAST, operationName) { /***/ }), +/***/ "../../../node_modules/graphql/utilities/getOperationRootType.mjs": +/*!************************************************************************!*\ + !*** ../../../node_modules/graphql/utilities/getOperationRootType.mjs ***! + \************************************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports.getOperationRootType = getOperationRootType; +var _GraphQLError = __webpack_require__(/*! ../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); +/** + * Extracts the root type of the operation from the schema. + * + * @deprecated Please use `GraphQLSchema.getRootType` instead. Will be removed in v17 + */ +function getOperationRootType(schema, operation) { + if (operation.operation === 'query') { + const queryType = schema.getQueryType(); + if (!queryType) { + throw new _GraphQLError.GraphQLError('Schema does not define the required query root type.', { + nodes: operation + }); + } + return queryType; + } + if (operation.operation === 'mutation') { + const mutationType = schema.getMutationType(); + if (!mutationType) { + throw new _GraphQLError.GraphQLError('Schema is not configured for mutations.', { + nodes: operation + }); + } + return mutationType; + } + if (operation.operation === 'subscription') { + const subscriptionType = schema.getSubscriptionType(); + if (!subscriptionType) { + throw new _GraphQLError.GraphQLError('Schema is not configured for subscriptions.', { + nodes: operation + }); + } + return subscriptionType; + } + throw new _GraphQLError.GraphQLError('Can only have query, mutation and subscription operations.', { + nodes: operation + }); +} + +/***/ }), + /***/ "../../../node_modules/graphql/utilities/index.mjs": /*!*********************************************************!*\ !*** ../../../node_modules/graphql/utilities/index.mjs ***! @@ -36964,6 +36254,12 @@ Object.defineProperty(exports, "TypeInfo", ({ return _TypeInfo.TypeInfo; } })); +Object.defineProperty(exports, "assertValidName", ({ + enumerable: true, + get: function () { + return _assertValidName.assertValidName; + } +})); Object.defineProperty(exports, "astFromValue", ({ enumerable: true, get: function () { @@ -37036,6 +36332,12 @@ Object.defineProperty(exports, "getOperationAST", ({ return _getOperationAST.getOperationAST; } })); +Object.defineProperty(exports, "getOperationRootType", ({ + enumerable: true, + get: function () { + return _getOperationRootType.getOperationRootType; + } +})); Object.defineProperty(exports, "introspectionFromSchema", ({ enumerable: true, get: function () { @@ -37054,18 +36356,18 @@ Object.defineProperty(exports, "isTypeSubTypeOf", ({ return _typeComparators.isTypeSubTypeOf; } })); +Object.defineProperty(exports, "isValidNameError", ({ + enumerable: true, + get: function () { + return _assertValidName.isValidNameError; + } +})); Object.defineProperty(exports, "lexicographicSortSchema", ({ enumerable: true, get: function () { return _lexicographicSortSchema.lexicographicSortSchema; } })); -Object.defineProperty(exports, "printDirective", ({ - enumerable: true, - get: function () { - return _printSchema.printDirective; - } -})); Object.defineProperty(exports, "printIntrospectionSchema", ({ enumerable: true, get: function () { @@ -37122,6 +36424,7 @@ Object.defineProperty(exports, "visitWithTypeInfo", ({ })); var _getIntrospectionQuery = __webpack_require__(/*! ./getIntrospectionQuery.mjs */ "../../../node_modules/graphql/utilities/getIntrospectionQuery.mjs"); var _getOperationAST = __webpack_require__(/*! ./getOperationAST.mjs */ "../../../node_modules/graphql/utilities/getOperationAST.mjs"); +var _getOperationRootType = __webpack_require__(/*! ./getOperationRootType.mjs */ "../../../node_modules/graphql/utilities/getOperationRootType.mjs"); var _introspectionFromSchema = __webpack_require__(/*! ./introspectionFromSchema.mjs */ "../../../node_modules/graphql/utilities/introspectionFromSchema.mjs"); var _buildClientSchema = __webpack_require__(/*! ./buildClientSchema.mjs */ "../../../node_modules/graphql/utilities/buildClientSchema.mjs"); var _buildASTSchema = __webpack_require__(/*! ./buildASTSchema.mjs */ "../../../node_modules/graphql/utilities/buildASTSchema.mjs"); @@ -37138,6 +36441,7 @@ var _concatAST = __webpack_require__(/*! ./concatAST.mjs */ "../../../node_modul var _separateOperations = __webpack_require__(/*! ./separateOperations.mjs */ "../../../node_modules/graphql/utilities/separateOperations.mjs"); var _stripIgnoredCharacters = __webpack_require__(/*! ./stripIgnoredCharacters.mjs */ "../../../node_modules/graphql/utilities/stripIgnoredCharacters.mjs"); var _typeComparators = __webpack_require__(/*! ./typeComparators.mjs */ "../../../node_modules/graphql/utilities/typeComparators.mjs"); +var _assertValidName = __webpack_require__(/*! ./assertValidName.mjs */ "../../../node_modules/graphql/utilities/assertValidName.mjs"); var _findBreakingChanges = __webpack_require__(/*! ./findBreakingChanges.mjs */ "../../../node_modules/graphql/utilities/findBreakingChanges.mjs"); /***/ }), @@ -37167,6 +36471,7 @@ var _getIntrospectionQuery = __webpack_require__(/*! ./getIntrospectionQuery.mjs * This is the inverse of buildClientSchema. The primary use case is outside * of the server context, for instance when doing schema comparisons. */ + function introspectionFromSchema(schema, options) { const optionsWithDefaults = { specifiedByUrl: true, @@ -37181,7 +36486,7 @@ function introspectionFromSchema(schema, options) { schema, document }); - result.errors == null && result.data != null || (0, _invariant.invariant)(false); + !result.errors && result.data || (0, _invariant.invariant)(false); return result.data; } @@ -37201,6 +36506,7 @@ Object.defineProperty(exports, "__esModule", ({ exports.lexicographicSortSchema = lexicographicSortSchema; var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); var _invariant = __webpack_require__(/*! ../jsutils/invariant.mjs */ "../../../node_modules/graphql/jsutils/invariant.mjs"); +var _keyValMap = __webpack_require__(/*! ../jsutils/keyValMap.mjs */ "../../../node_modules/graphql/jsutils/keyValMap.mjs"); var _naturalCompare = __webpack_require__(/*! ../jsutils/naturalCompare.mjs */ "../../../node_modules/graphql/jsutils/naturalCompare.mjs"); var _definition = __webpack_require__(/*! ../type/definition.mjs */ "../../../node_modules/graphql/type/definition.mjs"); var _directives = __webpack_require__(/*! ../type/directives.mjs */ "../../../node_modules/graphql/type/directives.mjs"); @@ -37211,12 +36517,13 @@ var _schema = __webpack_require__(/*! ../type/schema.mjs */ "../../../node_modul * * This function returns a sorted copy of the given GraphQLSchema. */ + function lexicographicSortSchema(schema) { const schemaConfig = schema.toConfig(); - const typeMap = new Map(sortByName(schemaConfig.types).map(type => [type.name, sortNamedType(type)])); + const typeMap = (0, _keyValMap.keyValMap)(sortByName(schemaConfig.types), type => type.name, sortNamedType); return new _schema.GraphQLSchema({ ...schemaConfig, - types: Array.from(typeMap.values()), + types: Object.values(typeMap), directives: sortByName(schemaConfig.directives).map(sortDirective), query: replaceMaybeType(schemaConfig.query), mutation: replaceMaybeType(schemaConfig.mutation), @@ -37229,12 +36536,12 @@ function lexicographicSortSchema(schema) { } else if ((0, _definition.isNonNullType)(type)) { // @ts-expect-error return new _definition.GraphQLNonNull(replaceType(type.ofType)); - } - // @ts-expect-error FIXME: TS Conversion + } // @ts-expect-error FIXME: TS Conversion + return replaceNamedType(type); } function replaceNamedType(type) { - return typeMap.get(type.name); + return typeMap[type.name]; } function replaceMaybeType(maybeType) { return maybeType && replaceNamedType(maybeType); @@ -37312,6 +36619,7 @@ function lexicographicSortSchema(schema) { } /* c8 ignore next 3 */ // Not reachable, all possible types have been considered. + false || (0, _invariant.invariant)(false, 'Unexpected type: ' + (0, _inspect.inspect)(type)); } } @@ -37346,7 +36654,6 @@ function sortBy(array, mapToKey) { Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.printDirective = printDirective; exports.printIntrospectionSchema = printIntrospectionSchema; exports.printSchema = printSchema; exports.printType = printType; @@ -37375,19 +36682,23 @@ function printFilteredSchema(schema, directiveFilter, typeFilter) { return [printSchemaDefinition(schema), ...directives.map(directive => printDirective(directive)), ...types.map(type => printType(type))].filter(Boolean).join('\n\n'); } function printSchemaDefinition(schema) { - const queryType = schema.getQueryType(); - const mutationType = schema.getMutationType(); - const subscriptionType = schema.getSubscriptionType(); - // Special case: When a schema has no root operation types, no valid schema - // definition can be printed. - if (!queryType && !mutationType && !subscriptionType) { + if (schema.description == null && isSchemaOfCommonNames(schema)) { return; } - // Only print a schema definition if there is a description or if it should - // not be omitted because of having default type names. - if (schema.description != null || !hasDefaultRootOperationTypes(schema)) { - return printDescription(schema) + 'schema {\n' + (queryType ? ` query: ${queryType.name}\n` : '') + (mutationType ? ` mutation: ${mutationType.name}\n` : '') + (subscriptionType ? ` subscription: ${subscriptionType.name}\n` : '') + '}'; + const operationTypes = []; + const queryType = schema.getQueryType(); + if (queryType) { + operationTypes.push(` query: ${queryType.name}`); } + const mutationType = schema.getMutationType(); + if (mutationType) { + operationTypes.push(` mutation: ${mutationType.name}`); + } + const subscriptionType = schema.getSubscriptionType(); + if (subscriptionType) { + operationTypes.push(` subscription: ${subscriptionType.name}`); + } + return printDescription(schema) + `schema {\n${operationTypes.join('\n')}\n}`; } /** * GraphQL schema define root types for each type of operation. These types are @@ -37402,16 +36713,23 @@ function printSchemaDefinition(schema) { * } * ``` * - * When using this naming convention, the schema description can be omitted so - * long as these names are only used for operation types. - * - * Note however that if any of these default names are used elsewhere in the - * schema but not as a root operation type, the schema definition must still - * be printed to avoid ambiguity. + * When using this naming convention, the schema description can be omitted. */ -function hasDefaultRootOperationTypes(schema) { - /* eslint-disable eqeqeq */ - return schema.getQueryType() == schema.getType('Query') && schema.getMutationType() == schema.getType('Mutation') && schema.getSubscriptionType() == schema.getType('Subscription'); + +function isSchemaOfCommonNames(schema) { + const queryType = schema.getQueryType(); + if (queryType && queryType.name !== 'Query') { + return false; + } + const mutationType = schema.getMutationType(); + if (mutationType && mutationType.name !== 'Mutation') { + return false; + } + const subscriptionType = schema.getSubscriptionType(); + if (subscriptionType && subscriptionType.name !== 'Subscription') { + return false; + } + return true; } function printType(type) { if ((0, _definition.isScalarType)(type)) { @@ -37434,6 +36752,7 @@ function printType(type) { } /* c8 ignore next 3 */ // Not reachable, all possible types have been considered. + false || (0, _invariant.invariant)(false, 'Unexpected type: ' + (0, _inspect.inspect)(type)); } function printScalar(type) { @@ -37472,9 +36791,9 @@ function printBlock(items) { function printArgs(args, indentation = '') { if (args.length === 0) { return ''; - } - // If every arg does not have a description, print them on one line. - if (args.every(arg => arg.description == null)) { + } // If every arg does not have a description, print them on one line. + + if (args.every(arg => !arg.description)) { return '(' + args.map(printInputValue).join(', ') + ')'; } return '(\n' + args.map((arg, i) => printDescription(arg, ' ' + indentation, !i) + ' ' + indentation + printInputValue(arg)).join('\n') + '\n' + indentation + ')'; @@ -37526,7 +36845,7 @@ function printDescription(def, indentation = '', firstInBlock = true) { block: (0, _blockString.isPrintableAsBlockString)(description) }); const prefix = indentation && !firstInBlock ? '\n' + indentation : indentation; - return prefix + blockString.replaceAll('\n', '\n' + indentation) + '\n'; + return prefix + blockString.replace(/\n/g, '\n' + indentation) + '\n'; } /***/ }), @@ -37551,10 +36870,11 @@ var _visitor = __webpack_require__(/*! ../language/visitor.mjs */ "../../../node * which contains a single operation as well the fragment definitions it * refers to. */ + function separateOperations(documentAST) { const operations = []; - const depGraph = Object.create(null); - // Populate metadata and build a dependency graph. + const depGraph = Object.create(null); // Populate metadata and build a dependency graph. + for (const definitionNode of documentAST.definitions) { switch (definitionNode.kind) { case _kinds.Kind.OPERATION_DEFINITION: @@ -37563,22 +36883,21 @@ function separateOperations(documentAST) { case _kinds.Kind.FRAGMENT_DEFINITION: depGraph[definitionNode.name.value] = collectDependencies(definitionNode.selectionSet); break; - default: - // ignore non-executable definitions + default: // ignore non-executable definitions } - } - // For each operation, produce a new synthesized AST which includes only what + } // For each operation, produce a new synthesized AST which includes only what // is necessary for completing that operation. + const separatedDocumentASTs = Object.create(null); for (const operation of operations) { const dependencies = new Set(); for (const fragmentName of collectDependencies(operation.selectionSet)) { collectTransitiveDependencies(dependencies, depGraph, fragmentName); - } - // Provides the empty string for anonymous operations. - const operationName = operation.name ? operation.name.value : ''; - // The list of definition nodes to be included for this operation, sorted + } // Provides the empty string for anonymous operations. + + const operationName = operation.name ? operation.name.value : ''; // The list of definition nodes to be included for this operation, sorted // to retain the same order as the original document. + separatedDocumentASTs[operationName] = { kind: _kinds.Kind.DOCUMENT, definitions: documentAST.definitions.filter(node => node === operation || node.kind === _kinds.Kind.FRAGMENT_DEFINITION && dependencies.has(node.name.value)) @@ -37586,6 +36905,7 @@ function separateOperations(documentAST) { } return separatedDocumentASTs; } + // From a dependency graph, collects a list of transitive dependencies by // recursing through a dependency graph. function collectTransitiveDependencies(collected, depGraph, fromName) { @@ -37632,6 +36952,7 @@ var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_mod * * @internal */ + function sortValueNode(valueNode) { switch (valueNode.kind) { case _kinds.Kind.OBJECT: @@ -37739,6 +37060,7 @@ var _tokenKind = __webpack_require__(/*! ../language/tokenKind.mjs */ "../../../ * """Type description""" type Foo{"""Field description""" bar:String} * ``` */ + function stripIgnoredCharacters(source) { const sourceObj = (0, _source.isSource)(source) ? source : new _source.Source(source); const body = sourceObj.body; @@ -37753,6 +37075,7 @@ function stripIgnoredCharacters(source) { * Also prevent case of non-punctuator token following by spread resulting * in invalid token (e.g. `1...` is invalid Float token). */ + const isNonPunctuator = !(0, _lexer.isPunctuatorTokenKind)(currentToken.kind); if (wasLastAddedTokenNonPunctuator) { if (isNonPunctuator || currentToken.kind === _tokenKind.TokenKind.SPREAD) { @@ -37796,28 +37119,29 @@ function isEqualType(typeA, typeB) { // Equivalent types are equal. if (typeA === typeB) { return true; - } - // If either type is non-null, the other must also be non-null. + } // If either type is non-null, the other must also be non-null. + if ((0, _definition.isNonNullType)(typeA) && (0, _definition.isNonNullType)(typeB)) { return isEqualType(typeA.ofType, typeB.ofType); - } - // If either type is a list, the other must also be a list. + } // If either type is a list, the other must also be a list. + if ((0, _definition.isListType)(typeA) && (0, _definition.isListType)(typeB)) { return isEqualType(typeA.ofType, typeB.ofType); - } - // Otherwise the types are not equal. + } // Otherwise the types are not equal. + return false; } /** * Provided a type and a super type, return true if the first type is either * equal or a subset of the second super type (covariant). */ + function isTypeSubTypeOf(schema, maybeSubType, superType) { // Equivalent type is a valid subtype if (maybeSubType === superType) { return true; - } - // If superType is non-null, maybeSubType must also be non-null. + } // If superType is non-null, maybeSubType must also be non-null. + if ((0, _definition.isNonNullType)(superType)) { if ((0, _definition.isNonNullType)(maybeSubType)) { return isTypeSubTypeOf(schema, maybeSubType.ofType, superType.ofType); @@ -37827,8 +37151,8 @@ function isTypeSubTypeOf(schema, maybeSubType, superType) { if ((0, _definition.isNonNullType)(maybeSubType)) { // If superType is nullable, maybeSubType may be non-null or nullable. return isTypeSubTypeOf(schema, maybeSubType.ofType, superType); - } - // If superType type is a list, maybeSubType type must also be a list. + } // If superType type is a list, maybeSubType type must also be a list. + if ((0, _definition.isListType)(superType)) { if ((0, _definition.isListType)(maybeSubType)) { return isTypeSubTypeOf(schema, maybeSubType.ofType, superType.ofType); @@ -37838,9 +37162,9 @@ function isTypeSubTypeOf(schema, maybeSubType, superType) { if ((0, _definition.isListType)(maybeSubType)) { // If superType is not a list, maybeSubType must also be not a list. return false; - } - // If superType type is an abstract type, check if it is super type of maybeSubType. + } // If superType type is an abstract type, check if it is super type of maybeSubType. // Otherwise, the child type is not a valid subtype of the parent type. + return (0, _definition.isAbstractType)(superType) && ((0, _definition.isInterfaceType)(maybeSubType) || (0, _definition.isObjectType)(maybeSubType)) && schema.isSubType(superType, maybeSubType); } /** @@ -37852,6 +37176,7 @@ function isTypeSubTypeOf(schema, maybeSubType, superType) { * * This function is commutative. */ + function doTypesOverlap(schema, typeA, typeB) { // Equivalent types overlap if (typeA === typeB) { @@ -37862,15 +37187,15 @@ function doTypesOverlap(schema, typeA, typeB) { // If both types are abstract, then determine if there is any intersection // between possible concrete types of each. return schema.getPossibleTypes(typeA).some(type => schema.isSubType(typeB, type)); - } - // Determine if the latter type is a possible concrete type of the former. + } // Determine if the latter type is a possible concrete type of the former. + return schema.isSubType(typeA, typeB); } if ((0, _definition.isAbstractType)(typeB)) { // Determine if the former type is a possible concrete type of the latter. return schema.isSubType(typeB, typeA); - } - // Otherwise the types do not overlap. + } // Otherwise the types do not overlap. + return false; } @@ -37923,6 +37248,7 @@ Object.defineProperty(exports, "__esModule", ({ exports.valueFromAST = valueFromAST; var _inspect = __webpack_require__(/*! ../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); var _invariant = __webpack_require__(/*! ../jsutils/invariant.mjs */ "../../../node_modules/graphql/jsutils/invariant.mjs"); +var _keyMap = __webpack_require__(/*! ../jsutils/keyMap.mjs */ "../../../node_modules/graphql/jsutils/keyMap.mjs"); var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); var _definition = __webpack_require__(/*! ../type/definition.mjs */ "../../../node_modules/graphql/type/definition.mjs"); /** @@ -37945,6 +37271,7 @@ var _definition = __webpack_require__(/*! ../type/definition.mjs */ "../../../no * | NullValue | null | * */ + function valueFromAST(valueNode, type, variables) { if (!valueNode) { // When there is no node, then there is also no value. @@ -37960,10 +37287,10 @@ function valueFromAST(valueNode, type, variables) { const variableValue = variables[variableName]; if (variableValue === null && (0, _definition.isNonNullType)(type)) { return; // Invalid: intentionally return no value. - } - // Note: This does no further checking that this variable is correct. + } // Note: This does no further checking that this variable is correct. // This assumes that this query has been validated and the variable // usage here is of the correct type. + return variableValue; } if ((0, _definition.isNonNullType)(type)) { @@ -38009,10 +37336,10 @@ function valueFromAST(valueNode, type, variables) { return; // Invalid: intentionally return no value. } const coercedObj = Object.create(null); - const fieldNodes = new Map(valueNode.fields.map(field => [field.name.value, field])); + const fieldNodes = (0, _keyMap.keyMap)(valueNode.fields, field => field.name.value); for (const field of Object.values(type.getFields())) { - const fieldNode = fieldNodes.get(field.name); - if (fieldNode == null || isMissingVariable(fieldNode.value, variables)) { + const fieldNode = fieldNodes[field.name]; + if (!fieldNode || isMissingVariable(fieldNode.value, variables)) { if (field.defaultValue !== undefined) { coercedObj[field.name] = field.defaultValue; } else if ((0, _definition.isNonNullType)(field.type)) { @@ -38054,10 +37381,11 @@ function valueFromAST(valueNode, type, variables) { } /* c8 ignore next 3 */ // Not reachable, all possible input types have been considered. + false || (0, _invariant.invariant)(false, 'Unexpected input type: ' + (0, _inspect.inspect)(type)); -} -// Returns true if the provided valueNode is a variable which is not defined +} // Returns true if the provided valueNode is a variable which is not defined // in the set of variables. + function isMissingVariable(valueNode, variables) { return valueNode.kind === _kinds.Kind.VARIABLE && (variables == null || variables[valueNode.name.value] === undefined); } @@ -38094,6 +37422,7 @@ var _kinds = __webpack_require__(/*! ../language/kinds.mjs */ "../../../node_mod * | Null | null | * */ + function valueFromASTUntyped(valueNode, variables) { switch (valueNode.kind) { case _kinds.Kind.NULL: @@ -38192,14 +37521,14 @@ class ASTValidationContext { let fragments = this._recursivelyReferencedFragments.get(operation); if (!fragments) { fragments = []; - const collectedNames = new Set(); + const collectedNames = Object.create(null); const nodesToVisit = [operation.selectionSet]; let node; while (node = nodesToVisit.pop()) { for (const spread of this.getFragmentSpreads(node)) { const fragName = spread.name.value; - if (!collectedNames.has(fragName)) { - collectedNames.add(fragName); + if (collectedNames[fragName] !== true) { + collectedNames[fragName] = true; const fragment = this.getFragment(fragName); if (fragment) { fragments.push(fragment); @@ -38312,24 +37641,6 @@ exports.ValidationContext = ValidationContext; Object.defineProperty(exports, "__esModule", ({ value: true })); -Object.defineProperty(exports, "DeferStreamDirectiveLabelRule", ({ - enumerable: true, - get: function () { - return _DeferStreamDirectiveLabelRule.DeferStreamDirectiveLabelRule; - } -})); -Object.defineProperty(exports, "DeferStreamDirectiveOnRootFieldRule", ({ - enumerable: true, - get: function () { - return _DeferStreamDirectiveOnRootFieldRule.DeferStreamDirectiveOnRootFieldRule; - } -})); -Object.defineProperty(exports, "DeferStreamDirectiveOnValidOperationsRule", ({ - enumerable: true, - get: function () { - return _DeferStreamDirectiveOnValidOperationsRule.DeferStreamDirectiveOnValidOperationsRule; - } -})); Object.defineProperty(exports, "ExecutableDefinitionsRule", ({ enumerable: true, get: function () { @@ -38462,12 +37773,6 @@ Object.defineProperty(exports, "SingleFieldSubscriptionsRule", ({ return _SingleFieldSubscriptionsRule.SingleFieldSubscriptionsRule; } })); -Object.defineProperty(exports, "StreamDirectiveOnListFieldRule", ({ - enumerable: true, - get: function () { - return _StreamDirectiveOnListFieldRule.StreamDirectiveOnListFieldRule; - } -})); Object.defineProperty(exports, "UniqueArgumentDefinitionNamesRule", ({ enumerable: true, get: function () { @@ -38585,9 +37890,6 @@ Object.defineProperty(exports, "validate", ({ var _validate = __webpack_require__(/*! ./validate.mjs */ "../../../node_modules/graphql/validation/validate.mjs"); var _ValidationContext = __webpack_require__(/*! ./ValidationContext.mjs */ "../../../node_modules/graphql/validation/ValidationContext.mjs"); var _specifiedRules = __webpack_require__(/*! ./specifiedRules.mjs */ "../../../node_modules/graphql/validation/specifiedRules.mjs"); -var _DeferStreamDirectiveLabelRule = __webpack_require__(/*! ./rules/DeferStreamDirectiveLabelRule.mjs */ "../../../node_modules/graphql/validation/rules/DeferStreamDirectiveLabelRule.mjs"); -var _DeferStreamDirectiveOnRootFieldRule = __webpack_require__(/*! ./rules/DeferStreamDirectiveOnRootFieldRule.mjs */ "../../../node_modules/graphql/validation/rules/DeferStreamDirectiveOnRootFieldRule.mjs"); -var _DeferStreamDirectiveOnValidOperationsRule = __webpack_require__(/*! ./rules/DeferStreamDirectiveOnValidOperationsRule.mjs */ "../../../node_modules/graphql/validation/rules/DeferStreamDirectiveOnValidOperationsRule.mjs"); var _ExecutableDefinitionsRule = __webpack_require__(/*! ./rules/ExecutableDefinitionsRule.mjs */ "../../../node_modules/graphql/validation/rules/ExecutableDefinitionsRule.mjs"); var _FieldsOnCorrectTypeRule = __webpack_require__(/*! ./rules/FieldsOnCorrectTypeRule.mjs */ "../../../node_modules/graphql/validation/rules/FieldsOnCorrectTypeRule.mjs"); var _FragmentsOnCompositeTypesRule = __webpack_require__(/*! ./rules/FragmentsOnCompositeTypesRule.mjs */ "../../../node_modules/graphql/validation/rules/FragmentsOnCompositeTypesRule.mjs"); @@ -38605,7 +37907,6 @@ var _PossibleFragmentSpreadsRule = __webpack_require__(/*! ./rules/PossibleFragm var _ProvidedRequiredArgumentsRule = __webpack_require__(/*! ./rules/ProvidedRequiredArgumentsRule.mjs */ "../../../node_modules/graphql/validation/rules/ProvidedRequiredArgumentsRule.mjs"); var _ScalarLeafsRule = __webpack_require__(/*! ./rules/ScalarLeafsRule.mjs */ "../../../node_modules/graphql/validation/rules/ScalarLeafsRule.mjs"); var _SingleFieldSubscriptionsRule = __webpack_require__(/*! ./rules/SingleFieldSubscriptionsRule.mjs */ "../../../node_modules/graphql/validation/rules/SingleFieldSubscriptionsRule.mjs"); -var _StreamDirectiveOnListFieldRule = __webpack_require__(/*! ./rules/StreamDirectiveOnListFieldRule.mjs */ "../../../node_modules/graphql/validation/rules/StreamDirectiveOnListFieldRule.mjs"); var _UniqueArgumentNamesRule = __webpack_require__(/*! ./rules/UniqueArgumentNamesRule.mjs */ "../../../node_modules/graphql/validation/rules/UniqueArgumentNamesRule.mjs"); var _UniqueDirectivesPerLocationRule = __webpack_require__(/*! ./rules/UniqueDirectivesPerLocationRule.mjs */ "../../../node_modules/graphql/validation/rules/UniqueDirectivesPerLocationRule.mjs"); var _UniqueFragmentNamesRule = __webpack_require__(/*! ./rules/UniqueFragmentNamesRule.mjs */ "../../../node_modules/graphql/validation/rules/UniqueFragmentNamesRule.mjs"); @@ -38629,182 +37930,6 @@ var _NoSchemaIntrospectionCustomRule = __webpack_require__(/*! ./rules/custom/No /***/ }), -/***/ "../../../node_modules/graphql/validation/rules/DeferStreamDirectiveLabelRule.mjs": -/*!****************************************************************************************!*\ - !*** ../../../node_modules/graphql/validation/rules/DeferStreamDirectiveLabelRule.mjs ***! - \****************************************************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.DeferStreamDirectiveLabelRule = DeferStreamDirectiveLabelRule; -var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); -var _kinds = __webpack_require__(/*! ../../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); -var _directives = __webpack_require__(/*! ../../type/directives.mjs */ "../../../node_modules/graphql/type/directives.mjs"); -/** - * Defer and stream directive labels are unique - * - * A GraphQL document is only valid if defer and stream directives' label argument is static and unique. - */ -function DeferStreamDirectiveLabelRule(context) { - const knownLabels = new Map(); - return { - Directive(node) { - if (node.name.value === _directives.GraphQLDeferDirective.name || node.name.value === _directives.GraphQLStreamDirective.name) { - var _node$arguments; - const labelArgument = (_node$arguments = node.arguments) === null || _node$arguments === void 0 ? void 0 : _node$arguments.find(arg => arg.name.value === 'label'); - const labelValue = labelArgument === null || labelArgument === void 0 ? void 0 : labelArgument.value; - if (!labelValue) { - return; - } - if (labelValue.kind !== _kinds.Kind.STRING) { - context.reportError(new _GraphQLError.GraphQLError(`Directive "${node.name.value}"'s label argument must be a static string.`, { - nodes: node - })); - return; - } - const knownLabel = knownLabels.get(labelValue.value); - if (knownLabel != null) { - context.reportError(new _GraphQLError.GraphQLError('Defer/Stream directive label argument must be unique.', { - nodes: [knownLabel, node] - })); - } else { - knownLabels.set(labelValue.value, node); - } - } - } - }; -} - -/***/ }), - -/***/ "../../../node_modules/graphql/validation/rules/DeferStreamDirectiveOnRootFieldRule.mjs": -/*!**********************************************************************************************!*\ - !*** ../../../node_modules/graphql/validation/rules/DeferStreamDirectiveOnRootFieldRule.mjs ***! - \**********************************************************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.DeferStreamDirectiveOnRootFieldRule = DeferStreamDirectiveOnRootFieldRule; -var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); -var _directives = __webpack_require__(/*! ../../type/directives.mjs */ "../../../node_modules/graphql/type/directives.mjs"); -/** - * Defer and stream directives are used on valid root field - * - * A GraphQL document is only valid if defer directives are not used on root mutation or subscription types. - */ -function DeferStreamDirectiveOnRootFieldRule(context) { - return { - Directive(node) { - const mutationType = context.getSchema().getMutationType(); - const subscriptionType = context.getSchema().getSubscriptionType(); - const parentType = context.getParentType(); - if (parentType && node.name.value === _directives.GraphQLDeferDirective.name) { - if (mutationType && parentType === mutationType) { - context.reportError(new _GraphQLError.GraphQLError(`Defer directive cannot be used on root mutation type "${parentType.name}".`, { - nodes: node - })); - } - if (subscriptionType && parentType === subscriptionType) { - context.reportError(new _GraphQLError.GraphQLError(`Defer directive cannot be used on root subscription type "${parentType.name}".`, { - nodes: node - })); - } - } - if (parentType && node.name.value === _directives.GraphQLStreamDirective.name) { - if (mutationType && parentType === mutationType) { - context.reportError(new _GraphQLError.GraphQLError(`Stream directive cannot be used on root mutation type "${parentType.name}".`, { - nodes: node - })); - } - if (subscriptionType && parentType === subscriptionType) { - context.reportError(new _GraphQLError.GraphQLError(`Stream directive cannot be used on root subscription type "${parentType.name}".`, { - nodes: node - })); - } - } - } - }; -} - -/***/ }), - -/***/ "../../../node_modules/graphql/validation/rules/DeferStreamDirectiveOnValidOperationsRule.mjs": -/*!****************************************************************************************************!*\ - !*** ../../../node_modules/graphql/validation/rules/DeferStreamDirectiveOnValidOperationsRule.mjs ***! - \****************************************************************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.DeferStreamDirectiveOnValidOperationsRule = DeferStreamDirectiveOnValidOperationsRule; -var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); -var _ast = __webpack_require__(/*! ../../language/ast.mjs */ "../../../node_modules/graphql/language/ast.mjs"); -var _kinds = __webpack_require__(/*! ../../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); -var _directives = __webpack_require__(/*! ../../type/directives.mjs */ "../../../node_modules/graphql/type/directives.mjs"); -function ifArgumentCanBeFalse(node) { - var _node$arguments; - const ifArgument = (_node$arguments = node.arguments) === null || _node$arguments === void 0 ? void 0 : _node$arguments.find(arg => arg.name.value === 'if'); - if (!ifArgument) { - return false; - } - if (ifArgument.value.kind === _kinds.Kind.BOOLEAN) { - if (ifArgument.value.value) { - return false; - } - } else if (ifArgument.value.kind !== _kinds.Kind.VARIABLE) { - return false; - } - return true; -} -/** - * Defer And Stream Directives Are Used On Valid Operations - * - * A GraphQL document is only valid if defer directives are not used on root mutation or subscription types. - */ -function DeferStreamDirectiveOnValidOperationsRule(context) { - const fragmentsUsedOnSubscriptions = new Set(); - return { - OperationDefinition(operation) { - if (operation.operation === _ast.OperationTypeNode.SUBSCRIPTION) { - for (const fragment of context.getRecursivelyReferencedFragments(operation)) { - fragmentsUsedOnSubscriptions.add(fragment.name.value); - } - } - }, - Directive(node, _key, _parent, _path, ancestors) { - const definitionNode = ancestors[2]; - if ('kind' in definitionNode && (definitionNode.kind === _kinds.Kind.FRAGMENT_DEFINITION && fragmentsUsedOnSubscriptions.has(definitionNode.name.value) || definitionNode.kind === _kinds.Kind.OPERATION_DEFINITION && definitionNode.operation === _ast.OperationTypeNode.SUBSCRIPTION)) { - if (node.name.value === _directives.GraphQLDeferDirective.name) { - if (!ifArgumentCanBeFalse(node)) { - context.reportError(new _GraphQLError.GraphQLError('Defer directive not supported on subscription operations. Disable `@defer` by setting the `if` argument to `false`.', { - nodes: node - })); - } - } else if (node.name.value === _directives.GraphQLStreamDirective.name) { - if (!ifArgumentCanBeFalse(node)) { - context.reportError(new _GraphQLError.GraphQLError('Stream directive not supported on subscription operations. Disable `@stream` by setting the `if` argument to `false`.', { - nodes: node - })); - } - } - } - } - }; -} - -/***/ }), - /***/ "../../../node_modules/graphql/validation/rules/ExecutableDefinitionsRule.mjs": /*!************************************************************************************!*\ !*** ../../../node_modules/graphql/validation/rules/ExecutableDefinitionsRule.mjs ***! @@ -38880,14 +38005,14 @@ function FieldsOnCorrectTypeRule(context) { if (!fieldDef) { // This field doesn't exist, lets look for suggestions. const schema = context.getSchema(); - const fieldName = node.name.value; - // First determine if there are any suggested types to condition on. - let suggestion = (0, _didYouMean.didYouMean)('to use an inline fragment on', getSuggestedTypeNames(schema, type, fieldName)); - // If there are no suggested types, then perhaps this was a typo? + const fieldName = node.name.value; // First determine if there are any suggested types to condition on. + + let suggestion = (0, _didYouMean.didYouMean)('to use an inline fragment on', getSuggestedTypeNames(schema, type, fieldName)); // If there are no suggested types, then perhaps this was a typo? + if (suggestion === '') { suggestion = (0, _didYouMean.didYouMean)(getSuggestedFieldNames(type, fieldName)); - } - // Report an error, including helpful suggestions. + } // Report an error, including helpful suggestions. + context.reportError(new _GraphQLError.GraphQLError(`Cannot query field "${fieldName}" on type "${type.name}".` + suggestion, { nodes: node })); @@ -38901,6 +38026,7 @@ function FieldsOnCorrectTypeRule(context) { * they implement. If any of those types include the provided field, suggest them, * sorted by how often the type is referenced. */ + function getSuggestedTypeNames(schema, type, fieldName) { if (!(0, _definition.isAbstractType)(type)) { // Must be an Object type, which does not have possible fields. @@ -38909,18 +38035,18 @@ function getSuggestedTypeNames(schema, type, fieldName) { const suggestedTypes = new Set(); const usageCount = Object.create(null); for (const possibleType of schema.getPossibleTypes(type)) { - if (possibleType.getFields()[fieldName] == null) { + if (!possibleType.getFields()[fieldName]) { continue; - } - // This object type defines this field. + } // This object type defines this field. + suggestedTypes.add(possibleType); usageCount[possibleType.name] = 1; for (const possibleInterface of possibleType.getInterfaces()) { var _usageCount$possibleI; - if (possibleInterface.getFields()[fieldName] == null) { + if (!possibleInterface.getFields()[fieldName]) { continue; - } - // This interface type defines this field. + } // This interface type defines this field. + suggestedTypes.add(possibleInterface); usageCount[possibleInterface.name] = ((_usageCount$possibleI = usageCount[possibleInterface.name]) !== null && _usageCount$possibleI !== void 0 ? _usageCount$possibleI : 0) + 1; } @@ -38930,8 +38056,8 @@ function getSuggestedTypeNames(schema, type, fieldName) { const usageCountDiff = usageCount[typeB.name] - usageCount[typeA.name]; if (usageCountDiff !== 0) { return usageCountDiff; - } - // Suggest super types first followed by subtypes + } // Suggest super types first followed by subtypes + if ((0, _definition.isInterfaceType)(typeA) && schema.isSubType(typeA, typeB)) { return -1; } @@ -38945,12 +38071,13 @@ function getSuggestedTypeNames(schema, type, fieldName) { * For the field name provided, determine if there are any similar field names * that may be the result of a typo. */ + function getSuggestedFieldNames(type, fieldName) { if ((0, _definition.isObjectType)(type) || (0, _definition.isInterfaceType)(type)) { const possibleFieldNames = Object.keys(type.getFields()); return (0, _suggestionList.suggestionList)(fieldName, possibleFieldNames); - } - // Otherwise, must be a Union type, which does not define fields. + } // Otherwise, must be a Union type, which does not define fields. + return []; } @@ -39058,28 +38185,31 @@ function KnownArgumentNamesRule(context) { /** * @internal */ + function KnownArgumentNamesOnDirectivesRule(context) { - const directiveArgs = new Map(); + const directiveArgs = Object.create(null); const schema = context.getSchema(); const definedDirectives = schema ? schema.getDirectives() : _directives.specifiedDirectives; for (const directive of definedDirectives) { - directiveArgs.set(directive.name, directive.args.map(arg => arg.name)); + directiveArgs[directive.name] = directive.args.map(arg => arg.name); } const astDefinitions = context.getDocument().definitions; for (const def of astDefinitions) { if (def.kind === _kinds.Kind.DIRECTIVE_DEFINITION) { var _def$arguments; + // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ const argsNodes = (_def$arguments = def.arguments) !== null && _def$arguments !== void 0 ? _def$arguments : []; - directiveArgs.set(def.name.value, argsNodes.map(arg => arg.name.value)); + directiveArgs[def.name.value] = argsNodes.map(arg => arg.name.value); } } return { Directive(directiveNode) { const directiveName = directiveNode.name.value; - const knownArgs = directiveArgs.get(directiveName); - if (directiveNode.arguments != null && knownArgs != null) { + const knownArgs = directiveArgs[directiveName]; + if (directiveNode.arguments && knownArgs) { for (const argNode of directiveNode.arguments) { const argName = argNode.name.value; if (!knownArgs.includes(argName)) { @@ -39125,30 +38255,30 @@ var _directives = __webpack_require__(/*! ../../type/directives.mjs */ "../../.. * See https://spec.graphql.org/draft/#sec-Directives-Are-Defined */ function KnownDirectivesRule(context) { - const locationsMap = new Map(); + const locationsMap = Object.create(null); const schema = context.getSchema(); const definedDirectives = schema ? schema.getDirectives() : _directives.specifiedDirectives; for (const directive of definedDirectives) { - locationsMap.set(directive.name, directive.locations); + locationsMap[directive.name] = directive.locations; } const astDefinitions = context.getDocument().definitions; for (const def of astDefinitions) { if (def.kind === _kinds.Kind.DIRECTIVE_DEFINITION) { - locationsMap.set(def.name.value, def.locations.map(name => name.value)); + locationsMap[def.name.value] = def.locations.map(name => name.value); } } return { Directive(node, _key, _parent, _path, ancestors) { const name = node.name.value; - const locations = locationsMap.get(name); - if (locations == null) { + const locations = locationsMap[name]; + if (!locations) { context.reportError(new _GraphQLError.GraphQLError(`Unknown directive "@${name}".`, { nodes: node })); return; } const candidateLocation = getDirectiveLocationForASTPath(ancestors); - if (candidateLocation != null && !locations.includes(candidateLocation)) { + if (candidateLocation && !locations.includes(candidateLocation)) { context.reportError(new _GraphQLError.GraphQLError(`Directive "@${name}" may not be used on ${candidateLocation}.`, { nodes: node })); @@ -39157,8 +38287,8 @@ function KnownDirectivesRule(context) { }; } function getDirectiveLocationForASTPath(ancestors) { - const appliedTo = ancestors.at(-1); - appliedTo != null && 'kind' in appliedTo || (0, _invariant.invariant)(false); + const appliedTo = ancestors[ancestors.length - 1]; + 'kind' in appliedTo || (0, _invariant.invariant)(false); switch (appliedTo.kind) { case _kinds.Kind.OPERATION_DEFINITION: return getDirectiveLocationForOperation(appliedTo.operation); @@ -39199,12 +38329,14 @@ function getDirectiveLocationForASTPath(ancestors) { return _directiveLocation.DirectiveLocation.INPUT_OBJECT; case _kinds.Kind.INPUT_VALUE_DEFINITION: { - const parentNode = ancestors.at(-3); - parentNode != null && 'kind' in parentNode || (0, _invariant.invariant)(false); + const parentNode = ancestors[ancestors.length - 3]; + 'kind' in parentNode || (0, _invariant.invariant)(false); return parentNode.kind === _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION ? _directiveLocation.DirectiveLocation.INPUT_FIELD_DEFINITION : _directiveLocation.DirectiveLocation.ARGUMENT_DEFINITION; } // Not reachable, all possible types have been considered. - /* c8 ignore next 2 */ + + /* c8 ignore next */ + default: false || (0, _invariant.invariant)(false, 'Unexpected kind: ' + (0, _inspect.inspect)(appliedTo.kind)); } @@ -39286,23 +38418,26 @@ var _scalars = __webpack_require__(/*! ../../type/scalars.mjs */ "../../../node_ * See https://spec.graphql.org/draft/#sec-Fragment-Spread-Type-Existence */ function KnownTypeNamesRule(context) { - var _context$getSchema$ge, _context$getSchema; - const { - definitions - } = context.getDocument(); - const existingTypesMap = (_context$getSchema$ge = (_context$getSchema = context.getSchema()) === null || _context$getSchema === void 0 ? void 0 : _context$getSchema.getTypeMap()) !== null && _context$getSchema$ge !== void 0 ? _context$getSchema$ge : {}; - const typeNames = new Set([...Object.keys(existingTypesMap), ...definitions.filter(_predicates.isTypeDefinitionNode).map(def => def.name.value)]); + const schema = context.getSchema(); + const existingTypesMap = schema ? schema.getTypeMap() : Object.create(null); + const definedTypes = Object.create(null); + for (const def of context.getDocument().definitions) { + if ((0, _predicates.isTypeDefinitionNode)(def)) { + definedTypes[def.name.value] = true; + } + } + const typeNames = [...Object.keys(existingTypesMap), ...Object.keys(definedTypes)]; return { NamedType(node, _1, parent, _2, ancestors) { const typeName = node.name.value; - if (!typeNames.has(typeName)) { + if (!existingTypesMap[typeName] && !definedTypes[typeName]) { var _ancestors$; const definitionNode = (_ancestors$ = ancestors[2]) !== null && _ancestors$ !== void 0 ? _ancestors$ : parent; const isSDL = definitionNode != null && isSDLNode(definitionNode); - if (isSDL && standardTypeNames.has(typeName)) { + if (isSDL && standardTypeNames.includes(typeName)) { return; } - const suggestedTypes = (0, _suggestionList.suggestionList)(typeName, isSDL ? [...standardTypeNames, ...typeNames] : [...typeNames]); + const suggestedTypes = (0, _suggestionList.suggestionList)(typeName, isSDL ? standardTypeNames.concat(typeNames) : typeNames); context.reportError(new _GraphQLError.GraphQLError(`Unknown type "${typeName}".` + (0, _didYouMean.didYouMean)(suggestedTypes), { nodes: node })); @@ -39310,7 +38445,7 @@ function KnownTypeNamesRule(context) { } }; } -const standardTypeNames = new Set([..._scalars.specifiedScalarTypes, ..._introspection.introspectionTypes].map(type => type.name)); +const standardTypeNames = [..._scalars.specifiedScalarTypes, ..._introspection.introspectionTypes].map(type => type.name); function isSDLNode(value) { return 'kind' in value && ((0, _predicates.isTypeSystemDefinitionNode)(value) || (0, _predicates.isTypeSystemExtensionNode)(value)); } @@ -39429,14 +38564,14 @@ function MaxIntrospectionDepthRule(context) { } const fragment = context.getFragment(fragmentName); if (!fragment) { - // Missing fragments checks are handled by the `KnownFragmentNamesRule`. + // Missing fragments checks are handled by `KnownFragmentNamesRule`. return false; - } - // Rather than following an immutable programming pattern which has + } // Rather than following an immutable programming pattern which has // significant memory and garbage collection overhead, we've opted to // take a mutable approach for efficiency's sake. Importantly visiting a // fragment twice is fine, so long as you don't do one visit inside the // other. + try { visitedFragments[fragmentName] = true; return checkDepth(fragment, visitedFragments, depth); @@ -39446,15 +38581,14 @@ function MaxIntrospectionDepthRule(context) { } if (node.kind === _kinds.Kind.FIELD && ( // check all introspection lists - // TODO: instead of relying on field names, check whether the type is a list node.name.value === 'fields' || node.name.value === 'interfaces' || node.name.value === 'possibleTypes' || node.name.value === 'inputFields')) { // eslint-disable-next-line no-param-reassign depth++; if (depth >= MAX_LISTS_DEPTH) { return true; } - } - // handles fields and inline fragments + } // handles fields and inline fragments + if ('selectionSet' in node && node.selectionSet) { for (const child of node.selectionSet.selections) { if (checkDepth(child, visitedFragments, depth)) { @@ -39504,10 +38638,10 @@ var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../ function NoFragmentCyclesRule(context) { // Tracks already visited fragments to maintain O(N) and to ensure that cycles // are not redundantly reported. - const visitedFrags = new Set(); - // Array of AST nodes used to produce meaningful errors - const spreadPath = []; - // Position in the spread path + const visitedFrags = Object.create(null); // Array of AST nodes used to produce meaningful errors + + const spreadPath = []; // Position in the spread path + const spreadPathIndexByName = Object.create(null); return { OperationDefinition: () => false, @@ -39515,16 +38649,16 @@ function NoFragmentCyclesRule(context) { detectCycleRecursive(node); return false; } - }; - // This does a straight-forward DFS to find cycles. + }; // This does a straight-forward DFS to find cycles. // It does not terminate when a cycle was found but continues to explore // the graph to find all possible cycles. + function detectCycleRecursive(fragment) { - if (visitedFrags.has(fragment.name.value)) { + if (visitedFrags[fragment.name.value]) { return; } const fragmentName = fragment.name.value; - visitedFrags.add(fragmentName); + visitedFrags[fragmentName] = true; const spreadNodes = context.getFragmentSpreads(fragment.selectionSet); if (spreadNodes.length === 0) { return; @@ -39576,21 +38710,28 @@ var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../ * See https://spec.graphql.org/draft/#sec-All-Variable-Uses-Defined */ function NoUndefinedVariablesRule(context) { + let variableNameDefined = Object.create(null); return { - OperationDefinition(operation) { - var _operation$variableDe; - const variableNameDefined = new Set((_operation$variableDe = operation.variableDefinitions) === null || _operation$variableDe === void 0 ? void 0 : _operation$variableDe.map(node => node.variable.name.value)); - const usages = context.getRecursiveVariableUsages(operation); - for (const { - node - } of usages) { - const varName = node.name.value; - if (!variableNameDefined.has(varName)) { - context.reportError(new _GraphQLError.GraphQLError(operation.name ? `Variable "$${varName}" is not defined by operation "${operation.name.value}".` : `Variable "$${varName}" is not defined.`, { - nodes: [node, operation] - })); + OperationDefinition: { + enter() { + variableNameDefined = Object.create(null); + }, + leave(operation) { + const usages = context.getRecursiveVariableUsages(operation); + for (const { + node + } of usages) { + const varName = node.name.value; + if (variableNameDefined[varName] !== true) { + context.reportError(new _GraphQLError.GraphQLError(operation.name ? `Variable "$${varName}" is not defined by operation "${operation.name.value}".` : `Variable "$${varName}" is not defined.`, { + nodes: [node, operation] + })); + } } } + }, + VariableDefinition(node) { + variableNameDefined[node.variable.name.value] = true; } }; } @@ -39619,13 +38760,11 @@ var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../ * See https://spec.graphql.org/draft/#sec-Fragments-Must-Be-Used */ function NoUnusedFragmentsRule(context) { - const fragmentNameUsed = new Set(); + const operationDefs = []; const fragmentDefs = []; return { - OperationDefinition(operation) { - for (const fragment of context.getRecursivelyReferencedFragments(operation)) { - fragmentNameUsed.add(fragment.name.value); - } + OperationDefinition(node) { + operationDefs.push(node); return false; }, FragmentDefinition(node) { @@ -39634,9 +38773,15 @@ function NoUnusedFragmentsRule(context) { }, Document: { leave() { + const fragmentNameUsed = Object.create(null); + for (const operation of operationDefs) { + for (const fragment of context.getRecursivelyReferencedFragments(operation)) { + fragmentNameUsed[fragment.name.value] = true; + } + } for (const fragmentDef of fragmentDefs) { const fragName = fragmentDef.name.value; - if (!fragmentNameUsed.has(fragName)) { + if (fragmentNameUsed[fragName] !== true) { context.reportError(new _GraphQLError.GraphQLError(`Fragment "${fragName}" is never used.`, { nodes: fragmentDef })); @@ -39671,24 +38816,32 @@ var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../ * See https://spec.graphql.org/draft/#sec-All-Variables-Used */ function NoUnusedVariablesRule(context) { + let variableDefs = []; return { - OperationDefinition(operation) { - var _operation$variableDe; - const usages = context.getRecursiveVariableUsages(operation); - const variableNameUsed = new Set(usages.map(({ - node - }) => node.name.value)); - // FIXME: https://github.com/graphql/graphql-js/issues/2203 - /* c8 ignore next */ - const variableDefinitions = (_operation$variableDe = operation.variableDefinitions) !== null && _operation$variableDe !== void 0 ? _operation$variableDe : []; - for (const variableDef of variableDefinitions) { - const variableName = variableDef.variable.name.value; - if (!variableNameUsed.has(variableName)) { - context.reportError(new _GraphQLError.GraphQLError(operation.name ? `Variable "$${variableName}" is never used in operation "${operation.name.value}".` : `Variable "$${variableName}" is never used.`, { - nodes: variableDef - })); + OperationDefinition: { + enter() { + variableDefs = []; + }, + leave(operation) { + const variableNameUsed = Object.create(null); + const usages = context.getRecursiveVariableUsages(operation); + for (const { + node + } of usages) { + variableNameUsed[node.name.value] = true; + } + for (const variableDef of variableDefs) { + const variableName = variableDef.variable.name.value; + if (variableNameUsed[variableName] !== true) { + context.reportError(new _GraphQLError.GraphQLError(operation.name ? `Variable "$${variableName}" is never used in operation "${operation.name.value}".` : `Variable "$${variableName}" is never used.`, { + nodes: variableDef + })); + } } } + }, + VariableDefinition(def) { + variableDefs.push(def); } }; } @@ -39714,9 +38867,6 @@ var _printer = __webpack_require__(/*! ../../language/printer.mjs */ "../../../n var _definition = __webpack_require__(/*! ../../type/definition.mjs */ "../../../node_modules/graphql/type/definition.mjs"); var _sortValueNode = __webpack_require__(/*! ../../utilities/sortValueNode.mjs */ "../../../node_modules/graphql/utilities/sortValueNode.mjs"); var _typeFromAST = __webpack_require__(/*! ../../utilities/typeFromAST.mjs */ "../../../node_modules/graphql/utilities/typeFromAST.mjs"); -/* eslint-disable max-params */ -// This file contains a lot of such errors but we plan to refactor it anyway -// so just disable it for entire file. function reasonMessage(reason) { if (Array.isArray(reason)) { return reason.map(([responseName, subReason]) => `subfields "${responseName}" conflict because ` + reasonMessage(subReason)).join(' and '); @@ -39732,14 +38882,15 @@ function reasonMessage(reason) { * * See https://spec.graphql.org/draft/#sec-Field-Selection-Merging */ + function OverlappingFieldsCanBeMergedRule(context) { // A memoization for when two fragments are compared "between" each other for // conflicts. Two fragments may be compared many times, so memoizing this can // dramatically improve the performance of this validator. - const comparedFragmentPairs = new PairSet(); - // A cache for the "field map" and list of fragment names found in any given + const comparedFragmentPairs = new PairSet(); // A cache for the "field map" and list of fragment names found in any given // selection set. Selection sets may be asked for this information multiple // times, so this improves the performance of this validator. + const cachedFieldsAndFragmentNames = new Map(); return { SelectionSet(selectionSet) { @@ -39753,6 +38904,7 @@ function OverlappingFieldsCanBeMergedRule(context) { } }; } + /** * Algorithm: * @@ -39812,43 +38964,43 @@ function OverlappingFieldsCanBeMergedRule(context) { // GraphQL Document. function findConflictsWithinSelectionSet(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, parentType, selectionSet) { const conflicts = []; - const [fieldMap, fragmentNames] = getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, parentType, selectionSet); - // (A) Find find all conflicts "within" the fields of this selection set. + const [fieldMap, fragmentNames] = getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, parentType, selectionSet); // (A) Find find all conflicts "within" the fields of this selection set. // Note: this is the *only place* `collectConflictsWithin` is called. + collectConflictsWithin(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, fieldMap); if (fragmentNames.length !== 0) { // (B) Then collect conflicts between these fields and those represented by // each spread fragment name found. for (let i = 0; i < fragmentNames.length; i++) { - collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, false, fieldMap, fragmentNames[i]); - // (C) Then compare this fragment with all other fragments found in this + collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, false, fieldMap, fragmentNames[i]); // (C) Then compare this fragment with all other fragments found in this // selection set to collect conflicts between fragments spread together. // This compares each item in the list of fragment names to every other // item in that same list (except for itself). + for (let j = i + 1; j < fragmentNames.length; j++) { collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, false, fragmentNames[i], fragmentNames[j]); } } } return conflicts; -} -// Collect all conflicts found between a set of fields and a fragment reference +} // Collect all conflicts found between a set of fields and a fragment reference // including via spreading in any nested fragments. + function collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap, fragmentName) { const fragment = context.getFragment(fragmentName); if (!fragment) { return; } - const [fieldMap2, referencedFragmentNames] = getReferencedFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragment); - // Do not compare a fragment's fieldMap to itself. + const [fieldMap2, referencedFragmentNames] = getReferencedFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragment); // Do not compare a fragment's fieldMap to itself. + if (fieldMap === fieldMap2) { return; - } - // (D) First collect any conflicts between the provided collection of fields + } // (D) First collect any conflicts between the provided collection of fields // and the collection of fields represented by the given fragment. - collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap, fieldMap2); - // (E) Then collect any conflicts between the provided collection of fields + + collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap, fieldMap2); // (E) Then collect any conflicts between the provided collection of fields // and any fragment names found in the given fragment. + for (const referencedFragmentName of referencedFragmentNames) { // Memoize so two fragments are not compared for conflicts more than once. if (comparedFragmentPairs.has(referencedFragmentName, fragmentName, areMutuallyExclusive)) { @@ -39857,15 +39009,15 @@ function collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFiel comparedFragmentPairs.add(referencedFragmentName, fragmentName, areMutuallyExclusive); collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap, referencedFragmentName); } -} -// Collect all conflicts found between two fragments, including via spreading in +} // Collect all conflicts found between two fragments, including via spreading in // any nested fragments. + function collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fragmentName1, fragmentName2) { // No need to compare a fragment to itself. if (fragmentName1 === fragmentName2) { return; - } - // Memoize so two fragments are not compared for conflicts more than once. + } // Memoize so two fragments are not compared for conflicts more than once. + if (comparedFragmentPairs.has(fragmentName1, fragmentName2, areMutuallyExclusive)) { return; } @@ -39876,57 +39028,57 @@ function collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFra return; } const [fieldMap1, referencedFragmentNames1] = getReferencedFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragment1); - const [fieldMap2, referencedFragmentNames2] = getReferencedFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragment2); - // (F) First, collect all conflicts between these two collections of fields + const [fieldMap2, referencedFragmentNames2] = getReferencedFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragment2); // (F) First, collect all conflicts between these two collections of fields // (not including any nested fragments). - collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, fieldMap2); - // (G) Then collect conflicts between the first fragment and any nested + + collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, fieldMap2); // (G) Then collect conflicts between the first fragment and any nested // fragments spread in the second fragment. + for (const referencedFragmentName2 of referencedFragmentNames2) { collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fragmentName1, referencedFragmentName2); - } - // (G) Then collect conflicts between the second fragment and any nested + } // (G) Then collect conflicts between the second fragment and any nested // fragments spread in the first fragment. + for (const referencedFragmentName1 of referencedFragmentNames1) { collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, referencedFragmentName1, fragmentName2); } -} -// Find all conflicts found between two selection sets, including those found +} // Find all conflicts found between two selection sets, including those found // via spreading in fragments. Called when determining if conflicts exist // between the sub-fields of two overlapping fields. + function findConflictsBetweenSubSelectionSets(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, parentType1, selectionSet1, parentType2, selectionSet2) { const conflicts = []; const [fieldMap1, fragmentNames1] = getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, parentType1, selectionSet1); - const [fieldMap2, fragmentNames2] = getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, parentType2, selectionSet2); - // (H) First, collect all conflicts between these two collections of field. - collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, fieldMap2); - // (I) Then collect conflicts between the first collection of fields and + const [fieldMap2, fragmentNames2] = getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, parentType2, selectionSet2); // (H) First, collect all conflicts between these two collections of field. + + collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, fieldMap2); // (I) Then collect conflicts between the first collection of fields and // those referenced by each fragment name associated with the second. + for (const fragmentName2 of fragmentNames2) { collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, fragmentName2); - } - // (I) Then collect conflicts between the second collection of fields and + } // (I) Then collect conflicts between the second collection of fields and // those referenced by each fragment name associated with the first. + for (const fragmentName1 of fragmentNames1) { collectConflictsBetweenFieldsAndFragment(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap2, fragmentName1); - } - // (J) Also collect conflicts between any fragment names by the first and + } // (J) Also collect conflicts between any fragment names by the first and // fragment names by the second. This compares each item in the first set of // names to each item in the second set of names. + for (const fragmentName1 of fragmentNames1) { for (const fragmentName2 of fragmentNames2) { collectConflictsBetweenFragments(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fragmentName1, fragmentName2); } } return conflicts; -} -// Collect all Conflicts "within" one collection of fields. +} // Collect all Conflicts "within" one collection of fields. + function collectConflictsWithin(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, fieldMap) { // A field map is a keyed collection, where each key represents a response // name and the value at that key is a list of all fields which provide that // response name. For every response name, if there are multiple fields, they // must be compared to find a potential conflict. - for (const [responseName, fields] of fieldMap.entries()) { + for (const [responseName, fields] of Object.entries(fieldMap)) { // This compares every field in the list to every other field in this list // (except to itself). If the list only has one item, nothing needs to // be compared. @@ -39943,21 +39095,21 @@ function collectConflictsWithin(context, conflicts, cachedFieldsAndFragmentNames } } } -} -// Collect all Conflicts between two collections of fields. This is similar to, +} // Collect all Conflicts between two collections of fields. This is similar to, // but different from the `collectConflictsWithin` function above. This check // assumes that `collectConflictsWithin` has already been called on each // provided collection of fields. This is true because this validator traverses // each individual selection set. + function collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, parentFieldsAreMutuallyExclusive, fieldMap1, fieldMap2) { // A field map is a keyed collection, where each key represents a response // name and the value at that key is a list of all fields which provide that // response name. For any response name which appears in both provided field // maps, each field from the first field map must be compared to every field // in the second field map to find potential conflicts. - for (const [responseName, fields1] of fieldMap1.entries()) { - const fields2 = fieldMap2.get(responseName); - if (fields2 != null) { + for (const [responseName, fields1] of Object.entries(fieldMap1)) { + const fields2 = fieldMap2[responseName]; + if (fields2) { for (const field1 of fields1) { for (const field2 of fields2) { const conflict = findConflict(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, parentFieldsAreMutuallyExclusive, responseName, field1, field2); @@ -39968,14 +39120,12 @@ function collectConflictsBetween(context, conflicts, cachedFieldsAndFragmentName } } } -} -// Determines if there is a conflict between two particular fields, including +} // Determines if there is a conflict between two particular fields, including // comparing their sub-fields. + function findConflict(context, cachedFieldsAndFragmentNames, comparedFragmentPairs, parentFieldsAreMutuallyExclusive, responseName, field1, field2) { - var _node1$directives, _node2$directives; const [parentType1, node1, def1] = field1; - const [parentType2, node2, def2] = field2; - // If it is known that two fields could not possibly apply at the same + const [parentType2, node2, def2] = field2; // If it is known that two fields could not possibly apply at the same // time, due to the parent types, then it is safe to permit them to diverge // in aliased field or arguments used as they will not present any ambiguity // by differing. @@ -39983,6 +39133,7 @@ function findConflict(context, cachedFieldsAndFragmentNames, comparedFragmentPai // different Object types. Interface or Union types might overlap - if not // in the current state of the schema, then perhaps in some future version, // thus may not safely diverge. + const areMutuallyExclusive = parentFieldsAreMutuallyExclusive || parentType1 !== parentType2 && (0, _definition.isObjectType)(parentType1) && (0, _definition.isObjectType)(parentType2); if (!areMutuallyExclusive) { // Two aliases must refer to the same field. @@ -39990,27 +39141,21 @@ function findConflict(context, cachedFieldsAndFragmentNames, comparedFragmentPai const name2 = node2.name.value; if (name1 !== name2) { return [[responseName, `"${name1}" and "${name2}" are different fields`], [node1], [node2]]; - } - // Two field calls must have the same arguments. + } // Two field calls must have the same arguments. + if (!sameArguments(node1, node2)) { return [[responseName, 'they have differing arguments'], [node1], [node2]]; } - } - // FIXME https://github.com/graphql/graphql-js/issues/2203 - const directives1 = /* c8 ignore next */(_node1$directives = node1.directives) !== null && _node1$directives !== void 0 ? _node1$directives : []; - const directives2 = /* c8 ignore next */(_node2$directives = node2.directives) !== null && _node2$directives !== void 0 ? _node2$directives : []; - if (!sameStreams(directives1, directives2)) { - return [[responseName, 'they have differing stream directives'], [node1], [node2]]; - } - // The return type for each field. + } // The return type for each field. + const type1 = def1 === null || def1 === void 0 ? void 0 : def1.type; const type2 = def2 === null || def2 === void 0 ? void 0 : def2.type; if (type1 && type2 && doTypesConflict(type1, type2)) { return [[responseName, `they return conflicting types "${(0, _inspect.inspect)(type1)}" and "${(0, _inspect.inspect)(type2)}"`], [node1], [node2]]; - } - // Collect and compare sub-fields. Use the same "visited fragment names" list + } // Collect and compare sub-fields. Use the same "visited fragment names" list // for both collections so fields in a fragment reference are never // compared to themselves. + const selectionSet1 = node1.selectionSet; const selectionSet2 = node2.selectionSet; if (selectionSet1 && selectionSet2) { @@ -40027,8 +39172,12 @@ function sameArguments(node1, node2) { if (args2 === undefined || args2.length === 0) { return false; } + /* c8 ignore next */ + if (args1.length !== args2.length) { + /* c8 ignore next */ return false; + /* c8 ignore next */ } const values2 = new Map(args2.map(({ name, @@ -40045,26 +39194,10 @@ function sameArguments(node1, node2) { } function stringifyValue(value) { return (0, _printer.print)((0, _sortValueNode.sortValueNode)(value)); -} -function getStreamDirective(directives) { - return directives.find(directive => directive.name.value === 'stream'); -} -function sameStreams(directives1, directives2) { - const stream1 = getStreamDirective(directives1); - const stream2 = getStreamDirective(directives2); - if (!stream1 && !stream2) { - // both fields do not have streams - return true; - } else if (stream1 && stream2) { - // check if both fields have equivalent streams - return sameArguments(stream1, stream2); - } - // fields have a mix of stream and no stream - return false; -} -// Two types conflict if both types could not apply to a value simultaneously. +} // Two types conflict if both types could not apply to a value simultaneously. // Composite types are ignored as their individual field types will be compared // later recursively. However List and Non-Null types must match. + function doTypesConflict(type1, type2) { if ((0, _definition.isListType)(type1)) { return (0, _definition.isListType)(type2) ? doTypesConflict(type1.ofType, type2.ofType) : true; @@ -40082,24 +39215,24 @@ function doTypesConflict(type1, type2) { return type1 !== type2; } return false; -} -// Given a selection set, return the collection of fields (a mapping of response +} // Given a selection set, return the collection of fields (a mapping of response // name to field nodes and definitions) as well as a list of fragment names // referenced via fragment spreads. + function getFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, parentType, selectionSet) { const cached = cachedFieldsAndFragmentNames.get(selectionSet); if (cached) { return cached; } - const nodeAndDefs = new Map(); - const fragmentNames = new Set(); + const nodeAndDefs = Object.create(null); + const fragmentNames = Object.create(null); _collectFieldsAndFragmentNames(context, parentType, selectionSet, nodeAndDefs, fragmentNames); - const result = [nodeAndDefs, [...fragmentNames]]; + const result = [nodeAndDefs, Object.keys(fragmentNames)]; cachedFieldsAndFragmentNames.set(selectionSet, result); return result; -} -// Given a reference to a fragment, return the represented collection of fields +} // Given a reference to a fragment, return the represented collection of fields // as well as a list of nested fragment names referenced via fragment spreads. + function getReferencedFieldsAndFragmentNames(context, cachedFieldsAndFragmentNames, fragment) { // Short-circuit building a type from the node if possible. const cached = cachedFieldsAndFragmentNames.get(fragment.selectionSet); @@ -40120,16 +39253,14 @@ function _collectFieldsAndFragmentNames(context, parentType, selectionSet, nodeA fieldDef = parentType.getFields()[fieldName]; } const responseName = selection.alias ? selection.alias.value : fieldName; - let nodeAndDefsList = nodeAndDefs.get(responseName); - if (nodeAndDefsList == null) { - nodeAndDefsList = []; - nodeAndDefs.set(responseName, nodeAndDefsList); + if (!nodeAndDefs[responseName]) { + nodeAndDefs[responseName] = []; } - nodeAndDefsList.push([parentType, selection, fieldDef]); + nodeAndDefs[responseName].push([parentType, selection, fieldDef]); break; } case _kinds.Kind.FRAGMENT_SPREAD: - fragmentNames.add(selection.name.value); + fragmentNames[selection.name.value] = true; break; case _kinds.Kind.INLINE_FRAGMENT: { @@ -40140,9 +39271,9 @@ function _collectFieldsAndFragmentNames(context, parentType, selectionSet, nodeA } } } -} -// Given a series of Conflicts which occurred between two sub-fields, generate +} // Given a series of Conflicts which occurred between two sub-fields, generate // a single Conflict. + function subfieldConflicts(conflicts, responseName, node1, node2) { if (conflicts.length > 0) { return [[responseName, conflicts.map(([reason]) => reason)], [node1, ...conflicts.map(([, fields1]) => fields1).flat()], [node2, ...conflicts.map(([,, fields2]) => fields2).flat()]]; @@ -40151,6 +39282,7 @@ function subfieldConflicts(conflicts, responseName, node1, node2) { /** * A way to keep track of pairs of things when the ordering of the pair does not matter. */ + class PairSet { constructor() { this._data = new Map(); @@ -40161,10 +39293,10 @@ class PairSet { const result = (_this$_data$get = this._data.get(key1)) === null || _this$_data$get === void 0 ? void 0 : _this$_data$get.get(key2); if (result === undefined) { return false; - } - // areMutuallyExclusive being false is a superset of being true, hence if + } // areMutuallyExclusive being false is a superset of being true, hence if // we want to know if this PairSet "has" these two with no exclusivity, // we have to ensure it was added as such. + return areMutuallyExclusive ? true : areMutuallyExclusive === result; } add(a, b, areMutuallyExclusive) { @@ -40270,10 +39402,10 @@ var _definition = __webpack_require__(/*! ../../type/definition.mjs */ "../../.. */ function PossibleTypeExtensionsRule(context) { const schema = context.getSchema(); - const definedTypes = new Map(); + const definedTypes = Object.create(null); for (const def of context.getDocument().definitions) { if ((0, _predicates.isTypeDefinitionNode)(def)) { - definedTypes.set(def.name.value, def); + definedTypes[def.name.value] = def; } } return { @@ -40286,15 +39418,15 @@ function PossibleTypeExtensionsRule(context) { }; function checkExtension(node) { const typeName = node.name.value; - const defNode = definedTypes.get(typeName); + const defNode = definedTypes[typeName]; const existingType = schema === null || schema === void 0 ? void 0 : schema.getType(typeName); let expectedKind; - if (defNode != null) { + if (defNode) { expectedKind = defKindToExtKind[defNode.kind]; } else if (existingType) { expectedKind = typeToExtKind(existingType); } - if (expectedKind != null) { + if (expectedKind) { if (expectedKind !== node.kind) { const kindStr = extensionKindToTypeName(node.kind); context.reportError(new _GraphQLError.GraphQLError(`Cannot extend non-${kindStr} type "${typeName}".`, { @@ -40302,8 +39434,10 @@ function PossibleTypeExtensionsRule(context) { })); } } else { - var _schema$getTypeMap; - const allTypeNames = [...definedTypes.keys(), ...Object.keys((_schema$getTypeMap = schema === null || schema === void 0 ? void 0 : schema.getTypeMap()) !== null && _schema$getTypeMap !== void 0 ? _schema$getTypeMap : {})]; + const allTypeNames = Object.keys({ + ...definedTypes, + ...(schema === null || schema === void 0 ? void 0 : schema.getTypeMap()) + }); const suggestedTypes = (0, _suggestionList.suggestionList)(typeName, allTypeNames); context.reportError(new _GraphQLError.GraphQLError(`Cannot extend type "${typeName}" because it is not defined.` + (0, _didYouMean.didYouMean)(suggestedTypes), { nodes: node.name @@ -40340,6 +39474,7 @@ function typeToExtKind(type) { } /* c8 ignore next 3 */ // Not reachable. All possible types have been considered + false || (0, _invariant.invariant)(false, 'Unexpected type: ' + (0, _inspect.inspect)(type)); } function extensionKindToTypeName(kind) { @@ -40357,7 +39492,9 @@ function extensionKindToTypeName(kind) { case _kinds.Kind.INPUT_OBJECT_TYPE_EXTENSION: return 'input object'; // Not reachable. All possible types have been considered - /* c8 ignore next 2 */ + + /* c8 ignore next */ + default: false || (0, _invariant.invariant)(false, 'Unexpected kind: ' + (0, _inspect.inspect)(kind)); } @@ -40379,6 +39516,7 @@ Object.defineProperty(exports, "__esModule", ({ exports.ProvidedRequiredArgumentsOnDirectivesRule = ProvidedRequiredArgumentsOnDirectivesRule; exports.ProvidedRequiredArgumentsRule = ProvidedRequiredArgumentsRule; var _inspect = __webpack_require__(/*! ../../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); +var _keyMap = __webpack_require__(/*! ../../jsutils/keyMap.mjs */ "../../../node_modules/graphql/jsutils/keyMap.mjs"); var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); var _kinds = __webpack_require__(/*! ../../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); var _printer = __webpack_require__(/*! ../../language/printer.mjs */ "../../../node_modules/graphql/language/printer.mjs"); @@ -40402,7 +39540,8 @@ function ProvidedRequiredArgumentsRule(context) { if (!fieldDef) { return false; } - const providedArgs = new Set( // FIXME: https://github.com/graphql/graphql-js/issues/2203 + const providedArgs = new Set( + // FIXME: https://github.com/graphql/graphql-js/issues/2203 /* c8 ignore next */ (_fieldNode$arguments = fieldNode.arguments) === null || _fieldNode$arguments === void 0 ? void 0 : _fieldNode$arguments.map(arg => arg.name.value)); for (const argDef of fieldDef.args) { @@ -40420,22 +39559,25 @@ function ProvidedRequiredArgumentsRule(context) { /** * @internal */ + function ProvidedRequiredArgumentsOnDirectivesRule(context) { var _schema$getDirectives; - const requiredArgsMap = new Map(); + const requiredArgsMap = Object.create(null); const schema = context.getSchema(); const definedDirectives = (_schema$getDirectives = schema === null || schema === void 0 ? void 0 : schema.getDirectives()) !== null && _schema$getDirectives !== void 0 ? _schema$getDirectives : _directives.specifiedDirectives; for (const directive of definedDirectives) { - requiredArgsMap.set(directive.name, new Map(directive.args.filter(_definition.isRequiredArgument).map(arg => [arg.name, arg]))); + requiredArgsMap[directive.name] = (0, _keyMap.keyMap)(directive.args.filter(_definition.isRequiredArgument), arg => arg.name); } const astDefinitions = context.getDocument().definitions; for (const def of astDefinitions) { if (def.kind === _kinds.Kind.DIRECTIVE_DEFINITION) { var _def$arguments; + // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ const argNodes = (_def$arguments = def.arguments) !== null && _def$arguments !== void 0 ? _def$arguments : []; - requiredArgsMap.set(def.name.value, new Map(argNodes.filter(isRequiredArgumentNode).map(arg => [arg.name.value, arg]))); + requiredArgsMap[def.name.value] = (0, _keyMap.keyMap)(argNodes.filter(isRequiredArgumentNode), arg => arg.name.value); } } return { @@ -40443,14 +39585,16 @@ function ProvidedRequiredArgumentsOnDirectivesRule(context) { // Validate on leave to allow for deeper errors to appear first. leave(directiveNode) { const directiveName = directiveNode.name.value; - const requiredArgs = requiredArgsMap.get(directiveName); - if (requiredArgs != null) { + const requiredArgs = requiredArgsMap[directiveName]; + if (requiredArgs) { var _directiveNode$argume; + // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ const argNodes = (_directiveNode$argume = directiveNode.arguments) !== null && _directiveNode$argume !== void 0 ? _directiveNode$argume : []; const argNodeMap = new Set(argNodes.map(arg => arg.name.value)); - for (const [argName, argDef] of requiredArgs.entries()) { + for (const [argName, argDef] of Object.entries(requiredArgs)) { if (!argNodeMap.has(argName)) { const argType = (0, _definition.isType)(argDef.type) ? (0, _inspect.inspect)(argDef.type) : (0, _printer.print)(argDef.type); context.reportError(new _GraphQLError.GraphQLError(`Directive "@${directiveName}" argument "${argName}" of type "${argType}" is required, but it was not provided.`, { @@ -40533,9 +39677,6 @@ exports.SingleFieldSubscriptionsRule = SingleFieldSubscriptionsRule; var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); var _kinds = __webpack_require__(/*! ../../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); var _collectFields = __webpack_require__(/*! ../../execution/collectFields.mjs */ "../../../node_modules/graphql/execution/collectFields.mjs"); -function toNodes(fieldGroup) { - return fieldGroup.map(fieldDetails => fieldDetails.node); -} /** * Subscriptions must only include a non-introspection field. * @@ -40560,22 +39701,21 @@ function SingleFieldSubscriptionsRule(context) { fragments[definition.name.value] = definition; } } - const { - groupedFieldSet - } = (0, _collectFields.collectFields)(schema, fragments, variableValues, subscriptionType, node); - if (groupedFieldSet.size > 1) { - const fieldGroups = [...groupedFieldSet.values()]; - const extraFieldGroups = fieldGroups.slice(1); - const extraFieldSelections = extraFieldGroups.flatMap(fieldGroup => toNodes(fieldGroup)); + const fields = (0, _collectFields.collectFields)(schema, fragments, variableValues, subscriptionType, node.selectionSet); + if (fields.size > 1) { + const fieldSelectionLists = [...fields.values()]; + const extraFieldSelectionLists = fieldSelectionLists.slice(1); + const extraFieldSelections = extraFieldSelectionLists.flat(); context.reportError(new _GraphQLError.GraphQLError(operationName != null ? `Subscription "${operationName}" must select only one top level field.` : 'Anonymous Subscription must select only one top level field.', { nodes: extraFieldSelections })); } - for (const fieldGroup of groupedFieldSet.values()) { - const fieldName = toNodes(fieldGroup)[0].name.value; + for (const fieldNodes of fields.values()) { + const field = fieldNodes[0]; + const fieldName = field.name.value; if (fieldName.startsWith('__')) { context.reportError(new _GraphQLError.GraphQLError(operationName != null ? `Subscription "${operationName}" must not select an introspection top level field.` : 'Anonymous Subscription must not select an introspection top level field.', { - nodes: toNodes(fieldGroup) + nodes: fieldNodes })); } } @@ -40587,42 +39727,6 @@ function SingleFieldSubscriptionsRule(context) { /***/ }), -/***/ "../../../node_modules/graphql/validation/rules/StreamDirectiveOnListFieldRule.mjs": -/*!*****************************************************************************************!*\ - !*** ../../../node_modules/graphql/validation/rules/StreamDirectiveOnListFieldRule.mjs ***! - \*****************************************************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.StreamDirectiveOnListFieldRule = StreamDirectiveOnListFieldRule; -var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); -var _definition = __webpack_require__(/*! ../../type/definition.mjs */ "../../../node_modules/graphql/type/definition.mjs"); -var _directives = __webpack_require__(/*! ../../type/directives.mjs */ "../../../node_modules/graphql/type/directives.mjs"); -/** - * Stream directives are used on list fields - * - * A GraphQL document is only valid if stream directives are used on list fields. - */ -function StreamDirectiveOnListFieldRule(context) { - return { - Directive(node) { - const fieldDef = context.getFieldDef(); - const parentType = context.getParentType(); - if (fieldDef && parentType && node.name.value === _directives.GraphQLStreamDirective.name && !((0, _definition.isListType)(fieldDef.type) || (0, _definition.isWrappingType)(fieldDef.type) && (0, _definition.isListType)(fieldDef.type.ofType))) { - context.reportError(new _GraphQLError.GraphQLError(`Stream directive cannot be used on non-list field "${fieldDef.name}" on type "${parentType.name}".`, { - nodes: node - })); - } - } - }; -} - -/***/ }), - /***/ "../../../node_modules/graphql/validation/rules/UniqueArgumentDefinitionNamesRule.mjs": /*!********************************************************************************************!*\ !*** ../../../node_modules/graphql/validation/rules/UniqueArgumentDefinitionNamesRule.mjs ***! @@ -40647,7 +39751,9 @@ function UniqueArgumentDefinitionNamesRule(context) { return { DirectiveDefinition(directiveNode) { var _directiveNode$argume; + // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ const argumentNodes = (_directiveNode$argume = directiveNode.arguments) !== null && _directiveNode$argume !== void 0 ? _directiveNode$argume : []; return checkArgUniqueness(`@${directiveNode.name.value}`, argumentNodes); @@ -40659,15 +39765,17 @@ function UniqueArgumentDefinitionNamesRule(context) { }; function checkArgUniquenessPerField(typeNode) { var _typeNode$fields; - const typeName = typeNode.name.value; - // FIXME: https://github.com/graphql/graphql-js/issues/2203 + const typeName = typeNode.name.value; // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ + const fieldNodes = (_typeNode$fields = typeNode.fields) !== null && _typeNode$fields !== void 0 ? _typeNode$fields : []; for (const fieldDef of fieldNodes) { var _fieldDef$arguments; - const fieldName = fieldDef.name.value; - // FIXME: https://github.com/graphql/graphql-js/issues/2203 + const fieldName = fieldDef.name.value; // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ + const argumentNodes = (_fieldDef$arguments = fieldDef.arguments) !== null && _fieldDef$arguments !== void 0 ? _fieldDef$arguments : []; checkArgUniqueness(`${typeName}.${fieldName}`, argumentNodes); } @@ -40717,7 +39825,9 @@ function UniqueArgumentNamesRule(context) { }; function checkArgUniqueness(parentNode) { var _parentNode$arguments; + // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ const argumentNodes = (_parentNode$arguments = parentNode.arguments) !== null && _parentNode$arguments !== void 0 ? _parentNode$arguments : []; const seenArgs = (0, _groupBy.groupBy)(argumentNodes, arg => arg.name.value); @@ -40752,7 +39862,7 @@ var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../ * A GraphQL document is only valid if all defined directives have unique names. */ function UniqueDirectiveNamesRule(context) { - const knownDirectiveNames = new Map(); + const knownDirectiveNames = Object.create(null); const schema = context.getSchema(); return { DirectiveDefinition(node) { @@ -40763,13 +39873,12 @@ function UniqueDirectiveNamesRule(context) { })); return; } - const knownName = knownDirectiveNames.get(directiveName); - if (knownName) { + if (knownDirectiveNames[directiveName]) { context.reportError(new _GraphQLError.GraphQLError(`There can be only one directive named "@${directiveName}".`, { - nodes: [knownName, node.name] + nodes: [knownDirectiveNames[directiveName], node.name] })); } else { - knownDirectiveNames.set(directiveName, node.name); + knownDirectiveNames[directiveName] = node.name; } return false; } @@ -40803,20 +39912,20 @@ var _directives = __webpack_require__(/*! ../../type/directives.mjs */ "../../.. * See https://spec.graphql.org/draft/#sec-Directives-Are-Unique-Per-Location */ function UniqueDirectivesPerLocationRule(context) { - const uniqueDirectiveMap = new Map(); + const uniqueDirectiveMap = Object.create(null); const schema = context.getSchema(); const definedDirectives = schema ? schema.getDirectives() : _directives.specifiedDirectives; for (const directive of definedDirectives) { - uniqueDirectiveMap.set(directive.name, !directive.isRepeatable); + uniqueDirectiveMap[directive.name] = !directive.isRepeatable; } const astDefinitions = context.getDocument().definitions; for (const def of astDefinitions) { if (def.kind === _kinds.Kind.DIRECTIVE_DEFINITION) { - uniqueDirectiveMap.set(def.name.value, !def.repeatable); + uniqueDirectiveMap[def.name.value] = !def.repeatable; } } - const schemaDirectives = new Map(); - const typeDirectivesMap = new Map(); + const schemaDirectives = Object.create(null); + const typeDirectivesMap = Object.create(null); return { // Many different AST nodes may contain directives. Rather than listing // them all, just listen for entering any node, and check to see if it @@ -40830,24 +39939,22 @@ function UniqueDirectivesPerLocationRule(context) { seenDirectives = schemaDirectives; } else if ((0, _predicates.isTypeDefinitionNode)(node) || (0, _predicates.isTypeExtensionNode)(node)) { const typeName = node.name.value; - seenDirectives = typeDirectivesMap.get(typeName); + seenDirectives = typeDirectivesMap[typeName]; if (seenDirectives === undefined) { - seenDirectives = new Map(); - typeDirectivesMap.set(typeName, seenDirectives); + typeDirectivesMap[typeName] = seenDirectives = Object.create(null); } } else { - seenDirectives = new Map(); + seenDirectives = Object.create(null); } for (const directive of node.directives) { const directiveName = directive.name.value; - if (uniqueDirectiveMap.get(directiveName) === true) { - const seenDirective = seenDirectives.get(directiveName); - if (seenDirective != null) { + if (uniqueDirectiveMap[directiveName]) { + if (seenDirectives[directiveName]) { context.reportError(new _GraphQLError.GraphQLError(`The directive "@${directiveName}" can only be used once at this location.`, { - nodes: [seenDirective, directive] + nodes: [seenDirectives[directiveName], directive] })); } else { - seenDirectives.set(directiveName, directive); + seenDirectives[directiveName] = directive; } } } @@ -40879,7 +39986,7 @@ var _definition = __webpack_require__(/*! ../../type/definition.mjs */ "../../.. function UniqueEnumValueNamesRule(context) { const schema = context.getSchema(); const existingTypeMap = schema ? schema.getTypeMap() : Object.create(null); - const knownValueNames = new Map(); + const knownValueNames = Object.create(null); return { EnumTypeDefinition: checkValueUniqueness, EnumTypeExtension: checkValueUniqueness @@ -40887,14 +39994,14 @@ function UniqueEnumValueNamesRule(context) { function checkValueUniqueness(node) { var _node$values; const typeName = node.name.value; - let valueNames = knownValueNames.get(typeName); - if (valueNames == null) { - valueNames = new Map(); - knownValueNames.set(typeName, valueNames); - } - // FIXME: https://github.com/graphql/graphql-js/issues/2203 + if (!knownValueNames[typeName]) { + knownValueNames[typeName] = Object.create(null); + } // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ + const valueNodes = (_node$values = node.values) !== null && _node$values !== void 0 ? _node$values : []; + const valueNames = knownValueNames[typeName]; for (const valueDef of valueNodes) { const valueName = valueDef.name.value; const existingType = existingTypeMap[typeName]; @@ -40902,15 +40009,12 @@ function UniqueEnumValueNamesRule(context) { context.reportError(new _GraphQLError.GraphQLError(`Enum value "${typeName}.${valueName}" already exists in the schema. It cannot also be defined in this type extension.`, { nodes: valueDef.name })); - continue; - } - const knownValueName = valueNames.get(valueName); - if (knownValueName != null) { + } else if (valueNames[valueName]) { context.reportError(new _GraphQLError.GraphQLError(`Enum value "${typeName}.${valueName}" can only be defined once.`, { - nodes: [knownValueName, valueDef.name] + nodes: [valueNames[valueName], valueDef.name] })); } else { - valueNames.set(valueName, valueDef.name); + valueNames[valueName] = valueDef.name; } } return false; @@ -40941,7 +40045,7 @@ var _definition = __webpack_require__(/*! ../../type/definition.mjs */ "../../.. function UniqueFieldDefinitionNamesRule(context) { const schema = context.getSchema(); const existingTypeMap = schema ? schema.getTypeMap() : Object.create(null); - const knownFieldNames = new Map(); + const knownFieldNames = Object.create(null); return { InputObjectTypeDefinition: checkFieldUniqueness, InputObjectTypeExtension: checkFieldUniqueness, @@ -40953,29 +40057,26 @@ function UniqueFieldDefinitionNamesRule(context) { function checkFieldUniqueness(node) { var _node$fields; const typeName = node.name.value; - let fieldNames = knownFieldNames.get(typeName); - if (fieldNames == null) { - fieldNames = new Map(); - knownFieldNames.set(typeName, fieldNames); - } - // FIXME: https://github.com/graphql/graphql-js/issues/2203 + if (!knownFieldNames[typeName]) { + knownFieldNames[typeName] = Object.create(null); + } // FIXME: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ + const fieldNodes = (_node$fields = node.fields) !== null && _node$fields !== void 0 ? _node$fields : []; + const fieldNames = knownFieldNames[typeName]; for (const fieldDef of fieldNodes) { const fieldName = fieldDef.name.value; if (hasField(existingTypeMap[typeName], fieldName)) { context.reportError(new _GraphQLError.GraphQLError(`Field "${typeName}.${fieldName}" already exists in the schema. It cannot also be defined in this type extension.`, { nodes: fieldDef.name })); - continue; - } - const knownFieldName = fieldNames.get(fieldName); - if (knownFieldName != null) { + } else if (fieldNames[fieldName]) { context.reportError(new _GraphQLError.GraphQLError(`Field "${typeName}.${fieldName}" can only be defined once.`, { - nodes: [knownFieldName, fieldDef.name] + nodes: [fieldNames[fieldName], fieldDef.name] })); } else { - fieldNames.set(fieldName, fieldDef.name); + fieldNames[fieldName] = fieldDef.name; } } return false; @@ -41011,18 +40112,17 @@ var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../ * See https://spec.graphql.org/draft/#sec-Fragment-Name-Uniqueness */ function UniqueFragmentNamesRule(context) { - const knownFragmentNames = new Map(); + const knownFragmentNames = Object.create(null); return { OperationDefinition: () => false, FragmentDefinition(node) { const fragmentName = node.name.value; - const knownFragmentName = knownFragmentNames.get(fragmentName); - if (knownFragmentName != null) { + if (knownFragmentNames[fragmentName]) { context.reportError(new _GraphQLError.GraphQLError(`There can be only one fragment named "${fragmentName}".`, { - nodes: [knownFragmentName, node.name] + nodes: [knownFragmentNames[fragmentName], node.name] })); } else { - knownFragmentNames.set(fragmentName, node.name); + knownFragmentNames[fragmentName] = node.name; } return false; } @@ -41055,28 +40155,27 @@ var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../ */ function UniqueInputFieldNamesRule(context) { const knownNameStack = []; - let knownNames = new Map(); + let knownNames = Object.create(null); return { ObjectValue: { enter() { knownNameStack.push(knownNames); - knownNames = new Map(); + knownNames = Object.create(null); }, leave() { const prevKnownNames = knownNameStack.pop(); - prevKnownNames != null || (0, _invariant.invariant)(false); + prevKnownNames || (0, _invariant.invariant)(false); knownNames = prevKnownNames; } }, ObjectField(node) { const fieldName = node.name.value; - const knownName = knownNames.get(fieldName); - if (knownName != null) { + if (knownNames[fieldName]) { context.reportError(new _GraphQLError.GraphQLError(`There can be only one input field named "${fieldName}".`, { - nodes: [knownName, node.name] + nodes: [knownNames[fieldName], node.name] })); } else { - knownNames.set(fieldName, node.name); + knownNames[fieldName] = node.name; } } }; @@ -41105,18 +40204,17 @@ var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../ * See https://spec.graphql.org/draft/#sec-Operation-Name-Uniqueness */ function UniqueOperationNamesRule(context) { - const knownOperationNames = new Map(); + const knownOperationNames = Object.create(null); return { OperationDefinition(node) { const operationName = node.name; - if (operationName != null) { - const knownOperationName = knownOperationNames.get(operationName.value); - if (knownOperationName != null) { + if (operationName) { + if (knownOperationNames[operationName.value]) { context.reportError(new _GraphQLError.GraphQLError(`There can be only one operation named "${operationName.value}".`, { - nodes: [knownOperationName, operationName] + nodes: [knownOperationNames[operationName.value], operationName] })); } else { - knownOperationNames.set(operationName.value, operationName); + knownOperationNames[operationName.value] = operationName; } } return false; @@ -41147,7 +40245,7 @@ var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../ */ function UniqueOperationTypesRule(context) { const schema = context.getSchema(); - const definedOperationTypes = new Map(); + const definedOperationTypes = Object.create(null); const existingOperationTypes = schema ? { query: schema.getQueryType(), mutation: schema.getMutationType(), @@ -41159,12 +40257,14 @@ function UniqueOperationTypesRule(context) { }; function checkOperationTypes(node) { var _node$operationTypes; + // See: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ const operationTypesNodes = (_node$operationTypes = node.operationTypes) !== null && _node$operationTypes !== void 0 ? _node$operationTypes : []; for (const operationType of operationTypesNodes) { const operation = operationType.operation; - const alreadyDefinedOperationType = definedOperationTypes.get(operation); + const alreadyDefinedOperationType = definedOperationTypes[operation]; if (existingOperationTypes[operation]) { context.reportError(new _GraphQLError.GraphQLError(`Type for ${operation} already defined in the schema. It cannot be redefined.`, { nodes: operationType @@ -41174,7 +40274,7 @@ function UniqueOperationTypesRule(context) { nodes: [alreadyDefinedOperationType, operationType] })); } else { - definedOperationTypes.set(operation, operationType); + definedOperationTypes[operation] = operationType; } } return false; @@ -41202,7 +40302,7 @@ var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../ * A GraphQL document is only valid if all defined types have unique names. */ function UniqueTypeNamesRule(context) { - const knownTypeNames = new Map(); + const knownTypeNames = Object.create(null); const schema = context.getSchema(); return { ScalarTypeDefinition: checkTypeName, @@ -41220,13 +40320,12 @@ function UniqueTypeNamesRule(context) { })); return; } - const knownNameNode = knownTypeNames.get(typeName); - if (knownNameNode != null) { + if (knownTypeNames[typeName]) { context.reportError(new _GraphQLError.GraphQLError(`There can be only one type named "${typeName}".`, { - nodes: [knownNameNode, node.name] + nodes: [knownTypeNames[typeName], node.name] })); } else { - knownTypeNames.set(typeName, node.name); + knownTypeNames[typeName] = node.name; } return false; } @@ -41257,7 +40356,9 @@ function UniqueVariableNamesRule(context) { return { OperationDefinition(operationNode) { var _operationNode$variab; + // See: https://github.com/graphql/graphql-js/issues/2203 + /* c8 ignore next */ const variableDefinitions = (_operationNode$variab = operationNode.variableDefinitions) !== null && _operationNode$variab !== void 0 ? _operationNode$variab : []; const seenVariableDefinitions = (0, _groupBy.groupBy)(variableDefinitions, node => node.variable.name.value); @@ -41288,6 +40389,7 @@ Object.defineProperty(exports, "__esModule", ({ exports.ValuesOfCorrectTypeRule = ValuesOfCorrectTypeRule; var _didYouMean = __webpack_require__(/*! ../../jsutils/didYouMean.mjs */ "../../../node_modules/graphql/jsutils/didYouMean.mjs"); var _inspect = __webpack_require__(/*! ../../jsutils/inspect.mjs */ "../../../node_modules/graphql/jsutils/inspect.mjs"); +var _keyMap = __webpack_require__(/*! ../../jsutils/keyMap.mjs */ "../../../node_modules/graphql/jsutils/keyMap.mjs"); var _suggestionList = __webpack_require__(/*! ../../jsutils/suggestionList.mjs */ "../../../node_modules/graphql/jsutils/suggestionList.mjs"); var _GraphQLError = __webpack_require__(/*! ../../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); var _kinds = __webpack_require__(/*! ../../language/kinds.mjs */ "../../../node_modules/graphql/language/kinds.mjs"); @@ -41326,11 +40428,11 @@ function ValuesOfCorrectTypeRule(context) { if (!(0, _definition.isInputObjectType)(type)) { isValidValueNode(context, node); return false; // Don't traverse further. - } - // Ensure every required field exists. - const fieldNodeMap = new Map(node.fields.map(field => [field.name.value, field])); + } // Ensure every required field exists. + + const fieldNodeMap = (0, _keyMap.keyMap)(node.fields, field => field.name.value); for (const fieldDef of Object.values(type.getFields())) { - const fieldNode = fieldNodeMap.get(fieldDef.name); + const fieldNode = fieldNodeMap[fieldDef.name]; if (!fieldNode && (0, _definition.isRequiredInputField)(fieldDef)) { const typeStr = (0, _inspect.inspect)(fieldDef.type); context.reportError(new _GraphQLError.GraphQLError(`Field "${type.name}.${fieldDef.name}" of required type "${typeStr}" was not provided.`, { @@ -41371,6 +40473,7 @@ function ValuesOfCorrectTypeRule(context) { * Any value literal may be a valid representation of a Scalar, depending on * that scalar type. */ + function isValidValueNode(context, node) { // Report any error at the full type expected by the location. const locationType = context.getInputType(); @@ -41384,11 +40487,12 @@ function isValidValueNode(context, node) { nodes: node })); return; - } - // Scalars and Enums determine if a literal value is valid via parseLiteral(), + } // Scalars and Enums determine if a literal value is valid via parseLiteral(), // which may throw or return an invalid value to indicate failure. + try { - const parseResult = type.parseLiteral(node, undefined /* variables */); + const parseResult = type.parseLiteral(node, undefined + /* variables */); if (parseResult === undefined) { const typeStr = (0, _inspect.inspect)(locationType); context.reportError(new _GraphQLError.GraphQLError(`Expected value of type "${typeStr}", found ${(0, _printer.print)(node)}.`, { @@ -41408,8 +40512,8 @@ function isValidValueNode(context, node) { } } function validateOneOfInputObject(context, node, type, fieldNodeMap, variableDefinitions) { - var _fieldNodeMap$get; - const keys = Array.from(fieldNodeMap.keys()); + var _fieldNodeMap$keys$; + const keys = Object.keys(fieldNodeMap); const isNotExactlyOneField = keys.length !== 1; if (isNotExactlyOneField) { context.reportError(new _GraphQLError.GraphQLError(`OneOf Input Object "${type.name}" must specify exactly one key.`, { @@ -41417,7 +40521,7 @@ function validateOneOfInputObject(context, node, type, fieldNodeMap, variableDef })); return; } - const value = (_fieldNodeMap$get = fieldNodeMap.get(keys[0])) === null || _fieldNodeMap$get === void 0 ? void 0 : _fieldNodeMap$get.value; + const value = (_fieldNodeMap$keys$ = fieldNodeMap[keys[0]]) === null || _fieldNodeMap$keys$ === void 0 ? void 0 : _fieldNodeMap$keys$.value; const isNullLiteral = !value || value.kind === _kinds.Kind.NULL; const isVariable = (value === null || value === void 0 ? void 0 : value.kind) === _kinds.Kind.VARIABLE; if (isNullLiteral) { @@ -41507,11 +40611,11 @@ var _typeFromAST = __webpack_require__(/*! ../../utilities/typeFromAST.mjs */ ". * See https://spec.graphql.org/draft/#sec-All-Variable-Usages-are-Allowed */ function VariablesInAllowedPositionRule(context) { - let varDefMap; + let varDefMap = Object.create(null); return { OperationDefinition: { enter() { - varDefMap = new Map(); + varDefMap = Object.create(null); }, leave(operation) { const usages = context.getRecursiveVariableUsages(operation); @@ -41521,7 +40625,7 @@ function VariablesInAllowedPositionRule(context) { defaultValue } of usages) { const varName = node.name.value; - const varDef = varDefMap.get(varName); + const varDef = varDefMap[varName]; if (varDef && type) { // A var type is allowed if it is the same or more strict (e.g. is // a subtype of) than the expected type. It can be more strict if @@ -41542,7 +40646,7 @@ function VariablesInAllowedPositionRule(context) { } }, VariableDefinition(node) { - varDefMap.set(node.variable.name.value, node); + varDefMap[node.variable.name.value] = node; } }; } @@ -41551,6 +40655,7 @@ function VariablesInAllowedPositionRule(context) { * which includes considering if default values exist for either the variable * or the location at which it is located. */ + function allowedVariableUsage(schema, varType, varDefaultValue, locationType, locationDefaultValue) { if ((0, _definition.isNonNullType)(locationType) && !(0, _definition.isNonNullType)(varType)) { const hasNonNullVariableDefaultValue = varDefaultValue != null && varDefaultValue.kind !== _kinds.Kind.NULL; @@ -41703,9 +40808,6 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.specifiedSDLRules = exports.specifiedRules = exports.recommendedRules = void 0; -var _DeferStreamDirectiveLabelRule = __webpack_require__(/*! ./rules/DeferStreamDirectiveLabelRule.mjs */ "../../../node_modules/graphql/validation/rules/DeferStreamDirectiveLabelRule.mjs"); -var _DeferStreamDirectiveOnRootFieldRule = __webpack_require__(/*! ./rules/DeferStreamDirectiveOnRootFieldRule.mjs */ "../../../node_modules/graphql/validation/rules/DeferStreamDirectiveOnRootFieldRule.mjs"); -var _DeferStreamDirectiveOnValidOperationsRule = __webpack_require__(/*! ./rules/DeferStreamDirectiveOnValidOperationsRule.mjs */ "../../../node_modules/graphql/validation/rules/DeferStreamDirectiveOnValidOperationsRule.mjs"); var _ExecutableDefinitionsRule = __webpack_require__(/*! ./rules/ExecutableDefinitionsRule.mjs */ "../../../node_modules/graphql/validation/rules/ExecutableDefinitionsRule.mjs"); var _FieldsOnCorrectTypeRule = __webpack_require__(/*! ./rules/FieldsOnCorrectTypeRule.mjs */ "../../../node_modules/graphql/validation/rules/FieldsOnCorrectTypeRule.mjs"); var _FragmentsOnCompositeTypesRule = __webpack_require__(/*! ./rules/FragmentsOnCompositeTypesRule.mjs */ "../../../node_modules/graphql/validation/rules/FragmentsOnCompositeTypesRule.mjs"); @@ -41726,7 +40828,6 @@ var _PossibleTypeExtensionsRule = __webpack_require__(/*! ./rules/PossibleTypeEx var _ProvidedRequiredArgumentsRule = __webpack_require__(/*! ./rules/ProvidedRequiredArgumentsRule.mjs */ "../../../node_modules/graphql/validation/rules/ProvidedRequiredArgumentsRule.mjs"); var _ScalarLeafsRule = __webpack_require__(/*! ./rules/ScalarLeafsRule.mjs */ "../../../node_modules/graphql/validation/rules/ScalarLeafsRule.mjs"); var _SingleFieldSubscriptionsRule = __webpack_require__(/*! ./rules/SingleFieldSubscriptionsRule.mjs */ "../../../node_modules/graphql/validation/rules/SingleFieldSubscriptionsRule.mjs"); -var _StreamDirectiveOnListFieldRule = __webpack_require__(/*! ./rules/StreamDirectiveOnListFieldRule.mjs */ "../../../node_modules/graphql/validation/rules/StreamDirectiveOnListFieldRule.mjs"); var _UniqueArgumentDefinitionNamesRule = __webpack_require__(/*! ./rules/UniqueArgumentDefinitionNamesRule.mjs */ "../../../node_modules/graphql/validation/rules/UniqueArgumentDefinitionNamesRule.mjs"); var _UniqueArgumentNamesRule = __webpack_require__(/*! ./rules/UniqueArgumentNamesRule.mjs */ "../../../node_modules/graphql/validation/rules/UniqueArgumentNamesRule.mjs"); var _UniqueDirectiveNamesRule = __webpack_require__(/*! ./rules/UniqueDirectiveNamesRule.mjs */ "../../../node_modules/graphql/validation/rules/UniqueDirectiveNamesRule.mjs"); @@ -41742,14 +40843,7 @@ var _UniqueVariableNamesRule = __webpack_require__(/*! ./rules/UniqueVariableNam var _ValuesOfCorrectTypeRule = __webpack_require__(/*! ./rules/ValuesOfCorrectTypeRule.mjs */ "../../../node_modules/graphql/validation/rules/ValuesOfCorrectTypeRule.mjs"); var _VariablesAreInputTypesRule = __webpack_require__(/*! ./rules/VariablesAreInputTypesRule.mjs */ "../../../node_modules/graphql/validation/rules/VariablesAreInputTypesRule.mjs"); var _VariablesInAllowedPositionRule = __webpack_require__(/*! ./rules/VariablesInAllowedPositionRule.mjs */ "../../../node_modules/graphql/validation/rules/VariablesInAllowedPositionRule.mjs"); -// Spec Section: "Defer And Stream Directive Labels Are Unique" - -// Spec Section: "Defer And Stream Directives Are Used On Valid Root Field" - -// Spec Section: "Defer And Stream Directives Are Used On Valid Operations" - // Spec Section: "Executable Definitions" - // Spec Section: "Field Selections on Objects, Interfaces, and Unions Types" // Spec Section: "Fragments on Composite Types" @@ -41786,8 +40880,6 @@ var _VariablesInAllowedPositionRule = __webpack_require__(/*! ./rules/VariablesI // Spec Section: "Subscriptions with Single Root Field" -// Spec Section: "Stream Directives Are Used On List Fields" - // Spec Section: "Argument Uniqueness" // Spec Section: "Directives Are Unique Per Location" @@ -41817,10 +40909,12 @@ const recommendedRules = exports.recommendedRules = Object.freeze([_MaxIntrospec * The order of the rules in this list has been adjusted to lead to the * most clear output when encountering multiple validation errors. */ -const specifiedRules = exports.specifiedRules = Object.freeze([_ExecutableDefinitionsRule.ExecutableDefinitionsRule, _UniqueOperationNamesRule.UniqueOperationNamesRule, _LoneAnonymousOperationRule.LoneAnonymousOperationRule, _SingleFieldSubscriptionsRule.SingleFieldSubscriptionsRule, _KnownTypeNamesRule.KnownTypeNamesRule, _FragmentsOnCompositeTypesRule.FragmentsOnCompositeTypesRule, _VariablesAreInputTypesRule.VariablesAreInputTypesRule, _ScalarLeafsRule.ScalarLeafsRule, _FieldsOnCorrectTypeRule.FieldsOnCorrectTypeRule, _UniqueFragmentNamesRule.UniqueFragmentNamesRule, _KnownFragmentNamesRule.KnownFragmentNamesRule, _NoUnusedFragmentsRule.NoUnusedFragmentsRule, _PossibleFragmentSpreadsRule.PossibleFragmentSpreadsRule, _NoFragmentCyclesRule.NoFragmentCyclesRule, _UniqueVariableNamesRule.UniqueVariableNamesRule, _NoUndefinedVariablesRule.NoUndefinedVariablesRule, _NoUnusedVariablesRule.NoUnusedVariablesRule, _KnownDirectivesRule.KnownDirectivesRule, _UniqueDirectivesPerLocationRule.UniqueDirectivesPerLocationRule, _DeferStreamDirectiveOnRootFieldRule.DeferStreamDirectiveOnRootFieldRule, _DeferStreamDirectiveOnValidOperationsRule.DeferStreamDirectiveOnValidOperationsRule, _DeferStreamDirectiveLabelRule.DeferStreamDirectiveLabelRule, _StreamDirectiveOnListFieldRule.StreamDirectiveOnListFieldRule, _KnownArgumentNamesRule.KnownArgumentNamesRule, _UniqueArgumentNamesRule.UniqueArgumentNamesRule, _ValuesOfCorrectTypeRule.ValuesOfCorrectTypeRule, _ProvidedRequiredArgumentsRule.ProvidedRequiredArgumentsRule, _VariablesInAllowedPositionRule.VariablesInAllowedPositionRule, _OverlappingFieldsCanBeMergedRule.OverlappingFieldsCanBeMergedRule, _UniqueInputFieldNamesRule.UniqueInputFieldNamesRule, ...recommendedRules]); + +const specifiedRules = exports.specifiedRules = Object.freeze([_ExecutableDefinitionsRule.ExecutableDefinitionsRule, _UniqueOperationNamesRule.UniqueOperationNamesRule, _LoneAnonymousOperationRule.LoneAnonymousOperationRule, _SingleFieldSubscriptionsRule.SingleFieldSubscriptionsRule, _KnownTypeNamesRule.KnownTypeNamesRule, _FragmentsOnCompositeTypesRule.FragmentsOnCompositeTypesRule, _VariablesAreInputTypesRule.VariablesAreInputTypesRule, _ScalarLeafsRule.ScalarLeafsRule, _FieldsOnCorrectTypeRule.FieldsOnCorrectTypeRule, _UniqueFragmentNamesRule.UniqueFragmentNamesRule, _KnownFragmentNamesRule.KnownFragmentNamesRule, _NoUnusedFragmentsRule.NoUnusedFragmentsRule, _PossibleFragmentSpreadsRule.PossibleFragmentSpreadsRule, _NoFragmentCyclesRule.NoFragmentCyclesRule, _UniqueVariableNamesRule.UniqueVariableNamesRule, _NoUndefinedVariablesRule.NoUndefinedVariablesRule, _NoUnusedVariablesRule.NoUnusedVariablesRule, _KnownDirectivesRule.KnownDirectivesRule, _UniqueDirectivesPerLocationRule.UniqueDirectivesPerLocationRule, _KnownArgumentNamesRule.KnownArgumentNamesRule, _UniqueArgumentNamesRule.UniqueArgumentNamesRule, _ValuesOfCorrectTypeRule.ValuesOfCorrectTypeRule, _ProvidedRequiredArgumentsRule.ProvidedRequiredArgumentsRule, _VariablesInAllowedPositionRule.VariablesInAllowedPositionRule, _OverlappingFieldsCanBeMergedRule.OverlappingFieldsCanBeMergedRule, _UniqueInputFieldNamesRule.UniqueInputFieldNamesRule, ...recommendedRules]); /** * @internal */ + const specifiedSDLRules = exports.specifiedSDLRules = Object.freeze([_LoneSchemaDefinitionRule.LoneSchemaDefinitionRule, _UniqueOperationTypesRule.UniqueOperationTypesRule, _UniqueTypeNamesRule.UniqueTypeNamesRule, _UniqueEnumValueNamesRule.UniqueEnumValueNamesRule, _UniqueFieldDefinitionNamesRule.UniqueFieldDefinitionNamesRule, _UniqueArgumentDefinitionNamesRule.UniqueArgumentDefinitionNamesRule, _UniqueDirectiveNamesRule.UniqueDirectiveNamesRule, _KnownTypeNamesRule.KnownTypeNamesRule, _KnownDirectivesRule.KnownDirectivesRule, _UniqueDirectivesPerLocationRule.UniqueDirectivesPerLocationRule, _PossibleTypeExtensionsRule.PossibleTypeExtensionsRule, _KnownArgumentNamesRule.KnownArgumentNamesOnDirectivesRule, _UniqueArgumentNamesRule.UniqueArgumentNamesRule, _UniqueInputFieldNamesRule.UniqueInputFieldNamesRule, _ProvidedRequiredArgumentsRule.ProvidedRequiredArgumentsOnDirectivesRule]); /***/ }), @@ -41840,6 +40934,7 @@ exports.assertValidSDL = assertValidSDL; exports.assertValidSDLExtension = assertValidSDLExtension; exports.validate = validate; exports.validateSDL = validateSDL; +var _devAssert = __webpack_require__(/*! ../jsutils/devAssert.mjs */ "../../../node_modules/graphql/jsutils/devAssert.mjs"); var _GraphQLError = __webpack_require__(/*! ../error/GraphQLError.mjs */ "../../../node_modules/graphql/error/GraphQLError.mjs"); var _visitor = __webpack_require__(/*! ../language/visitor.mjs */ "../../../node_modules/graphql/language/visitor.mjs"); var _validate = __webpack_require__(/*! ../type/validate.mjs */ "../../../node_modules/graphql/type/validate.mjs"); @@ -41866,30 +40961,32 @@ var _ValidationContext = __webpack_require__(/*! ./ValidationContext.mjs */ "../ * Optionally a custom TypeInfo instance may be provided. If not provided, one * will be created from the provided schema. */ + function validate(schema, documentAST, rules = _specifiedRules.specifiedRules, options, /** @deprecated will be removed in 17.0.0 */ typeInfo = new _TypeInfo.TypeInfo(schema)) { var _options$maxErrors; const maxErrors = (_options$maxErrors = options === null || options === void 0 ? void 0 : options.maxErrors) !== null && _options$maxErrors !== void 0 ? _options$maxErrors : 100; - // If the schema used for validation is invalid, throw an error. + documentAST || (0, _devAssert.devAssert)(false, 'Must provide document.'); // If the schema used for validation is invalid, throw an error. + (0, _validate.assertValidSchema)(schema); - const abortError = new _GraphQLError.GraphQLError('Too many validation errors, error limit reached. Validation aborted.'); + const abortObj = Object.freeze({}); const errors = []; const context = new _ValidationContext.ValidationContext(schema, documentAST, typeInfo, error => { if (errors.length >= maxErrors) { - throw abortError; + errors.push(new _GraphQLError.GraphQLError('Too many validation errors, error limit reached. Validation aborted.')); // eslint-disable-next-line @typescript-eslint/no-throw-literal + + throw abortObj; } errors.push(error); - }); - // This uses a specialized visitor which runs multiple visitors in parallel, + }); // This uses a specialized visitor which runs multiple visitors in parallel, // while maintaining the visitor skip and break API. - const visitor = (0, _visitor.visitInParallel)(rules.map(rule => rule(context))); - // Visit the whole document with each instance of all provided rules. + + const visitor = (0, _visitor.visitInParallel)(rules.map(rule => rule(context))); // Visit the whole document with each instance of all provided rules. + try { (0, _visitor.visit)(documentAST, (0, _TypeInfo.visitWithTypeInfo)(typeInfo, visitor)); } catch (e) { - if (e === abortError) { - errors.push(abortError); - } else { + if (e !== abortObj) { throw e; } } @@ -41898,6 +40995,7 @@ typeInfo = new _TypeInfo.TypeInfo(schema)) { /** * @internal */ + function validateSDL(documentAST, schemaToExtend, rules = _specifiedRules.specifiedSDLRules) { const errors = []; const context = new _ValidationContext.SDLValidationContext(documentAST, schemaToExtend, error => { @@ -41913,6 +41011,7 @@ function validateSDL(documentAST, schemaToExtend, rules = _specifiedRules.specif * * @internal */ + function assertValidSDL(documentAST) { const errors = validateSDL(documentAST); if (errors.length !== 0) { @@ -41925,6 +41024,7 @@ function assertValidSDL(documentAST) { * * @internal */ + function assertValidSDLExtension(documentAST, schema) { const errors = validateSDL(documentAST, schema); if (errors.length !== 0) { @@ -41948,18 +41048,20 @@ Object.defineProperty(exports, "__esModule", ({ exports.versionInfo = exports.version = void 0; // Note: This file is autogenerated using "resources/gen-version.js" script and // automatically updated by "npm version" command. + /** * A string containing the version of the GraphQL.js library */ -const version = exports.version = '17.0.0-alpha.7'; +const version = exports.version = '16.9.0'; /** * An object containing the components of the GraphQL.js version string */ + const versionInfo = exports.versionInfo = Object.freeze({ - major: 17, - minor: 0, + major: 16, + minor: 9, patch: 0, - preReleaseTag: 'alpha.7' + preReleaseTag: null }); /***/ }), @@ -69309,7 +68411,7 @@ function createContextHook(context) { var _a; const value = React.useContext(context); if (value === null && (options == null ? void 0 : options.nonNull)) { - throw new Error(`Tried to use \`${((_a = options.caller) == null ? void 0 : _a.name) || useGivenContext.caller.name}\` without the necessary context. Make sure to render the \`${context.displayName}Provider\` component higher up the tree.`); + throw new Error(`Tried to use \`${((_a = options.caller) == null ? void 0 : _a.name) || "a component"}\` without the necessary context. Make sure to render the \`${context.displayName}Provider\` component higher up the tree.`); } return value; } diff --git a/netbox/project-static/dist/netbox.css b/netbox/project-static/dist/netbox.css index 8bf61408f..084736acb 100644 Binary files a/netbox/project-static/dist/netbox.css and b/netbox/project-static/dist/netbox.css differ diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index 969d5c73a..1492913d9 100644 Binary files a/netbox/project-static/dist/netbox.js and b/netbox/project-static/dist/netbox.js differ diff --git a/netbox/project-static/dist/netbox.js.map b/netbox/project-static/dist/netbox.js.map index 0f4ac63d3..bfe749fd7 100644 Binary files a/netbox/project-static/dist/netbox.js.map and b/netbox/project-static/dist/netbox.js.map differ diff --git a/netbox/project-static/netbox-graphiql/package.json b/netbox/project-static/netbox-graphiql/package.json index 27257e34c..c5b2f3077 100644 --- a/netbox/project-static/netbox-graphiql/package.json +++ b/netbox/project-static/netbox-graphiql/package.json @@ -1,13 +1,13 @@ { "name": "netbox-graphiql", - "version": "4.1.0", + "version": "4.2.0", "description": "NetBox GraphiQL Custom Front End", "main": "dist/graphiql.js", "license": "Apache-2.0", "private": true, "dependencies": { - "@graphiql/plugin-explorer": "3.2.2", - "graphiql": "3.7.1", + "@graphiql/plugin-explorer": "3.2.3", + "graphiql": "3.7.2", "graphql": "16.9.0", "js-cookie": "3.0.5", "react": "18.3.1", diff --git a/netbox/project-static/package.json b/netbox/project-static/package.json index 1342c299f..34974fe12 100644 --- a/netbox/project-static/package.json +++ b/netbox/project-static/package.json @@ -1,6 +1,6 @@ { "name": "netbox", - "version": "4.0.0", + "version": "4.1.0", "main": "dist/netbox.js", "license": "Apache-2.0", "private": true, @@ -27,11 +27,11 @@ "bootstrap": "5.3.3", "clipboard": "2.0.11", "flatpickr": "4.6.13", - "gridstack": "10.3.1", + "gridstack": "11.1.2", "htmx.org": "1.9.12", "query-string": "9.1.1", - "sass": "1.79.5", - "tom-select": "2.3.1", + "sass": "1.82.0", + "tom-select": "2.4.1", "typeface-inter": "3.18.1", "typeface-roboto-mono": "1.1.13" }, diff --git a/netbox/project-static/src/buttons/reslug.ts b/netbox/project-static/src/buttons/reslug.ts index f445854c1..53c21b1f0 100644 --- a/netbox/project-static/src/buttons/reslug.ts +++ b/netbox/project-static/src/buttons/reslug.ts @@ -1,3 +1,5 @@ +import { getElements } from '../util'; + /** * Create a slug from any input string. * @@ -15,34 +17,30 @@ function slugify(slug: string, chars: number): string { } /** - * If a slug field exists, add event listeners to handle automatically generating its value. + * For any slug fields, add event listeners to handle automatically generating slug values. */ export function initReslug(): void { - const slugField = document.getElementById('id_slug') as HTMLInputElement; - const slugButton = document.getElementById('reslug') as HTMLButtonElement; - if (slugField === null || slugButton === null) { - return; - } - const sourceId = slugField.getAttribute('slug-source'); - const sourceField = document.getElementById(`id_${sourceId}`) as HTMLInputElement; + for (const slugButton of getElements('button#reslug')) { + const form = slugButton.form; + if (form == null) continue; + const slugField = form.querySelector('#id_slug') as HTMLInputElement; + if (slugField == null) continue; + const sourceId = slugField.getAttribute('slug-source'); + const sourceField = form.querySelector(`#id_${sourceId}`) as HTMLInputElement; - if (sourceField === null) { - console.error('Unable to find field for slug field.'); - return; - } + const slugLengthAttr = slugField.getAttribute('maxlength'); + let slugLength = 50; - const slugLengthAttr = slugField.getAttribute('maxlength'); - let slugLength = 50; - - if (slugLengthAttr) { - slugLength = Number(slugLengthAttr); - } - sourceField.addEventListener('blur', () => { - if (!slugField.value) { - slugField.value = slugify(sourceField.value, slugLength); + if (slugLengthAttr) { + slugLength = Number(slugLengthAttr); } - }); - slugButton.addEventListener('click', () => { - slugField.value = slugify(sourceField.value, slugLength); - }); + sourceField.addEventListener('blur', () => { + if (!slugField.value) { + slugField.value = slugify(sourceField.value, slugLength); + } + }); + slugButton.addEventListener('click', () => { + slugField.value = slugify(sourceField.value, slugLength); + }); + } } diff --git a/netbox/project-static/src/htmx.ts b/netbox/project-static/src/htmx.ts index f4092036b..6a772011b 100644 --- a/netbox/project-static/src/htmx.ts +++ b/netbox/project-static/src/htmx.ts @@ -4,11 +4,16 @@ import { initSelects } from './select'; import { initObjectSelector } from './objectSelector'; import { initBootstrap } from './bs'; import { initMessages } from './messages'; +import { initQuickAdd } from './quickAdd'; function initDepedencies(): void { - for (const init of [initButtons, initClipboard, initSelects, initObjectSelector, initBootstrap, initMessages]) { - init(); - } + initButtons(); + initClipboard(); + initSelects(); + initObjectSelector(); + initQuickAdd(); + initBootstrap(); + initMessages(); } /** diff --git a/netbox/project-static/src/quickAdd.ts b/netbox/project-static/src/quickAdd.ts new file mode 100644 index 000000000..e038f5d19 --- /dev/null +++ b/netbox/project-static/src/quickAdd.ts @@ -0,0 +1,39 @@ +import { Modal } from 'bootstrap'; + +function handleQuickAddObject(): void { + const quick_add = document.getElementById('quick-add-object'); + if (quick_add == null) return; + + const object_id = quick_add.getAttribute('data-object-id'); + if (object_id == null) return; + const object_repr = quick_add.getAttribute('data-object-repr'); + if (object_repr == null) return; + + const target_id = quick_add.getAttribute('data-target-id'); + if (target_id == null) return; + const target = document.getElementById(target_id); + if (target == null) return; + + //@ts-expect-error tomselect added on init + target.tomselect.addOption({ + id: object_id, + display: object_repr, + }); + //@ts-expect-error tomselect added on init + target.tomselect.addItem(object_id); + + const modal_element = document.getElementById('htmx-modal'); + if (modal_element) { + const modal = Modal.getInstance(modal_element); + if (modal) { + modal.hide(); + } + } +} + +export function initQuickAdd(): void { + const quick_add_modal = document.getElementById('htmx-modal-content'); + if (quick_add_modal) { + quick_add_modal.addEventListener('htmx:afterSwap', () => handleQuickAddObject()); + } +} diff --git a/netbox/project-static/src/select/classes/dynamicTomSelect.ts b/netbox/project-static/src/select/classes/dynamicTomSelect.ts index 72c9fe518..8e44ce6a7 100644 --- a/netbox/project-static/src/select/classes/dynamicTomSelect.ts +++ b/netbox/project-static/src/select/classes/dynamicTomSelect.ts @@ -1,18 +1,17 @@ -import { RecursivePartial, TomInput, TomOption, TomSettings } from 'tom-select/dist/types/types'; -import { addClasses } from 'tom-select/src/vanilla' +import { RecursivePartial, TomOption, TomSettings } from 'tom-select/dist/types/types'; +import { TomInput } from 'tom-select/dist/cjs/types/core'; +import { addClasses } from 'tom-select/src/vanilla.ts'; import queryString from 'query-string'; import TomSelect from 'tom-select'; import type { Stringifiable } from 'query-string'; import { DynamicParamsMap } from './dynamicParamsMap'; // Transitional -import { QueryFilter, PathFilter } from '../types' +import { QueryFilter, PathFilter } from '../types'; import { getElement, replaceAll } from '../../util'; - // Extends TomSelect to provide enhanced fetching of options via the REST API export class DynamicTomSelect extends TomSelect { - public readonly nullOption: Nullable = null; // Transitional code from APISelect @@ -25,7 +24,7 @@ export class DynamicTomSelect extends TomSelect { * Overrides */ - constructor( input_arg: string|TomInput, user_settings: RecursivePartial ) { + constructor(input_arg: string | TomInput, user_settings: RecursivePartial) { super(input_arg, user_settings); // Glean the REST API endpoint URL from the {% endif %} + diff --git a/netbox/templates/extras/dashboard/widgets/rssfeed.html b/netbox/templates/extras/dashboard/widgets/rssfeed.html index 4420783fd..fa602a112 100644 --- a/netbox/templates/extras/dashboard/widgets/rssfeed.html +++ b/netbox/templates/extras/dashboard/widgets/rssfeed.html @@ -12,6 +12,10 @@
    {% trans "No content found" %}
    {% endfor %}
    +{% elif isolated_deployment %} + + {% trans "This RSS feed requires an external connection. Check the ISOLATED_DEPLOYMENT setting." %} + {% else %} {# There was an error retrieving/parsing the feed #} diff --git a/netbox/templates/extras/script_list.html b/netbox/templates/extras/script_list.html index 5b7361a12..cbffbf8de 100644 --- a/netbox/templates/extras/script_list.html +++ b/netbox/templates/extras/script_list.html @@ -37,101 +37,104 @@ {% endif %} - {% if module.scripts %} - - - - - - - - - - - - {% for script in module.scripts.all %} - {% with last_job=script.get_latest_jobs|first %} - - +
    {% trans "Name" %}{% trans "Description" %}{% trans "Last Run" %}{% trans "Status" %}
    - {% if script.is_executable %} - {{ script.python_class.name }} + {% with scripts=module.scripts.all %} + {% if scripts %} + + + + + + + + + + + + {% for script in scripts %} + {% with last_job=script.get_latest_jobs|first %} + + + + {% if last_job %} + + {% else %} - {{ script.python_class.name }} - - - + + {% endif %} - - + + {% if last_job %} - - - {% else %} - - + {% for test_name, data in last_job.data.tests.items %} + + + + + {% endfor %} + {% elif not last_job.data.log %} + {# legacy #} + {% for method, stats in last_job.data.items %} + + + + + {% endfor %} {% endif %} - - - {% if last_job %} - {% for test_name, data in last_job.data.tests.items %} - - - - - {% endfor %} - {% elif not last_job.data.log %} - {# legacy #} - {% for method, stats in last_job.data.items %} - - - - - {% endfor %} - {% endif %} - {% endwith %} - {% endfor %} - -
    {% trans "Name" %}{% trans "Description" %}{% trans "Last Run" %}{% trans "Status" %}
    + {% if script.is_executable %} + {{ script.python_class.name }} + {% else %} + {{ script.python_class.name }} + + + + {% endif %} + {{ script.python_class.Meta.description|markdown|placeholder }} + {{ last_job.created|isodatetime }} + + {% badge last_job.get_status_display last_job.get_status_color %} + {% trans "Never" %}{{ ''|placeholder }}{{ script.python_class.Meta.description|markdown|placeholder }} + {% if request.user|can_run:script and script.is_executable %} +
    +
    + {% csrf_token %} + +
    +
    + {% endif %} +
    - {{ last_job.created|isodatetime }} - - {% badge last_job.get_status_display last_job.get_status_color %} - {% trans "Never" %}{{ ''|placeholder }}
    + {{ test_name }} + + {{ data.success }} + {{ data.info }} + {{ data.warning }} + {{ data.failure }} +
    + {{ method }} + + {{ stats.success }} + {{ stats.info }} + {{ stats.warning }} + {{ stats.failure }} +
    - {% if request.user|can_run:script and script.is_executable %} -
    -
    - {% csrf_token %} - -
    -
    - {% endif %} -
    - {{ test_name }} - - {{ data.success }} - {{ data.info }} - {{ data.warning }} - {{ data.failure }} -
    - {{ method }} - - {{ stats.success }} - {{ stats.info }} - {{ stats.warning }} - {{ stats.failure }} -
    - {% else %} -
    -
    + {% else %} +
    +
    - - {% endif %} + {% endif %} + {% endwith %} {% empty %} diff --git a/netbox/templates/ipam/vlan_edit.html b/netbox/templates/ipam/vlan_edit.html index 814fc6b78..885844580 100644 --- a/netbox/templates/ipam/vlan_edit.html +++ b/netbox/templates/ipam/vlan_edit.html @@ -17,6 +17,14 @@ {% render_field form.tags %} +
    +
    +

    {% trans "Q-in-Q (802.1ad)" %}

    +
    + {% render_field form.qinq_role %} + {% render_field form.qinq_svlan %} +
    +

    {% trans "Tenancy" %}

    diff --git a/netbox/templates/ipam/vlantranslationpolicy.html b/netbox/templates/ipam/vlantranslationpolicy.html new file mode 100644 index 000000000..58a1201d4 --- /dev/null +++ b/netbox/templates/ipam/vlantranslationpolicy.html @@ -0,0 +1,65 @@ +{% extends 'generic/object.html' %} +{% load helpers %} +{% load plugins %} +{% load render_table from django_tables2 %} +{% load i18n %} + +{% block content %} +
    +
    +
    +

    {% trans "VLAN Translation Policy" %}

    + + + + + + + + + + + + + +
    {% trans "Name" %}{{ object.name|placeholder }}
    {% trans "Description" %}{{ object.description|placeholder }}
    {% trans "Rules" %} + {% if object.rules.count %} + {{ object.rules.count }} + {% else %} + 0 + {% endif %} +
    +
    + {% plugin_left_page object %} +
    +
    + {% include 'inc/panels/tags.html' %} + {% include 'inc/panels/custom_fields.html' %} + {% include 'inc/panels/comments.html' %} + {% plugin_right_page object %} +
    +
    +
    +
    +
    +

    + {% trans "VLAN Translation Rules" %} + {% if perms.ipam.add_vlantranslationrule %} + + {% endif %} +

    + {% htmx_table 'ipam:vlantranslationrule_list' policy_id=object.pk %} +
    +
    +
    +
    +
    + {% plugin_full_width_page object %} +
    +
    +{% endblock %} diff --git a/netbox/templates/ipam/vlantranslationrule.html b/netbox/templates/ipam/vlantranslationrule.html new file mode 100644 index 000000000..7f3aad2ad --- /dev/null +++ b/netbox/templates/ipam/vlantranslationrule.html @@ -0,0 +1,45 @@ +{% extends 'generic/object.html' %} +{% load helpers %} +{% load plugins %} +{% load render_table from django_tables2 %} +{% load i18n %} + +{% block content %} +
    +
    +
    +

    {% trans "VLAN Translation Rule" %}

    + + + + + + + + + + + + + + + + + +
    {% trans "Policy" %}{{ object.policy|linkify }}
    {% trans "Local VID" %}{{ object.local_vid }}
    {% trans "Remote VID" %}{{ object.remote_vid }}
    {% trans "Description" %}{{ object.description }}
    +
    + {% plugin_left_page object %} +
    +
    + {% include 'inc/panels/tags.html' %} + {% include 'inc/panels/custom_fields.html' %} + {% include 'inc/panels/comments.html' %} + {% plugin_right_page object %} +
    +
    +
    +
    + {% plugin_full_width_page object %} +
    +
    +{% endblock %} diff --git a/netbox/templates/virtualization/cluster.html b/netbox/templates/virtualization/cluster.html index d79d8075c..4155dacb2 100644 --- a/netbox/templates/virtualization/cluster.html +++ b/netbox/templates/virtualization/cluster.html @@ -39,8 +39,12 @@ - {% trans "Site" %} - {{ object.site|linkify|placeholder }} + {% trans "Scope" %} + {% if object.scope %} + {{ object.scope|linkify }} ({% trans object.scope_type.name %}) + {% else %} + {{ ''|placeholder }} + {% endif %}
    diff --git a/netbox/templates/virtualization/virtualmachine/render_config.html b/netbox/templates/virtualization/virtualmachine/render_config.html index 5e7a0711b..fa6f1723b 100644 --- a/netbox/templates/virtualization/virtualmachine/render_config.html +++ b/netbox/templates/virtualization/virtualmachine/render_config.html @@ -5,7 +5,7 @@ {% block title %}{{ object }} - {% trans "Config" %}{% endblock %} {% block content %} -
    +

    {% trans "Config Template" %}

    @@ -48,19 +48,28 @@
    -
    -

    - {% trans "Rendered Config" %} - - {% trans "Download" %} - -

    - {% if config_template %} -
    {{ rendered_config }}
    + {% if config_template %} + {% if rendered_config %} +
    +

    + {% trans "Rendered Config" %} + + {% trans "Download" %} + +

    +
    {{ rendered_config }}
    +
    {% else %} -
    {% trans "No configuration template found" %}
    +
    +

    {% trans "Error rendering template" %}

    + {% trans error_message %} +
    {% endif %} -
    + {% else %} +
    + {% trans "No configuration template has been assigned for this virtual machine." %} +
    + {% endif %}
    {% endblock %} diff --git a/netbox/templates/virtualization/vminterface.html b/netbox/templates/virtualization/vminterface.html index 0d679680d..88c9379cf 100644 --- a/netbox/templates/virtualization/vminterface.html +++ b/netbox/templates/virtualization/vminterface.html @@ -14,69 +14,85 @@ {% block content %}
    -
    -

    {% trans "Interface" %}

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    {% trans "Virtual Machine" %}{{ object.virtual_machine|linkify }}
    {% trans "Name" %}{{ object.name }}
    {% trans "Enabled" %} - {% if object.enabled %} - - {% else %} - - {% endif %} -
    {% trans "Parent" %}{{ object.parent|linkify|placeholder }}
    {% trans "Bridge" %}{{ object.bridge|linkify|placeholder }}
    {% trans "VRF" %}{{ object.vrf|linkify|placeholder }}
    {% trans "Description" %}{{ object.description|placeholder }}
    {% trans "MTU" %}{{ object.mtu|placeholder }}
    {% trans "MAC Address" %}{{ object.mac_address|placeholder }}
    {% trans "802.1Q Mode" %}{{ object.get_mode_display|placeholder }}
    {% trans "Tunnel" %}{{ object.tunnel_termination.tunnel|linkify|placeholder }}
    -
    - {% include 'inc/panels/tags.html' %} - {% plugin_left_page object %} +
    +

    {% trans "Interface" %}

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    {% trans "Virtual Machine" %}{{ object.virtual_machine|linkify }}
    {% trans "Name" %}{{ object.name }}
    {% trans "Enabled" %} + {% if object.enabled %} + + {% else %} + + {% endif %} +
    {% trans "Parent" %}{{ object.parent|linkify|placeholder }}
    {% trans "Bridge" %}{{ object.bridge|linkify|placeholder }}
    {% trans "Description" %}{{ object.description|placeholder }}
    {% trans "MTU" %}{{ object.mtu|placeholder }}
    {% trans "802.1Q Mode" %}{{ object.get_mode_display|placeholder }}
    {% trans "Tunnel" %}{{ object.tunnel_termination.tunnel|linkify|placeholder }}
    -
    - {% include 'inc/panels/custom_fields.html' %} - {% include 'ipam/inc/panels/fhrp_groups.html' %} - {% plugin_right_page object %} + {% include 'inc/panels/tags.html' %} + {% plugin_left_page object %} +
    +
    + {% include 'inc/panels/custom_fields.html' %} +
    +

    {% trans "Addressing" %}

    + + + + + + + + + + + + + +
    {% trans "MAC Address" %} + {% if object.mac_address %} + {{ object.mac_address }} + {% trans "Primary" %} + {% else %} + {{ ''|placeholder }} + {% endif %} +
    {% trans "VRF" %}{{ object.vrf|linkify|placeholder }}
    {% trans "VLAN Translation" %}{{ object.vlan_translation_policy|linkify|placeholder }}
    + {% include 'ipam/inc/panels/fhrp_groups.html' %} + {% plugin_right_page object %} +
    @@ -95,11 +111,36 @@
    +
    +
    +
    +

    + {% trans "MAC Addresses" %} + {% if perms.ipam.add_macaddress %} + + {% endif %} +

    + {% htmx_table 'dcim:macaddress_list' vminterface_id=object.pk %} +
    +
    +
    {% include 'inc/panel_table.html' with table=vlan_table heading="VLANs" %}
    +{% if object.vlan_translation_policy %} +
    +
    + {% include 'inc/panel_table.html' with table=vlan_translation_table heading="VLAN Translation" %} +
    +
    +{% endif %}
    {% include 'inc/panel_table.html' with table=child_interfaces_table heading="Child Interfaces" %} diff --git a/netbox/templates/wireless/wirelesslan.html b/netbox/templates/wireless/wirelesslan.html index 493c36132..54473ea54 100644 --- a/netbox/templates/wireless/wirelesslan.html +++ b/netbox/templates/wireless/wirelesslan.html @@ -22,6 +22,14 @@ {% trans "Status" %} {% badge object.get_status_display bg_color=object.get_status_color %} + + {% trans "Scope" %} + {% if object.scope %} + {{ object.scope|linkify }} ({% trans object.scope_type.name %}) + {% else %} + {{ ''|placeholder }} + {% endif %} + {% trans "Description" %} {{ object.description|placeholder }} diff --git a/netbox/tenancy/api/nested_serializers.py b/netbox/tenancy/api/nested_serializers.py deleted file mode 100644 index 5adb78863..000000000 --- a/netbox/tenancy/api/nested_serializers.py +++ /dev/null @@ -1,58 +0,0 @@ -import warnings - -from netbox.api.serializers import WritableNestedSerializer -from serializers_.nested import NestedContactGroupSerializer, NestedTenantGroupSerializer -from tenancy.models import * - -__all__ = [ - 'NestedContactSerializer', - 'NestedContactAssignmentSerializer', - 'NestedContactGroupSerializer', - 'NestedContactRoleSerializer', - 'NestedTenantGroupSerializer', - 'NestedTenantSerializer', -] - -# TODO: Remove in v4.2 -warnings.warn( - "Dedicated nested serializers will be removed in NetBox v4.2. Use Serializer(nested=True) instead.", - DeprecationWarning -) - - -# -# Tenants -# - -class NestedTenantSerializer(WritableNestedSerializer): - - class Meta: - model = Tenant - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug'] - - -# -# Contacts -# - -class NestedContactRoleSerializer(WritableNestedSerializer): - - class Meta: - model = ContactRole - fields = ['id', 'url', 'display_url', 'display', 'name', 'slug'] - - -class NestedContactSerializer(WritableNestedSerializer): - - class Meta: - model = Contact - fields = ['id', 'url', 'display_url', 'display', 'name'] - - -class NestedContactAssignmentSerializer(WritableNestedSerializer): - contact = NestedContactSerializer() - role = NestedContactRoleSerializer - - class Meta: - model = ContactAssignment - fields = ['id', 'url', 'display', 'contact', 'role', 'priority'] diff --git a/netbox/tenancy/forms/forms.py b/netbox/tenancy/forms/forms.py index 114253e7a..0edb36348 100644 --- a/netbox/tenancy/forms/forms.py +++ b/netbox/tenancy/forms/forms.py @@ -25,6 +25,7 @@ class TenancyForm(forms.Form): label=_('Tenant'), queryset=Tenant.objects.all(), required=False, + quick_add=True, query_params={ 'group_id': '$tenant_group' } diff --git a/netbox/tenancy/graphql/types.py b/netbox/tenancy/graphql/types.py index 120b5c71b..7baa136b3 100644 --- a/netbox/tenancy/graphql/types.py +++ b/netbox/tenancy/graphql/types.py @@ -66,6 +66,7 @@ class TenantGroupType(OrganizationalObjectType): parent: Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')] | None tenants: List[TenantType] + children: List[Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')]] # @@ -99,6 +100,7 @@ class ContactGroupType(OrganizationalObjectType): parent: Annotated["ContactGroupType", strawberry.lazy('tenancy.graphql.types')] | None contacts: List[ContactType] + children: List[Annotated["ContactGroupType", strawberry.lazy('tenancy.graphql.types')]] @strawberry_django.type( diff --git a/netbox/tenancy/migrations/0001_squashed_0012.py b/netbox/tenancy/migrations/0001_squashed_0012.py index e8a028a92..8f3f74d9f 100644 --- a/netbox/tenancy/migrations/0001_squashed_0012.py +++ b/netbox/tenancy/migrations/0001_squashed_0012.py @@ -6,7 +6,6 @@ import taggit.managers class Migration(migrations.Migration): - initial = True dependencies = [ @@ -43,7 +42,16 @@ class Migration(migrations.Migration): ('rght', models.PositiveIntegerField(editable=False)), ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), ('level', models.PositiveIntegerField(editable=False)), - ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='tenancy.tenantgroup')), + ( + 'parent', + mptt.fields.TreeForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='children', + to='tenancy.tenantgroup', + ), + ), ], options={ 'ordering': ['name'], @@ -60,7 +68,16 @@ class Migration(migrations.Migration): ('slug', models.SlugField(max_length=100, unique=True)), ('description', models.CharField(blank=True, max_length=200)), ('comments', models.TextField(blank=True)), - ('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tenants', to='tenancy.tenantgroup')), + ( + 'group', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='tenants', + to='tenancy.tenantgroup', + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], options={ diff --git a/netbox/tenancy/migrations/0002_squashed_0011.py b/netbox/tenancy/migrations/0002_squashed_0011.py index 8accd1da9..cfdcb58dd 100644 --- a/netbox/tenancy/migrations/0002_squashed_0011.py +++ b/netbox/tenancy/migrations/0002_squashed_0011.py @@ -7,7 +7,6 @@ import utilities.json class Migration(migrations.Migration): - replaces = [ ('tenancy', '0002_tenant_ordering'), ('tenancy', '0003_contacts'), @@ -18,7 +17,7 @@ class Migration(migrations.Migration): ('tenancy', '0008_unique_constraints'), ('tenancy', '0009_standardize_description_comments'), ('tenancy', '0010_tenant_relax_uniqueness'), - ('tenancy', '0011_contactassignment_tags') + ('tenancy', '0011_contactassignment_tags'), ] dependencies = [ @@ -37,7 +36,10 @@ class Migration(migrations.Migration): fields=[ ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('name', models.CharField(max_length=100, unique=True)), ('slug', models.SlugField(max_length=100, unique=True)), @@ -53,7 +55,10 @@ class Migration(migrations.Migration): fields=[ ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('name', models.CharField(max_length=100)), ('slug', models.SlugField(max_length=100)), @@ -62,7 +67,16 @@ class Migration(migrations.Migration): ('rght', models.PositiveIntegerField(editable=False)), ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), ('level', models.PositiveIntegerField(editable=False)), - ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='tenancy.contactgroup')), + ( + 'parent', + mptt.fields.TreeForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='children', + to='tenancy.contactgroup', + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], options={ @@ -75,7 +89,10 @@ class Migration(migrations.Migration): fields=[ ('created', models.DateTimeField(auto_now_add=True, null=True)), ('last_updated', models.DateTimeField(auto_now=True, null=True)), - ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ( + 'custom_field_data', + models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('name', models.CharField(max_length=100)), ('title', models.CharField(blank=True, max_length=100)), @@ -83,7 +100,16 @@ class Migration(migrations.Migration): ('email', models.EmailField(blank=True, max_length=254)), ('address', models.CharField(blank=True, max_length=200)), ('comments', models.TextField(blank=True)), - ('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='contacts', to='tenancy.contactgroup')), + ( + 'group', + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name='contacts', + to='tenancy.contactgroup', + ), + ), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ('link', models.URLField(blank=True)), ], @@ -125,9 +151,24 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('object_id', models.PositiveBigIntegerField()), ('priority', models.CharField(blank=True, max_length=50)), - ('contact', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='assignments', to='tenancy.contact')), - ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), - ('role', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='assignments', to='tenancy.contactrole')), + ( + 'contact', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, related_name='assignments', to='tenancy.contact' + ), + ), + ( + 'content_type', + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype'), + ), + ( + 'role', + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name='assignments', + to='tenancy.contactrole', + ), + ), ], options={ 'ordering': ('priority', 'contact'), @@ -140,11 +181,16 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='contactassignment', - constraint=models.UniqueConstraint(fields=('content_type', 'object_id', 'contact', 'role'), name='tenancy_contactassignment_unique_object_contact_role'), + constraint=models.UniqueConstraint( + fields=('content_type', 'object_id', 'contact', 'role'), + name='tenancy_contactassignment_unique_object_contact_role', + ), ), migrations.AddConstraint( model_name='contactgroup', - constraint=models.UniqueConstraint(fields=('parent', 'name'), name='tenancy_contactgroup_unique_parent_name'), + constraint=models.UniqueConstraint( + fields=('parent', 'name'), name='tenancy_contactgroup_unique_parent_name' + ), ), migrations.AddField( model_name='contact', @@ -163,19 +209,31 @@ class Migration(migrations.Migration): ), migrations.AddConstraint( model_name='tenant', - constraint=models.UniqueConstraint(fields=('group', 'name'), name='tenancy_tenant_unique_group_name', violation_error_message='Tenant name must be unique per group.'), + constraint=models.UniqueConstraint( + fields=('group', 'name'), + name='tenancy_tenant_unique_group_name', + violation_error_message='Tenant name must be unique per group.', + ), ), migrations.AddConstraint( model_name='tenant', - constraint=models.UniqueConstraint(condition=models.Q(('group__isnull', True)), fields=('name',), name='tenancy_tenant_unique_name'), + constraint=models.UniqueConstraint( + condition=models.Q(('group__isnull', True)), fields=('name',), name='tenancy_tenant_unique_name' + ), ), migrations.AddConstraint( model_name='tenant', - constraint=models.UniqueConstraint(fields=('group', 'slug'), name='tenancy_tenant_unique_group_slug', violation_error_message='Tenant slug must be unique per group.'), + constraint=models.UniqueConstraint( + fields=('group', 'slug'), + name='tenancy_tenant_unique_group_slug', + violation_error_message='Tenant slug must be unique per group.', + ), ), migrations.AddConstraint( model_name='tenant', - constraint=models.UniqueConstraint(condition=models.Q(('group__isnull', True)), fields=('slug',), name='tenancy_tenant_unique_slug'), + constraint=models.UniqueConstraint( + condition=models.Q(('group__isnull', True)), fields=('slug',), name='tenancy_tenant_unique_slug' + ), ), migrations.AddField( model_name='contactassignment', diff --git a/netbox/tenancy/migrations/0012_contactassignment_custom_fields.py b/netbox/tenancy/migrations/0012_contactassignment_custom_fields.py index ee6726822..7f681fd91 100644 --- a/netbox/tenancy/migrations/0012_contactassignment_custom_fields.py +++ b/netbox/tenancy/migrations/0012_contactassignment_custom_fields.py @@ -5,7 +5,6 @@ import utilities.json class Migration(migrations.Migration): - dependencies = [ ('tenancy', '0011_contactassignment_tags'), ] diff --git a/netbox/tenancy/migrations/0013_gfk_indexes.py b/netbox/tenancy/migrations/0013_gfk_indexes.py index dd23cefbb..9d58c8932 100644 --- a/netbox/tenancy/migrations/0013_gfk_indexes.py +++ b/netbox/tenancy/migrations/0013_gfk_indexes.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('tenancy', '0012_contactassignment_custom_fields'), ] diff --git a/netbox/tenancy/migrations/0014_contactassignment_ordering.py b/netbox/tenancy/migrations/0014_contactassignment_ordering.py index 66f08aa2a..5e2c39311 100644 --- a/netbox/tenancy/migrations/0014_contactassignment_ordering.py +++ b/netbox/tenancy/migrations/0014_contactassignment_ordering.py @@ -4,7 +4,6 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ ('tenancy', '0013_gfk_indexes'), ] diff --git a/netbox/tenancy/migrations/0015_contactassignment_rename_content_type.py b/netbox/tenancy/migrations/0015_contactassignment_rename_content_type.py index 58b14e10f..f2c1ce190 100644 --- a/netbox/tenancy/migrations/0015_contactassignment_rename_content_type.py +++ b/netbox/tenancy/migrations/0015_contactassignment_rename_content_type.py @@ -2,7 +2,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('contenttypes', '0002_remove_content_type_name'), ('extras', '0111_rename_content_types'), @@ -25,16 +24,13 @@ class Migration(migrations.Migration): ), migrations.AddIndex( model_name='contactassignment', - index=models.Index( - fields=['object_type', 'object_id'], - name='tenancy_con_object__6f20f7_idx' - ), + index=models.Index(fields=['object_type', 'object_id'], name='tenancy_con_object__6f20f7_idx'), ), migrations.AddConstraint( model_name='contactassignment', constraint=models.UniqueConstraint( fields=('object_type', 'object_id', 'contact', 'role'), - name='tenancy_contactassignment_unique_object_contact_role' + name='tenancy_contactassignment_unique_object_contact_role', ), ), ] diff --git a/netbox/tenancy/migrations/0016_charfield_null_choices.py b/netbox/tenancy/migrations/0016_charfield_null_choices.py new file mode 100644 index 000000000..9f5016a13 --- /dev/null +++ b/netbox/tenancy/migrations/0016_charfield_null_choices.py @@ -0,0 +1,25 @@ +from django.db import migrations, models + + +def set_null_values(apps, schema_editor): + """ + Replace empty strings with null values. + """ + ContactAssignment = apps.get_model('tenancy', 'ContactAssignment') + + ContactAssignment.objects.filter(priority='').update(priority=None) + + +class Migration(migrations.Migration): + dependencies = [ + ('tenancy', '0015_contactassignment_rename_content_type'), + ] + + operations = [ + migrations.AlterField( + model_name='contactassignment', + name='priority', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.RunPython(code=set_null_values, reverse_code=migrations.RunPython.noop), + ] diff --git a/netbox/tenancy/migrations/0017_natural_ordering.py b/netbox/tenancy/migrations/0017_natural_ordering.py new file mode 100644 index 000000000..beb98d634 --- /dev/null +++ b/netbox/tenancy/migrations/0017_natural_ordering.py @@ -0,0 +1,26 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('tenancy', '0016_charfield_null_choices'), + ('dcim', '0197_natural_sort_collation'), + ] + + operations = [ + migrations.AlterField( + model_name='contact', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + migrations.AlterField( + model_name='tenant', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100), + ), + migrations.AlterField( + model_name='tenantgroup', + name='name', + field=models.CharField(db_collation='natural_sort', max_length=100, unique=True), + ), + ] diff --git a/netbox/tenancy/models/contacts.py b/netbox/tenancy/models/contacts.py index 46ca97261..3969c8317 100644 --- a/netbox/tenancy/models/contacts.py +++ b/netbox/tenancy/models/contacts.py @@ -56,7 +56,8 @@ class Contact(PrimaryModel): ) name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) title = models.CharField( verbose_name=_('title'), @@ -125,7 +126,8 @@ class ContactAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, Chan verbose_name=_('priority'), max_length=50, choices=ContactPriorityChoices, - blank=True + blank=True, + null=True ) clone_fields = ('object_type', 'object_id', 'role', 'priority') diff --git a/netbox/tenancy/models/tenants.py b/netbox/tenancy/models/tenants.py index 7a2d9c2f8..55f0c5933 100644 --- a/netbox/tenancy/models/tenants.py +++ b/netbox/tenancy/models/tenants.py @@ -18,7 +18,8 @@ class TenantGroup(NestedGroupModel): name = models.CharField( verbose_name=_('name'), max_length=100, - unique=True + unique=True, + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), @@ -39,7 +40,8 @@ class Tenant(ContactsMixin, PrimaryModel): """ name = models.CharField( verbose_name=_('name'), - max_length=100 + max_length=100, + db_collation="natural_sort" ) slug = models.SlugField( verbose_name=_('slug'), diff --git a/netbox/tenancy/tables/columns.py b/netbox/tenancy/tables/columns.py index ec73cac4a..005bcf737 100644 --- a/netbox/tenancy/tables/columns.py +++ b/netbox/tenancy/tables/columns.py @@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _ import django_tables2 as tables from netbox.tables import columns +from .template_code import * __all__ = ( 'ContactsColumnMixin', @@ -15,15 +16,7 @@ class TenantColumn(tables.TemplateColumn): """ Include the tenant description. """ - template_code = """ - {% if record.tenant %} - {{ record.tenant }} - {% elif record.vrf.tenant %} - {{ record.vrf.tenant }}* - {% else %} - — - {% endif %} - """ + template_code = TENANT_COLUMN def __init__(self, *args, **kwargs): super().__init__(template_code=self.template_code, *args, **kwargs) @@ -36,15 +29,7 @@ class TenantGroupColumn(tables.TemplateColumn): """ Include the tenant group description. """ - template_code = """ - {% if record.tenant and record.tenant.group %} - {{ record.tenant.group }} - {% elif record.vrf.tenant and record.vrf.tenant.group %} - {{ record.vrf.tenant.group }}* - {% else %} - — - {% endif %} - """ + template_code = TENANT_GROUP_COLUMN def __init__(self, accessor=tables.A('tenant__group'), *args, **kwargs): if 'verbose_name' not in kwargs: diff --git a/netbox/tenancy/tables/template_code.py b/netbox/tenancy/tables/template_code.py new file mode 100644 index 000000000..1d15a8708 --- /dev/null +++ b/netbox/tenancy/tables/template_code.py @@ -0,0 +1,19 @@ +TENANT_COLUMN = """ +{% if record.tenant %} + {{ record.tenant }} +{% elif record.vrf.tenant %} + {{ record.vrf.tenant }}* +{% else %} + — +{% endif %} +""" + +TENANT_GROUP_COLUMN = """ +{% if record.tenant and record.tenant.group %} + {{ record.tenant.group }} +{% elif record.vrf.tenant and record.vrf.tenant.group %} + {{ record.vrf.tenant.group }}* +{% else %} + — +{% endif %} +""" diff --git a/netbox/tenancy/tests/test_api.py b/netbox/tenancy/tests/test_api.py index 5a6fe0453..c32ad3826 100644 --- a/netbox/tenancy/tests/test_api.py +++ b/netbox/tenancy/tests/test_api.py @@ -239,9 +239,24 @@ class ContactAssignmentTest(APIViewTestCases.APIViewTestCase): ContactRole.objects.bulk_create(contact_roles) contact_assignments = ( - ContactAssignment(object=sites[0], contact=contacts[0], role=contact_roles[0], priority=ContactPriorityChoices.PRIORITY_PRIMARY), - ContactAssignment(object=sites[0], contact=contacts[1], role=contact_roles[1], priority=ContactPriorityChoices.PRIORITY_SECONDARY), - ContactAssignment(object=sites[0], contact=contacts[2], role=contact_roles[2], priority=ContactPriorityChoices.PRIORITY_TERTIARY), + ContactAssignment( + object=sites[0], + contact=contacts[0], + role=contact_roles[0], + priority=ContactPriorityChoices.PRIORITY_PRIMARY, + ), + ContactAssignment( + object=sites[0], + contact=contacts[1], + role=contact_roles[1], + priority=ContactPriorityChoices.PRIORITY_SECONDARY, + ), + ContactAssignment( + object=sites[0], + contact=contacts[2], + role=contact_roles[2], + priority=ContactPriorityChoices.PRIORITY_TERTIARY, + ), ) ContactAssignment.objects.bulk_create(contact_assignments) diff --git a/netbox/tenancy/urls.py b/netbox/tenancy/urls.py index ad9908c62..cd0caabdc 100644 --- a/netbox/tenancy/urls.py +++ b/netbox/tenancy/urls.py @@ -1,57 +1,27 @@ from django.urls import include, path from utilities.urls import get_model_urls -from . import views +from . import views # noqa F401 app_name = 'tenancy' urlpatterns = [ - # Tenant groups - path('tenant-groups/', views.TenantGroupListView.as_view(), name='tenantgroup_list'), - path('tenant-groups/add/', views.TenantGroupEditView.as_view(), name='tenantgroup_add'), - path('tenant-groups/import/', views.TenantGroupBulkImportView.as_view(), name='tenantgroup_import'), - path('tenant-groups/edit/', views.TenantGroupBulkEditView.as_view(), name='tenantgroup_bulk_edit'), - path('tenant-groups/delete/', views.TenantGroupBulkDeleteView.as_view(), name='tenantgroup_bulk_delete'), + path('tenant-groups/', include(get_model_urls('tenancy', 'tenantgroup', detail=False))), path('tenant-groups//', include(get_model_urls('tenancy', 'tenantgroup'))), - # Tenants - path('tenants/', views.TenantListView.as_view(), name='tenant_list'), - path('tenants/add/', views.TenantEditView.as_view(), name='tenant_add'), - path('tenants/import/', views.TenantBulkImportView.as_view(), name='tenant_import'), - path('tenants/edit/', views.TenantBulkEditView.as_view(), name='tenant_bulk_edit'), - path('tenants/delete/', views.TenantBulkDeleteView.as_view(), name='tenant_bulk_delete'), + path('tenants/', include(get_model_urls('tenancy', 'tenant', detail=False))), path('tenants//', include(get_model_urls('tenancy', 'tenant'))), - # Contact groups - path('contact-groups/', views.ContactGroupListView.as_view(), name='contactgroup_list'), - path('contact-groups/add/', views.ContactGroupEditView.as_view(), name='contactgroup_add'), - path('contact-groups/import/', views.ContactGroupBulkImportView.as_view(), name='contactgroup_import'), - path('contact-groups/edit/', views.ContactGroupBulkEditView.as_view(), name='contactgroup_bulk_edit'), - path('contact-groups/delete/', views.ContactGroupBulkDeleteView.as_view(), name='contactgroup_bulk_delete'), + path('contact-groups/', include(get_model_urls('tenancy', 'contactgroup', detail=False))), path('contact-groups//', include(get_model_urls('tenancy', 'contactgroup'))), - # Contact roles - path('contact-roles/', views.ContactRoleListView.as_view(), name='contactrole_list'), - path('contact-roles/add/', views.ContactRoleEditView.as_view(), name='contactrole_add'), - path('contact-roles/import/', views.ContactRoleBulkImportView.as_view(), name='contactrole_import'), - path('contact-roles/edit/', views.ContactRoleBulkEditView.as_view(), name='contactrole_bulk_edit'), - path('contact-roles/delete/', views.ContactRoleBulkDeleteView.as_view(), name='contactrole_bulk_delete'), + path('contact-roles/', include(get_model_urls('tenancy', 'contactrole', detail=False))), path('contact-roles//', include(get_model_urls('tenancy', 'contactrole'))), - # Contacts - path('contacts/', views.ContactListView.as_view(), name='contact_list'), - path('contacts/add/', views.ContactEditView.as_view(), name='contact_add'), - path('contacts/import/', views.ContactBulkImportView.as_view(), name='contact_import'), - path('contacts/edit/', views.ContactBulkEditView.as_view(), name='contact_bulk_edit'), - path('contacts/delete/', views.ContactBulkDeleteView.as_view(), name='contact_bulk_delete'), + path('contacts/', include(get_model_urls('tenancy', 'contact', detail=False))), path('contacts//', include(get_model_urls('tenancy', 'contact'))), - # Contact assignments - path('contact-assignments/', views.ContactAssignmentListView.as_view(), name='contactassignment_list'), - path('contact-assignments/add/', views.ContactAssignmentEditView.as_view(), name='contactassignment_add'), - path('contact-assignments/import/', views.ContactAssignmentBulkImportView.as_view(), name='contactassignment_import'), - path('contact-assignments/edit/', views.ContactAssignmentBulkEditView.as_view(), name='contactassignment_bulk_edit'), - path('contact-assignments/delete/', views.ContactAssignmentBulkDeleteView.as_view(), name='contactassignment_bulk_delete'), + path('contact-assignments/', include(get_model_urls('tenancy', 'contactassignment', detail=False))), path('contact-assignments//', include(get_model_urls('tenancy', 'contactassignment'))), ] diff --git a/netbox/tenancy/views.py b/netbox/tenancy/views.py index 12bf4baab..0988d2e65 100644 --- a/netbox/tenancy/views.py +++ b/netbox/tenancy/views.py @@ -1,6 +1,6 @@ from django.contrib.contenttypes.models import ContentType from django.shortcuts import get_object_or_404 -from django.utils.translation import gettext as _ +from django.utils.translation import gettext_lazy as _ from netbox.views import generic from utilities.query import count_related @@ -37,11 +37,12 @@ class ObjectContactsView(generic.ObjectChildrenView): return table + # # Tenant groups # - +@register_model_view(TenantGroup, 'list', path='', detail=False) class TenantGroupListView(generic.ObjectListView): queryset = TenantGroup.objects.add_related_count( TenantGroup.objects.all(), @@ -67,6 +68,7 @@ class TenantGroupView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(TenantGroup, 'add', detail=False) @register_model_view(TenantGroup, 'edit') class TenantGroupEditView(generic.ObjectEditView): queryset = TenantGroup.objects.all() @@ -78,11 +80,13 @@ class TenantGroupDeleteView(generic.ObjectDeleteView): queryset = TenantGroup.objects.all() +@register_model_view(TenantGroup, 'bulk_import', detail=False) class TenantGroupBulkImportView(generic.BulkImportView): queryset = TenantGroup.objects.all() model_form = forms.TenantGroupImportForm +@register_model_view(TenantGroup, 'bulk_edit', path='edit', detail=False) class TenantGroupBulkEditView(generic.BulkEditView): queryset = TenantGroup.objects.add_related_count( TenantGroup.objects.all(), @@ -96,6 +100,7 @@ class TenantGroupBulkEditView(generic.BulkEditView): form = forms.TenantGroupBulkEditForm +@register_model_view(TenantGroup, 'bulk_delete', path='delete', detail=False) class TenantGroupBulkDeleteView(generic.BulkDeleteView): queryset = TenantGroup.objects.add_related_count( TenantGroup.objects.all(), @@ -112,6 +117,7 @@ class TenantGroupBulkDeleteView(generic.BulkDeleteView): # Tenants # +@register_model_view(Tenant, 'list', path='', detail=False) class TenantListView(generic.ObjectListView): queryset = Tenant.objects.all() filterset = filtersets.TenantFilterSet @@ -129,6 +135,7 @@ class TenantView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(Tenant, 'add', detail=False) @register_model_view(Tenant, 'edit') class TenantEditView(generic.ObjectEditView): queryset = Tenant.objects.all() @@ -140,11 +147,13 @@ class TenantDeleteView(generic.ObjectDeleteView): queryset = Tenant.objects.all() +@register_model_view(Tenant, 'bulk_import', detail=False) class TenantBulkImportView(generic.BulkImportView): queryset = Tenant.objects.all() model_form = forms.TenantImportForm +@register_model_view(Tenant, 'bulk_edit', path='edit', detail=False) class TenantBulkEditView(generic.BulkEditView): queryset = Tenant.objects.all() filterset = filtersets.TenantFilterSet @@ -152,6 +161,7 @@ class TenantBulkEditView(generic.BulkEditView): form = forms.TenantBulkEditForm +@register_model_view(Tenant, 'bulk_delete', path='delete', detail=False) class TenantBulkDeleteView(generic.BulkDeleteView): queryset = Tenant.objects.all() filterset = filtersets.TenantFilterSet @@ -167,6 +177,7 @@ class TenantContactsView(ObjectContactsView): # Contact groups # +@register_model_view(ContactGroup, 'list', path='', detail=False) class ContactGroupListView(generic.ObjectListView): queryset = ContactGroup.objects.add_related_count( ContactGroup.objects.all(), @@ -192,6 +203,7 @@ class ContactGroupView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(ContactGroup, 'add', detail=False) @register_model_view(ContactGroup, 'edit') class ContactGroupEditView(generic.ObjectEditView): queryset = ContactGroup.objects.all() @@ -203,11 +215,13 @@ class ContactGroupDeleteView(generic.ObjectDeleteView): queryset = ContactGroup.objects.all() +@register_model_view(ContactGroup, 'bulk_import', detail=False) class ContactGroupBulkImportView(generic.BulkImportView): queryset = ContactGroup.objects.all() model_form = forms.ContactGroupImportForm +@register_model_view(ContactGroup, 'bulk_edit', path='edit', detail=False) class ContactGroupBulkEditView(generic.BulkEditView): queryset = ContactGroup.objects.add_related_count( ContactGroup.objects.all(), @@ -221,6 +235,7 @@ class ContactGroupBulkEditView(generic.BulkEditView): form = forms.ContactGroupBulkEditForm +@register_model_view(ContactGroup, 'bulk_delete', path='delete', detail=False) class ContactGroupBulkDeleteView(generic.BulkDeleteView): queryset = ContactGroup.objects.add_related_count( ContactGroup.objects.all(), @@ -237,6 +252,7 @@ class ContactGroupBulkDeleteView(generic.BulkDeleteView): # Contact roles # +@register_model_view(ContactRole, 'list', path='', detail=False) class ContactRoleListView(generic.ObjectListView): queryset = ContactRole.objects.all() filterset = filtersets.ContactRoleFilterSet @@ -254,6 +270,7 @@ class ContactRoleView(GetRelatedModelsMixin, generic.ObjectView): } +@register_model_view(ContactRole, 'add', detail=False) @register_model_view(ContactRole, 'edit') class ContactRoleEditView(generic.ObjectEditView): queryset = ContactRole.objects.all() @@ -265,11 +282,13 @@ class ContactRoleDeleteView(generic.ObjectDeleteView): queryset = ContactRole.objects.all() +@register_model_view(ContactRole, 'bulk_import', detail=False) class ContactRoleBulkImportView(generic.BulkImportView): queryset = ContactRole.objects.all() model_form = forms.ContactRoleImportForm +@register_model_view(ContactRole, 'bulk_edit', path='edit', detail=False) class ContactRoleBulkEditView(generic.BulkEditView): queryset = ContactRole.objects.all() filterset = filtersets.ContactRoleFilterSet @@ -277,6 +296,7 @@ class ContactRoleBulkEditView(generic.BulkEditView): form = forms.ContactRoleBulkEditForm +@register_model_view(ContactRole, 'bulk_delete', path='delete', detail=False) class ContactRoleBulkDeleteView(generic.BulkDeleteView): queryset = ContactRole.objects.all() filterset = filtersets.ContactRoleFilterSet @@ -287,6 +307,7 @@ class ContactRoleBulkDeleteView(generic.BulkDeleteView): # Contacts # +@register_model_view(Contact, 'list', path='', detail=False) class ContactListView(generic.ObjectListView): queryset = Contact.objects.annotate( assignment_count=count_related(ContactAssignment, 'contact') @@ -301,6 +322,7 @@ class ContactView(generic.ObjectView): queryset = Contact.objects.all() +@register_model_view(Contact, 'add', detail=False) @register_model_view(Contact, 'edit') class ContactEditView(generic.ObjectEditView): queryset = Contact.objects.all() @@ -312,11 +334,13 @@ class ContactDeleteView(generic.ObjectDeleteView): queryset = Contact.objects.all() +@register_model_view(Contact, 'bulk_import', detail=False) class ContactBulkImportView(generic.BulkImportView): queryset = Contact.objects.all() model_form = forms.ContactImportForm +@register_model_view(Contact, 'bulk_edit', path='edit', detail=False) class ContactBulkEditView(generic.BulkEditView): queryset = Contact.objects.annotate( assignment_count=count_related(ContactAssignment, 'contact') @@ -326,6 +350,7 @@ class ContactBulkEditView(generic.BulkEditView): form = forms.ContactBulkEditForm +@register_model_view(Contact, 'bulk_delete', path='delete', detail=False) class ContactBulkDeleteView(generic.BulkDeleteView): queryset = Contact.objects.annotate( assignment_count=count_related(ContactAssignment, 'contact') @@ -333,24 +358,26 @@ class ContactBulkDeleteView(generic.BulkDeleteView): filterset = filtersets.ContactFilterSet table = tables.ContactTable + # # Contact assignments # - +@register_model_view(ContactAssignment, 'list', path='', detail=False) class ContactAssignmentListView(generic.ObjectListView): queryset = ContactAssignment.objects.all() filterset = filtersets.ContactAssignmentFilterSet filterset_form = forms.ContactAssignmentFilterForm table = tables.ContactAssignmentTable actions = { - 'import': {'add'}, 'export': {'view'}, + 'bulk_import': {'add'}, 'bulk_edit': {'change'}, 'bulk_delete': {'delete'}, } +@register_model_view(ContactAssignment, 'add', detail=False) @register_model_view(ContactAssignment, 'edit') class ContactAssignmentEditView(generic.ObjectEditView): queryset = ContactAssignment.objects.all() @@ -370,6 +397,13 @@ class ContactAssignmentEditView(generic.ObjectEditView): } +@register_model_view(ContactAssignment, 'bulk_import', detail=False) +class ContactAssignmentBulkImportView(generic.BulkImportView): + queryset = ContactAssignment.objects.all() + model_form = forms.ContactAssignmentImportForm + + +@register_model_view(ContactAssignment, 'bulk_edit', path='edit', detail=False) class ContactAssignmentBulkEditView(generic.BulkEditView): queryset = ContactAssignment.objects.all() filterset = filtersets.ContactAssignmentFilterSet @@ -377,11 +411,7 @@ class ContactAssignmentBulkEditView(generic.BulkEditView): form = forms.ContactAssignmentBulkEditForm -class ContactAssignmentBulkImportView(generic.BulkImportView): - queryset = ContactAssignment.objects.all() - model_form = forms.ContactAssignmentImportForm - - +@register_model_view(ContactAssignment, 'bulk_delete', path='delete', detail=False) class ContactAssignmentBulkDeleteView(generic.BulkDeleteView): queryset = ContactAssignment.objects.all() filterset = filtersets.ContactAssignmentFilterSet diff --git a/netbox/translations/cs/LC_MESSAGES/django.mo b/netbox/translations/cs/LC_MESSAGES/django.mo index df95c667c..d5a4db33b 100644 Binary files a/netbox/translations/cs/LC_MESSAGES/django.mo and b/netbox/translations/cs/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/cs/LC_MESSAGES/django.po b/netbox/translations/cs/LC_MESSAGES/django.po index b583f13f7..dad9129fe 100644 --- a/netbox/translations/cs/LC_MESSAGES/django.po +++ b/netbox/translations/cs/LC_MESSAGES/django.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" "Last-Translator: Pavel Valach, 2024\n" "Language-Team: Czech (https://app.transifex.com/netbox-community/teams/178115/cs/)\n" @@ -88,8 +88,8 @@ msgstr "Vaše heslo bylo úspěšně změněno." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -102,7 +102,7 @@ msgstr "Zajišťování" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -113,8 +113,8 @@ msgid "Active" msgstr "Aktivní" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Vypnuto" @@ -127,7 +127,7 @@ msgstr "Zrušení přidělování" msgid "Decommissioned" msgstr "Vyřazeno z provozu" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Primární" @@ -200,12 +200,12 @@ msgstr "Skupina stránek (slug)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -214,18 +214,17 @@ msgstr "Skupina stránek (slug)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -333,10 +332,10 @@ msgstr "Zakončení A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -388,7 +387,7 @@ msgstr "Skupina okruhů (slug)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -403,33 +402,33 @@ msgstr "ASN" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -438,7 +437,7 @@ msgstr "ASN" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -453,7 +452,7 @@ msgstr "ASN" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -473,7 +472,7 @@ msgstr "ASN" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -566,10 +565,10 @@ msgid "Service ID" msgstr "ID služby" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -590,16 +589,16 @@ msgstr "Barva" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -654,14 +653,14 @@ msgstr "Účet poskytovatele" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -670,13 +669,13 @@ msgstr "Účet poskytovatele" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -687,7 +686,7 @@ msgstr "Účet poskytovatele" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -723,30 +722,30 @@ msgstr "Stav" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -816,11 +815,11 @@ msgstr "Parametry služby" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -852,11 +851,11 @@ msgstr "Rychlost portu (Kbps)" msgid "Upstream speed (Kbps)" msgstr "Odchozí rychlost (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Označit jako zapojené" @@ -903,10 +902,10 @@ msgstr "Typ okruhu" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -916,13 +915,13 @@ msgstr "Provozní stav" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -947,12 +946,12 @@ msgstr "Síť poskytovatele" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -969,9 +968,9 @@ msgstr "Síť poskytovatele" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1000,8 +999,8 @@ msgid "Contacts" msgstr "Kontakty" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1009,13 +1008,12 @@ msgstr "Kontakty" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1028,16 +1026,16 @@ msgid "Region" msgstr "Region" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1049,7 +1047,7 @@ msgstr "Skupina stránek" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1088,9 +1086,9 @@ msgstr "Účet" msgid "Term Side" msgstr "Strana termínu" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1100,11 +1098,11 @@ msgstr "Přiřazení" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1176,20 +1174,20 @@ msgid "Unique circuit ID" msgstr "Jedinečné ID obvodu" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "stav" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "nainstalován" @@ -1310,11 +1308,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1325,7 +1323,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1413,7 +1411,7 @@ msgstr "sítě poskytovatelů" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1424,7 +1422,7 @@ msgstr "sítě poskytovatelů" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1455,7 +1453,7 @@ msgstr "sítě poskytovatelů" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1619,7 +1617,7 @@ msgstr "Dokončeno" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Neuspěl" @@ -1686,7 +1684,7 @@ msgid "Cancelled" msgstr "Zrušeno" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Místní" @@ -1773,8 +1771,8 @@ msgid "User name" msgstr "Uživatelské jméno" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1878,7 +1876,7 @@ msgid "Completed before" msgstr "Dokončeno dříve" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1944,9 +1942,9 @@ msgstr "" msgid "Rack Elevations" msgstr "Výšky stojanů" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Napájení" @@ -2046,7 +2044,7 @@ msgid "Change logging is not supported for this object type ({type})." msgstr "Protokolování změn není u tohoto typu objektu podporováno ({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2106,7 +2104,7 @@ msgstr "typ" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2225,58 +2223,58 @@ msgstr "spravovaný soubor" msgid "managed files" msgstr "spravované soubory" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "naplánováno" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "interval" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Interval opakování (v minutách)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "začal" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "dokončena" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "data" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "chyba" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "ID úlohy" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "práce" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "pracovní místa" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "K tomuto typu objektu nelze přiřadit úlohy ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "Neplatný stav pro ukončení úlohy. Možnosti jsou: {choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "enqueue () nelze volat s hodnotami pro schedule_at a instant." @@ -2359,7 +2357,7 @@ msgstr "Maximální verze NetBoxu" msgid "No plugin data found" msgstr "Nebyla nalezena žádná data pluginu" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Autor" @@ -2367,7 +2365,7 @@ msgstr "Autor" msgid "Installed" msgstr "Nainstalováno" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Certifikováno" @@ -2493,11 +2491,11 @@ msgstr "Práce {id} byl zastaven." msgid "Failed to stop job {id}" msgstr "Nepodařilo se zastavit úlohu {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "Katalog pluginů nelze načíst" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Plugin {name} nenalezeno" @@ -2517,7 +2515,7 @@ msgid "Staging" msgstr "Inscenace" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Vyřazení z provozu" @@ -2581,7 +2579,7 @@ msgstr "Zastaralé" msgid "Millimeters" msgstr "Milimetry" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "palce" @@ -2595,15 +2593,15 @@ msgstr "Zepředu dozadu" msgid "Rear to front" msgstr "Zezadu dopředu" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2683,7 +2681,7 @@ msgid "Top to bottom" msgstr "Nahoru dolů" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "pasivní" @@ -2712,8 +2710,8 @@ msgid "Proprietary" msgstr "Proprietární" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Ostatní" @@ -2726,24 +2724,24 @@ msgstr "ITA/Mezinárodní" msgid "Physical" msgstr "Fyzické" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Virtuální" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Bezdrátové" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Virtuální rozhraní" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2752,27 +2750,27 @@ msgstr "Virtuální rozhraní" msgid "Bridge" msgstr "Most" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Agregační skupina (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (pevný)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (modulární)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (propojovací deska)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Buněčný" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2780,130 +2778,130 @@ msgstr "Buněčný" msgid "Serial" msgstr "Sériový" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Koaxiální" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "Stohování" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Poloviční" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Plný" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Auto" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Přístup" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Označeno" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Označeno (Vše)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "Norma IEEE" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "Pasivní 24V (2 páry)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "Pasivní 24V (4 páry)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "Pasivní 48V (2 páry)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "Pasivní 48V (4 páry)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "měď" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Optická vlákna" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Vlákno" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Připojeno" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Kilometry" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Metry" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Centimetry" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Míle" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Stopy" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Kilogramy" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Gramy" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "libry" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Unce" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Redundantní" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Jednofázový" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Třífázový" @@ -3149,7 +3147,7 @@ msgstr "Skupina clusteru (ID)" msgid "Device model (slug)" msgstr "Model zařízení (slug)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "Je plná hloubka" @@ -3271,21 +3269,21 @@ msgstr "Přiřazená VLAN" msgid "Assigned VID" msgstr "Přiřazené VID" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3352,7 +3350,7 @@ msgid "LAG interface (ID)" msgstr "Rozhraní LAG (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Kontext virtuálního zařízení" @@ -3426,7 +3424,7 @@ msgstr "Značky" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3443,38 +3441,38 @@ msgstr "" "Podporovány jsou alfanumerické rozsahy. (Musí odpovídat počtu vytvořených " "jmen.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Kontaktní jméno" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Kontaktní telefon" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "Kontaktní e-mail" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Časové pásmo" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3484,58 +3482,59 @@ msgstr "Časové pásmo" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Výrobce" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Tvarový faktor" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Šířka" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Výška (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Sestupné jednotky" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Vnější šířka" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Vnější hloubka" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Vnější jednotka" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Hloubka montáže" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3546,10 +3545,10 @@ msgstr "Hloubka montáže" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3558,61 +3557,61 @@ msgstr "Hloubka montáže" msgid "Weight" msgstr "Hmotnost" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Max. hmotnost" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Jednotka hmotnosti" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Typ stojanu" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Vnější rozměry" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Rozměry" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Číslování" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3640,45 +3639,50 @@ msgstr "Číslování" msgid "Role" msgstr "Role" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Typ stojanu" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Sériové číslo" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Inventární číslo" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Proudění vzduchu" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3688,64 +3692,64 @@ msgstr "Proudění vzduchu" msgid "Rack" msgstr "Stojan" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Hardware" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Výchozí platforma" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Číslo dílu" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "Výška U pozic" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Vyloučit z využití" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Typ zařízení" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Typ modulu" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Šasi" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "Role virtuálního počítače" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3756,19 +3760,19 @@ msgstr "Role virtuálního počítače" msgid "Config template" msgstr "Konfigurační šablona" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Typ zařízení" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Role zařízení" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3782,14 +3786,36 @@ msgstr "Role zařízení" msgid "Platform" msgstr "Nástupiště" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Klastr" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3799,9 +3825,9 @@ msgstr "Nástupiště" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3810,10 +3836,10 @@ msgstr "Nástupiště" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3840,7 +3866,7 @@ msgstr "Nástupiště" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3850,23 +3876,28 @@ msgstr "Nástupiště" msgid "Device" msgstr "Zařízení" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Konfigurace" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Virtualizace" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Typ modulu" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3884,109 +3915,109 @@ msgstr "Typ modulu" msgid "Label" msgstr "Štítek" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Délka" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Jednotka délky" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Doména" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "Napájecí panel" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Zdroj" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Fáze" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Napětí" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Proud" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Maximální využití" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Maximální příkon" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Maximální příkon (W)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Přidělený příkon" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Přidělený příkon (W)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Napájecí port" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Napájecí větev" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Pouze správa" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "Režim PoE" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "Typ PoE" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Bezdrátová role" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4000,17 +4031,17 @@ msgstr "Bezdrátová role" msgid "Module" msgstr "Modul" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "Agregační skupina" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Kontexty virtuálních zařízení" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4019,7 +4050,7 @@ msgstr "Kontexty virtuálních zařízení" msgid "Speed" msgstr "Rychlost" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4033,76 +4064,88 @@ msgstr "Rychlost" msgid "Mode" msgstr "Režim" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "Skupina VLAN" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "Neznačené VLAN" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "Označené VLAN" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Skupina bezdrátových sítí" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "Bezdrátové LAN sítě" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Adresování" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Operace" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Související rozhraní" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "Přepínání 802.1Q" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "Pro přiřazení sítí VLAN musí být zadán režim rozhraní" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "Přístupovému rozhraní nelze přiřadit označené sítě VLAN." @@ -4128,9 +4171,9 @@ msgstr "Přiřazená skupina" msgid "available options" msgstr "dostupné možnosti" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4152,15 +4195,15 @@ msgstr "Výrobce tohoto typu stojanu" msgid "The lowest-numbered position in the rack" msgstr "Nejnižší očíslovaná pozice v regálu" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Šířka kolejnice k kolejnici (v palcích)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Jednotka pro vnější rozměry" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Jednotka pro regálové závaží" @@ -4172,158 +4215,148 @@ msgstr "Jméno přiděleného nájemce" msgid "Name of assigned role" msgstr "Název přiřazené role" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Směr proudění vzduchu" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Nadřazený web" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Umístění stojanu (pokud existuje)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Jednotky" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Seznam jednotlivých čísel jednotek oddělených čárkami" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "Výrobce, který vyrábí tento typ zařízení" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "Výchozí platforma pro zařízení tohoto typu (volitelné)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Hmotnost zařízení" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Jednotka pro hmotnost zařízení" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Hmotnost modulu" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Jednotka pro hmotnost modulu" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Omezte přiřazení platformy tomuto výrobci" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Přidělená role" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Výrobce typu zařízení" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Model typu zařízení" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Přiřazená platforma" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Virtuální podvozek" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Klastr" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Virtualizační klastr" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Přiřazené umístění (pokud existuje)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Přiřazený stojan (pokud existuje)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Tvář" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Namontovaná plocha stojanu" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Rodičovské zařízení (pro podřízená zařízení)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Místo pro zařízení" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" "Místo pro zařízení, ve kterém je toto zařízení nainstalováno (pro podřízená " "zařízení)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "Zařízení, ve kterém je tento modul nainstalován" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Modulová přihrádka" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "Místo modulu, ve kterém je tento modul nainstalován" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "Typ modulu" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Replikace komponent" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4331,85 +4364,85 @@ msgstr "" "Automaticky naplnit komponenty přidružené k tomuto typu modulu (ve výchozím " "nastavení povoleno)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Přijměte komponenty" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Přijměte již existující komponenty" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Typ portu" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Rychlost portu v bps" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Typ výstupu" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Místní napájecí port, který napájí tuto zásuvku" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Elektrická fáze (pro třífázové obvody)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Nadřazené rozhraní" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Přemostěné rozhraní" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Zpoždění" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Nadřazené rozhraní LAG" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "Vdcs" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "Názvy VDC oddělené čárkami, uzavřené dvojitými uvozovkami. Příklad:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Fyzické médium" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Dvoupodlažní" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "Režim Poe" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Typ Poe" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "Provozní režim IEEE 802.1Q (pro rozhraní L2)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4417,172 +4450,172 @@ msgstr "Provozní režim IEEE 802.1Q (pro rozhraní L2)" msgid "Assigned VRF" msgstr "Přiřazené VRF" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Rf role" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Bezdrátová role (AP/stanice)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} není přiřazen k zařízení {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Zadní port" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Odpovídající zadní port" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Klasifikace fyzického média" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Nainstalované zařízení" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "Dětské zařízení instalované v této pozici" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Dětské zařízení nebylo nalezeno." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Nadřazená položka inventáře" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Typ komponenty" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Typ komponenty" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Název komponenty" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Název komponenty" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Komponenta nebyla nalezena: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Zařízení na straně A" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Název zařízení" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Typ strany A" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Typ ukončení" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Jméno strany A" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Název ukončení" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Zařízení na straně B" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Typ strany B" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Název strany B" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Stav připojení" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "Strana {side_upper}: {device} {termination_object} je již připojeno" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "Zakončení strany {side_upper} nebylo nalezeno: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Hlavní" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Hlavní zařízení" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Název nadřazeného webu" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "Nadřazený napájecí panel" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Primární nebo redundantní" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Typ napájení (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Jednofázové nebo třífázové" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "Primární IPv4" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "IPv4 adresa s maskou, např. 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "Primární IPv6" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "IPv6 adresa s délkou předpony, např. 2001:db8: :1/64" @@ -4669,10 +4702,6 @@ msgstr "Rodičovská skupina" msgid "Facility" msgstr "Zařízení" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Typ stojanu" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Funkce" @@ -4709,7 +4738,7 @@ msgid "Has virtual device contexts" msgstr "Má kontexty virtuálních zařízení" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Skupina klastru" @@ -4748,7 +4777,7 @@ msgstr "Druh" msgid "Mgmt only" msgstr "Pouze správa" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4851,36 +4880,46 @@ msgstr "Automaticky naplnit komponenty přidružené k tomuto typu modulu" msgid "Characteristics" msgstr "Charakteristika" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Šablona portu konzoly" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Šablona portu konzolového serveru" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Šablona předního portu" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Šablona rozhraní" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Šablona elektrické zásuvky" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Šablona napájecího portu" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Šablona zadního portu" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4904,7 +4943,7 @@ msgstr "Šablona zadního portu" msgid "Interface" msgstr "Rozhraní" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4912,14 +4951,14 @@ msgstr "Rozhraní" msgid "Console Port" msgstr "Port konzoly" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Port konzolového serveru" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4930,7 +4969,7 @@ msgstr "Port konzolového serveru" msgid "Front Port" msgstr "Přední port" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4943,40 +4982,40 @@ msgstr "Přední port" msgid "Rear Port" msgstr "Zadní port" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Napájecí port" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Napájecí zásuvka" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Přiřazení komponent" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "InventoryItem lze přiřadit pouze k jedné komponentě." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "Rozhraní LAG" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Filtrujte sítě VLAN dostupné pro přiřazení podle skupiny." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Podřazené zařízení" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -4984,35 +5023,35 @@ msgstr "" "Podřízená zařízení musí být nejprve vytvořena a přiřazena k staveništi a " "stojanu nadřazeného zařízení." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Port konzoly" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Port konzolového serveru" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Přední port" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "Napájecí zásuvka" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Položka inventáře" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Role položky inventáře" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5030,12 +5069,12 @@ msgstr "" "{pattern_count}." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Zadní porty" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" "Vyberte jedno přiřazení zadního portu pro každý vytvořený přední port." @@ -5049,16 +5088,7 @@ msgstr "" "Počet šablon předních portů, které mají být vytvořeny ({frontport_count}), " "musí odpovídat zvolenému počtu pozic zadních portů ({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"Řetězec {module} bude nahrazen polohou přiřazeného modulu, " -"pokud existuje." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5067,24 +5097,24 @@ msgstr "" "Počet předních portů, které mají být vytvořeny ({frontport_count}), musí " "odpovídat zvolenému počtu pozic zadních portů ({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Členové" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Počáteční pozice" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." msgstr "Pozice prvního člena. Zvýší se o jeden pro každého dalšího člena." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "Pro prvního člena virtuálnáho šasi musí být specifikována pozice." @@ -6002,12 +6032,12 @@ msgstr "poloha (U)" msgid "rack face" msgstr "plocha stojanu" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "primární IPv4" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "primární IPv6" @@ -6177,22 +6207,22 @@ msgid "" msgstr "" "Modul musí být instalován v modulu patřící přiřazenému zařízení ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "doména" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "virtuální podvozek" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "" "Vybraný master ({master}) není přiřazena k tomuto virtuálnímu podvozku." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6201,34 +6231,34 @@ msgstr "" "Nelze odstranit virtuální šasi {self}. Existují členská rozhraní, která " "tvoří rozhraní LAG napříč podvozky." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "identifikátor" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Numerický identifikátor jedinečný pro nadřazené zařízení" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "komentáře" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "kontext virtuálního zařízení" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "kontexty virtuálních zařízení" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} není IPV{family} adresa." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "Primární IP adresa musí patřit k rozhraní na přiřazeném zařízení." @@ -6415,7 +6445,7 @@ msgstr "Lokálně přiřazený identifikátor" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Funkční role" @@ -6624,7 +6654,7 @@ msgstr "Dosažitelný" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Přístroje" @@ -6653,8 +6683,8 @@ msgid "Site Group" msgstr "Skupina stránek" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6705,20 +6735,20 @@ msgid "Power outlets" msgstr "Elektrické zásuvky" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Rozhraní" @@ -6744,8 +6774,8 @@ msgid "Module Bay" msgstr "Modulová přihrádka" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6774,7 +6804,7 @@ msgstr "Maximální tažení (W)" msgid "Allocated draw (W)" msgstr "Přidělené losování (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6870,87 +6900,87 @@ msgstr "Výška U" msgid "Instances" msgstr "Instance" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Porty konzoly" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Porty konzolového serveru" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Napájecí porty" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Napájecí zásuvky" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Přední porty" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Zadní porty" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Pozice pro zařízení" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Modulové pozice" @@ -6999,7 +7029,7 @@ msgstr "Prostor" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7009,28 +7039,28 @@ msgstr "Stránky" msgid "Test case must set peer_termination_type" msgstr "Testovací případ musí nastavit peer_termination_type" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Odpojeno {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Rezervace" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Zařízení bez racku" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Kontext konfigurace" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Konfigurace rendrování" @@ -7041,35 +7071,35 @@ msgstr "Při vykreslování šablony došlo k chybě: {error}" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Virtuální stroje" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Nainstalované zařízení {device} v zátoce {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Odstraněné zařízení {device} od zátoky {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Děti" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Přidán člen {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "Nelze odebrat hlavní zařízení {device} z virtuálního podvozku." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "Odstraněno {device} z virtuálního šasi {chassis}" @@ -7252,7 +7282,6 @@ msgstr "Aktualizovat" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -8071,19 +8100,19 @@ msgstr "Naplánujte spuštění skriptu na nastavený čas" msgid "Interval at which this script is re-run (in minutes)" msgstr "Interval, ve kterém je tento skript znovu spuštěn (v minutách)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "Změny v databázi byly automaticky vráceny." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Skript byl přerušen s chybou: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Došlo k výjimce: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "Změny databáze byly vráceny kvůli chybě." @@ -9102,7 +9131,7 @@ msgstr "Odstraněný widget: " msgid "Error deleting widget: " msgstr "Chyba při mazání widgetu: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "Nelze spustit skript: Proces RQ Worker není spuštěn." @@ -9248,7 +9277,7 @@ msgid "Prefixes which contain this prefix or IP" msgstr "Předpony, které obsahují tuto předponu nebo IP" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Délka masky" @@ -9262,7 +9291,7 @@ msgid "VLAN number (1-4094)" msgstr "Číslo VLAN (1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9374,16 +9403,16 @@ msgstr "Je vyžadována maska CIDR (např. /24)." msgid "Address pattern" msgstr "Vzor adresy" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Vynutit jedinečný prostor" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "Je soukromý" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9397,20 +9426,20 @@ msgstr "Je soukromý" msgid "RIR" msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Datum přidání" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "Skupina VLAN" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9423,32 +9452,32 @@ msgstr "Skupina VLAN" msgid "VLAN" msgstr "WLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Délka předpony" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "Je bazén" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Zacházejte jako plně využívané" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "Přiřazení VLAN" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "Název DNS" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9456,12 +9485,12 @@ msgstr "Název DNS" msgid "Protocol" msgstr "protokolu" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "ID skupiny" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9473,12 +9502,12 @@ msgstr "ID skupiny" msgid "Authentication type" msgstr "Typ autentizace" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Ověřovací klíč" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9490,26 +9519,26 @@ msgstr "Ověřovací klíč" msgid "Authentication" msgstr "Autentizace" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Typ rozsahu" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "Rozsahy ID VLAN" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Rozsah" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "Rozsahy ID VLAN" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Stránky a skupina" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9536,8 +9565,8 @@ msgstr "Skupina VLAN (pokud existuje)" msgid "Parent device of assigned interface (if any)" msgstr "Nadřazené zařízení přiřazeného rozhraní (pokud existuje)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9563,41 +9592,61 @@ msgstr "Je primární" msgid "Make this the primary IP for the assigned device" msgstr "Nastavte to jako primární IP pro přiřazené zařízení" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "Není určeno žádné zařízení ani virtuální počítač; nelze nastavit jako " "primární IP" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "Není určeno žádné rozhraní; nelze nastavit jako primární IP" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Typ autentizace" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Typ rozsahu (aplikace a model)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Přiřazená skupina VLAN" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "Protokol IP" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Vyžadováno, pokud není přiřazeno k virtuálnímu počítači" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Požadováno, pokud není přiřazeno k zařízení" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} není přiřazen k tomuto zařízení/virtuálnímu počítači." @@ -9679,7 +9728,7 @@ msgstr "Přiřazeno k rozhraní" msgid "DNS Name" msgstr "Název DNS" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9690,13 +9739,13 @@ msgstr "VLAN" msgid "Contains VLAN ID" msgstr "Obsahuje VLAN ID" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "ID VLAN" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9707,7 +9756,7 @@ msgstr "ID VLAN" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9736,8 +9785,8 @@ msgstr "Přiřazení webu/VLAN" msgid "IP Range" msgstr "Rozsah IP" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "Skupina FHRP" @@ -9746,46 +9795,56 @@ msgstr "Skupina FHRP" msgid "Make this the primary IP for the device/VM" msgstr "Nastavte z něj primární IP pro zařízení/virtuální počítač" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "NAT IP (uvnitř)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "IP adresu lze přiřadit pouze jednomu objektu." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Nelze znovu přiřadit adresu IP, pokud je určena jako primární IP pro " -"nadřazený objekt" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "Jako primární IP adresy lze označit pouze adresy IP přiřazené k rozhraní." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Virtuální IP adresa" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "Přiřazení již existuje" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "ID VLAN" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "Dětské sítě VLAN" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9793,33 +9852,33 @@ msgstr "" "Seznam jednoho nebo více čísel portů oddělený čárkami. Rozsah lze zadat " "pomocí pomlčky." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Šablona služby" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Přístav (y)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Servisní služby" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Šablona služby" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "Z šablony" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Zvyk" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10098,6 +10157,14 @@ msgstr "{ip} je vysílací adresa, která nemusí být přiřazena k rozhraní." msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Duplicitní adresa IP nalezena v {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Nelze znovu přiřadit adresu IP, pokud je určena jako primární IP pro " +"nadřazený objekt" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Stav SLAAC lze přiřadit pouze adresám IPv6" @@ -10149,40 +10216,48 @@ msgstr "Nelze nastavit scope_type bez scope_id." msgid "Cannot set scope_id without scope_type." msgstr "Nelze nastavit scope_id bez scope_type." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Rozsahy se nemohou překrývat." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"Maximální dětský VID musí být větší nebo roven minimálnímu dětskému VID " -"({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "Konkrétní místo, ke kterému je tato VLAN přiřazena (pokud existuje)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "Skupina VLAN (volitelné)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "Numerické ID VLAN (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Provozní stav této VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "Primární funkce této VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10191,7 +10266,7 @@ msgstr "" "VLAN je přiřazena ke skupině {group} (oblast působnosti: {scope}); nelze " "také přiřadit k webu {site}." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "VID musí být v rozmezí {ranges} pro sítě VLAN ve skupině {group}" @@ -10952,17 +11027,12 @@ msgstr "Zásady protokolu IPsec" msgid "IPSec Profiles" msgstr "Profily IPsec" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Virtualizace" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Virtuální disky" @@ -11124,7 +11194,7 @@ msgstr "Systém" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11368,19 +11438,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Řádek {i}: Objekt s ID {id} neexistuje" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "Ne {object_type} Byly vybrány." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Přejmenováno {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Vymazáno {count} {object_type}" @@ -11412,7 +11482,7 @@ msgstr "Synchronizováno {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} musí implementovat get_children ()" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11756,9 +11826,7 @@ msgid "Circuit Type" msgstr "Typ obvodu" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11769,7 +11837,6 @@ msgstr "Přidat" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12057,35 +12124,35 @@ msgstr "dní" msgid "Indefinite" msgstr "Neurčitý" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Není nainstalován" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Přehled" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Nainstalovat" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Podrobnosti o pluginu" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Souhrn" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Licence" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Historie verzí" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Pokyny k místní instalaci" @@ -12428,8 +12495,8 @@ msgstr "Přidat službu" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12502,20 +12569,24 @@ msgstr "Konfigurace" msgid "Context Data" msgstr "Kontextová data" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Rendrovaná konfigurace" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Ke stažení" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Nebyla nalezena žádná šablona konfigurace" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12537,7 +12608,6 @@ msgid "Local Config Context Data" msgstr "Kontextová data místní konfigurace" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12584,12 +12654,12 @@ msgid "VM Role" msgstr "Role virtuálního počítače" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Název modelu" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Číslo dílu" @@ -12728,7 +12798,7 @@ msgstr "MAC adresa" msgid "Wireless Link" msgstr "Bezdrátové spojení" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Peer" @@ -13350,7 +13420,7 @@ msgstr "Nemáte oprávnění spouštět skripty" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Spustit skript" @@ -13363,27 +13433,32 @@ msgstr "Chyba při načítání skriptu" msgid "Script no longer exists in the source file." msgstr "Skript již ve zdrojovém souboru neexistuje." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Poslední běh" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "Skript již není přítomen ve zdrojovém souboru" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Nikdy" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Spustit znovu" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Nenalezeny žádné skripty" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13703,7 +13778,7 @@ msgstr "Všechna oznámení" msgid "Select" msgstr "Vybrat" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Obnovit" @@ -14187,6 +14262,10 @@ msgstr "Zdroje" msgid "Add Virtual Disk" msgstr "Přidat virtuální disk" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15250,13 +15329,13 @@ msgid "Memory (MB)" msgstr "Paměť (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Disk (GB)" +msgid "Disk (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Velikost (GB)" +msgid "Size (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15437,68 +15516,80 @@ msgstr "virtuální disk" msgid "virtual disks" msgstr "virtuální disky" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Přidal {count} zařízení do clusteru {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Odstraněno {count} zařízení z clusteru {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPsec - Přeprava" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec - Tunel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP v IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GREE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Rozbočovač" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "Mluvil" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Agresivní" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Hlavní" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Předsdílené klíče" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Certifikáty" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "Podpisy RSA" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "Podpisy DSA" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15507,23 +15598,27 @@ msgstr "Podpisy DSA" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Skupina {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Ethernetová soukromá síť LAN" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Ethernetová virtuální privátní síť LAN" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Ethernetový soukromý strom" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Virtuální privátní strom Ethernetu" diff --git a/netbox/translations/da/LC_MESSAGES/django.mo b/netbox/translations/da/LC_MESSAGES/django.mo index 2390fc9f1..ea7f83ac3 100644 Binary files a/netbox/translations/da/LC_MESSAGES/django.mo and b/netbox/translations/da/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/da/LC_MESSAGES/django.po b/netbox/translations/da/LC_MESSAGES/django.po index 14e00591d..bf9f12abe 100644 --- a/netbox/translations/da/LC_MESSAGES/django.po +++ b/netbox/translations/da/LC_MESSAGES/django.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" "Last-Translator: Jeremy Stretch, 2024\n" "Language-Team: Danish (https://app.transifex.com/netbox-community/teams/178115/da/)\n" @@ -89,8 +89,8 @@ msgstr "Din adgangskode er blevet ændret." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -103,7 +103,7 @@ msgstr "Opretter" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -114,8 +114,8 @@ msgid "Active" msgstr "Aktiv" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Offline" @@ -128,7 +128,7 @@ msgstr "Nedlægger" msgid "Decommissioned" msgstr "Nedlagt" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Primær" @@ -201,12 +201,12 @@ msgstr "Områdegruppe (slug)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -215,18 +215,17 @@ msgstr "Områdegruppe (slug)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -334,10 +333,10 @@ msgstr "Afslutning A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -389,7 +388,7 @@ msgstr "Kredsløbsgruppe (slug)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -404,33 +403,33 @@ msgstr "ASN'er" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -439,7 +438,7 @@ msgstr "ASN'er" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -454,7 +453,7 @@ msgstr "ASN'er" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -474,7 +473,7 @@ msgstr "ASN'er" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -567,10 +566,10 @@ msgid "Service ID" msgstr "Tjeneste-id" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -591,16 +590,16 @@ msgstr "Farve" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -655,14 +654,14 @@ msgstr "Leverandørkonto" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -671,13 +670,13 @@ msgstr "Leverandørkonto" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -688,7 +687,7 @@ msgstr "Leverandørkonto" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -724,30 +723,30 @@ msgstr "Status" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -817,11 +816,11 @@ msgstr "Serviceparametre" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -853,11 +852,11 @@ msgstr "Porthastighed (Kbps)" msgid "Upstream speed (Kbps)" msgstr "Opstrøms hastighed (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Marker tilsluttet" @@ -904,10 +903,10 @@ msgstr "Kredsløbstype" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -917,13 +916,13 @@ msgstr "Driftsstatus" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -948,12 +947,12 @@ msgstr "Leverandørnetværk" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -970,9 +969,9 @@ msgstr "Leverandørnetværk" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1001,8 +1000,8 @@ msgid "Contacts" msgstr "Kontakter" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1010,13 +1009,12 @@ msgstr "Kontakter" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1029,16 +1027,16 @@ msgid "Region" msgstr "Regionen" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1050,7 +1048,7 @@ msgstr "Områdegruppe" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1089,9 +1087,9 @@ msgstr "Konto" msgid "Term Side" msgstr "Termside" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1101,11 +1099,11 @@ msgstr "Opgave" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1177,20 +1175,20 @@ msgid "Unique circuit ID" msgstr "Unikt kredsløbs-ID" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "status" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "installeret" @@ -1312,11 +1310,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1327,7 +1325,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1415,7 +1413,7 @@ msgstr "leverandørnetværk" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1426,7 +1424,7 @@ msgstr "leverandørnetværk" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1457,7 +1455,7 @@ msgstr "leverandørnetværk" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1621,7 +1619,7 @@ msgstr "Afsluttet" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Mislykkedes" @@ -1688,7 +1686,7 @@ msgid "Cancelled" msgstr "Annulleret" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Lokalt" @@ -1775,8 +1773,8 @@ msgid "User name" msgstr "Brugernavn" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1880,7 +1878,7 @@ msgid "Completed before" msgstr "Færdiggjort før" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1945,9 +1943,9 @@ msgstr "Skal uploade en fil eller vælge en datafil, der skal synkroniseres" msgid "Rack Elevations" msgstr "Rackhøjder" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Strøm" @@ -2047,7 +2045,7 @@ msgid "Change logging is not supported for this object type ({type})." msgstr "Ændringslogføring understøttes ikke for denne objekttype ({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2107,7 +2105,7 @@ msgstr "type" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2227,58 +2225,58 @@ msgstr "administreret fil" msgid "managed files" msgstr "administrerede filer" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "planlagt" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "interval" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Gentagelsesinterval (i minutter)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "startede" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "afsluttet" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "data" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "fejl" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "job-ID" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "job" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "stillinger" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "Job kan ikke tildeles denne objekttype ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "Ugyldig status for opsigelse af job. Valgmulighederne er: {choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" @@ -2362,7 +2360,7 @@ msgstr "Maksimal NetBox-version" msgid "No plugin data found" msgstr "Ingen plugin-data fundet" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Forfatter" @@ -2370,7 +2368,7 @@ msgstr "Forfatter" msgid "Installed" msgstr "Installeret" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Certificeret" @@ -2496,11 +2494,11 @@ msgstr "Job {id} er blevet stoppet." msgid "Failed to stop job {id}" msgstr "Det lykkedes ikke at stoppe jobbet {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "Plugin-kataloget kunne ikke indlæses" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Plugin {name} ikke fundet" @@ -2520,7 +2518,7 @@ msgid "Staging" msgstr "Iscenesættelse" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Nedlæggelse" @@ -2584,7 +2582,7 @@ msgstr "Forældet" msgid "Millimeters" msgstr "Millimeter" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "Tommer" @@ -2598,15 +2596,15 @@ msgstr "Foran til bag" msgid "Rear to front" msgstr "Bagsiden til forsiden" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2686,7 +2684,7 @@ msgid "Top to bottom" msgstr "Top til bund" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Passiv" @@ -2715,8 +2713,8 @@ msgid "Proprietary" msgstr "Proprietær" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Andet" @@ -2729,24 +2727,24 @@ msgstr "ITA/International" msgid "Physical" msgstr "Fysisk" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Virtuel" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Trådløs" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Virtuelle grænseflader" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2755,27 +2753,27 @@ msgstr "Virtuelle grænseflader" msgid "Bridge" msgstr "Bro" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Link Aggregation Group (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (fast)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (modulopbygget)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (bagplan)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Cellulær" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2783,130 +2781,130 @@ msgstr "Cellulær" msgid "Serial" msgstr "Seriel" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Koaksial" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "Stabling" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Halvdelen" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Fuld" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Auto" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Adgang" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Markeret" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Tagget (Alle)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "IEEE-standard" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "Passiv 24V (2-par)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "Passiv 24V (4-par)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "Passiv 48V (2-par)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "Passiv 48V (4-par)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Kobber" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Fiberoptisk" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Fiber" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Tilsluttet" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Kilometer" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Meter" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Centimeter" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Mil" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Fod" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Kilogram" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Gram" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "pund" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Ounce" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Redundant" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Enkeltfase" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Trefaset" @@ -3152,7 +3150,7 @@ msgstr "Klyngegruppe (ID)" msgid "Device model (slug)" msgstr "Enhedsmodel (slug)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "Er fuld dybde" @@ -3274,21 +3272,21 @@ msgstr "Tildelt VLAN" msgid "Assigned VID" msgstr "Tildelt VID" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3355,7 +3353,7 @@ msgid "LAG interface (ID)" msgstr "LAG-grænseflade (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Virtuel enhedskontekst" @@ -3429,7 +3427,7 @@ msgstr "Mærker" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3446,38 +3444,38 @@ msgstr "" "Alfanumeriske intervaller understøttes. (Skal svare til antallet af navne, " "der oprettes.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Kontaktens navn" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Kontakt telefon" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "Kontakt E-mail" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Tidszone" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3487,58 +3485,59 @@ msgstr "Tidszone" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Producent" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Formfaktor" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Bredde" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Højde (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Faldende enheder" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Udvendig bredde" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Ydre dybde" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Ydre enhed" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Monteringsdybde" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3549,10 +3548,10 @@ msgstr "Monteringsdybde" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3561,61 +3560,61 @@ msgstr "Monteringsdybde" msgid "Weight" msgstr "Vægt" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Maks. Vægt" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Vægtenhed" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Racktype" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Udvendige mål" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Dimensioner" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Nummerering" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3643,45 +3642,50 @@ msgstr "Nummerering" msgid "Role" msgstr "Rolle" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Racktype" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Serienummer" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Aktivemærke" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Luftstrøm" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3691,64 +3695,64 @@ msgstr "Luftstrøm" msgid "Rack" msgstr "Rack" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Hardware" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Standardplatform" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Varenummer" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "U højde" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Ekskluder fra udnyttelse" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Enhedstype" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Modultype" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Chassis" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "VM-rolle" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3759,19 +3763,19 @@ msgstr "VM-rolle" msgid "Config template" msgstr "Konfigurationsskabelon" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Enhedstype" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Enhedsrolle" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3785,14 +3789,36 @@ msgstr "Enhedsrolle" msgid "Platform" msgstr "Platformen" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Klynge" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3802,9 +3828,9 @@ msgstr "Platformen" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3813,10 +3839,10 @@ msgstr "Platformen" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3843,7 +3869,7 @@ msgstr "Platformen" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3853,23 +3879,28 @@ msgstr "Platformen" msgid "Device" msgstr "Enhed" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Konfiguration" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Virtualisering" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Modultype" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3887,109 +3918,109 @@ msgstr "Modultype" msgid "Label" msgstr "Mærke" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Længde" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Længdeenhed" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "domæne" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "Strømpanel" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Forsyning" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Fase" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Spænding" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Strømstyrke" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Maksimal udnyttelse" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Maksimal trækning" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Maksimal forbrug (watt)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Tildelt lodtrækning" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Allokeret forbrug (watt)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Strømstik" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Foderben" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Kun ledelse" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "PoE-tilstand" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "PoE-type" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Trådløs rolle" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4003,17 +4034,17 @@ msgstr "Trådløs rolle" msgid "Module" msgstr "Modul" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "FORSINKELSE" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Virtuelle enhedskontekster" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4022,7 +4053,7 @@ msgstr "Virtuelle enhedskontekster" msgid "Speed" msgstr "Hastighed" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4036,76 +4067,88 @@ msgstr "Hastighed" msgid "Mode" msgstr "Tilstand" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "VLAN-gruppe" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "Umærket VLAN" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "Mærkede VLAN'er" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Trådløs LAN-gruppe" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "Trådløse LAN" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Adressering" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Betjening" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Relaterede grænseflader" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "802.1Q-skift" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "Interfacetilstand skal specificeres for at tildele VLAN'er" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "En adgangsgrænseflade kan ikke have tildelt taggede VLAN'er." @@ -4131,9 +4174,9 @@ msgstr "Tildelt gruppe" msgid "available options" msgstr "tilgængelige muligheder" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4155,15 +4198,15 @@ msgstr "Producenten af denne racktype" msgid "The lowest-numbered position in the rack" msgstr "Den laveste nummererede position i racket" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Skinne-til-skinne-bredde (i tommer)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Enhed til udvendige mål" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Enhed til rackvægte" @@ -4175,156 +4218,146 @@ msgstr "Navn på tildelt lejer" msgid "Name of assigned role" msgstr "Navn på tildelt rolle" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Luftstrømsretning" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Overordnet område" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Rackets placering (hvis nogen)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Enheder" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Kommasepareret liste over individuelle enhedsnumre" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "Producenten, der fremstiller denne enhedstype" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "Standardplatformen for enheder af denne type (valgfrit)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Enhedsvægt" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Enhed til enhedens vægt" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Modulvægt" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Enhed til modulvægt" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Begræns platformstildelinger til denne producent" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Tildelt rolle" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Producent af enhedstype" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Enhedstypemodel" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Tildelt platform" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Virtuelt kabinet" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Klynge" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Virtualiseringsklynge" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Tildelt placering (hvis nogen)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Tildelt rack (hvis et sådant findes)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Ansigt" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Monteret rackflade" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Overordnet enhed (til underordnede enheder)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Enhedsplads" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "Enhedsplads, hvor denne enhed er installeret (til børneenheder)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "Enheden, hvor dette modul er installeret" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Modulplads" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "Modulrummet, hvor dette modul er installeret" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "Typen af modul" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Replikerer komponenter" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4332,87 +4365,87 @@ msgstr "" "Udfyld automatisk komponenter, der er knyttet til denne modultype (aktiveret" " som standard)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Vedtage komponenter" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Vedtage allerede eksisterende komponenter" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Porttype" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Porthastighed i bps" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Udtagstype" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Lokalt strømstik, der forsyner dette strømudtag" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Elektrisk fase (til trefasede kredsløb)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Forældregrænseflade" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Brobaseret grænseflade" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Forsinkelse" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Overordnet LAG-grænseflade" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "Vdcs" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" "VDC-navne adskilt af kommaer, indkapslet med dobbelte anførselstegn. " "Eksempel:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Fysisk medium" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Duplex" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "Poe-tilstand" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Poe-type" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "IEEE 802.1Q driftstilstand (til L2-grænseflader)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4420,173 +4453,173 @@ msgstr "IEEE 802.1Q driftstilstand (til L2-grænseflader)" msgid "Assigned VRF" msgstr "Tildelt VRF" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Rf-rolle" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Trådløs rolle (AP/station)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} er ikke tildelt enheden {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Bageste port" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Tilsvarende bagport" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Klassificering af fysisk medium" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Installeret enhed" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "Børneenhed installeret i denne bugt" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Børneenhed blev ikke fundet." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Overordnet beholdningspost" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Komponenttype" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Komponenttype" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Komponentnavn" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Komponentnavn" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Komponent ikke fundet: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Side A-enhed" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Enhedsnavn" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Side A type" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Afslutningstype" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Side A navn" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Opsigelsesnavn" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Side B-enhed" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Side B type" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Side B navn" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Forbindelsesstatus" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "" "Side {side_upper}: {device} {termination_object} er allerede tilsluttet" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} sideafslutning ikke fundet: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Mester" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Hovedenhed" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Navn på overordnet område" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "Hoved strømpanel" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Primær eller redundant" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Forsyningstype (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Enkelt- eller trefaset" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "Primær IPv4" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "IP-adresse med maske, fx 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "Primær IPv6" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "IPv6-adresse med præfix-længde, fx 2001:db8::1/64" @@ -4673,10 +4706,6 @@ msgstr "Forældregruppe" msgid "Facility" msgstr "Faciliteterne" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Racktype" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Funktion" @@ -4713,7 +4742,7 @@ msgid "Has virtual device contexts" msgstr "Har virtuelle enhedskontekster" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Klyngegruppe" @@ -4752,7 +4781,7 @@ msgstr "Venlig" msgid "Mgmt only" msgstr "Kun Mgmt" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4856,36 +4885,46 @@ msgstr "Udfyld automatisk komponenter, der er knyttet til denne modultype" msgid "Characteristics" msgstr "Karakteristika" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Konsolportskabelon" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Konsolserverportskabelon" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Frontportskabelon" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Grænsefladeskabelon" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Skabelon til strømudtag" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Strømstikskabelon" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Bagport skabelon" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4909,7 +4948,7 @@ msgstr "Bagport skabelon" msgid "Interface" msgstr "Grænseflade" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4917,14 +4956,14 @@ msgstr "Grænseflade" msgid "Console Port" msgstr "Konsolport" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Konsolserverport" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4935,7 +4974,7 @@ msgstr "Konsolserverport" msgid "Front Port" msgstr "Frontport" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4948,40 +4987,40 @@ msgstr "Frontport" msgid "Rear Port" msgstr "Bageste port" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Strømstik" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Strømudtag" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Komponenttildeling" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "En InventoryItem kan kun tildeles til en enkelt komponent." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "LAG-grænseflade" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Filtrer VLAN'er, der er tilgængelige til tildeling efter gruppe." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Børneenhed" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -4989,35 +5028,35 @@ msgstr "" "Underordnede enheder skal først oprettes og tildeles til den overordnede " "enheds område og rack." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Konsolport" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Konsolserverport" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Frontport" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "Strømudtag" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Lagergenstand" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Lagervarrolle" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5035,12 +5074,12 @@ msgstr "" "{pattern_count} forventes." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Bageste porte" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "Vælg en bagporttildeling for hver frontport, der oprettes." @@ -5053,16 +5092,7 @@ msgstr "" "Antallet af frontportskabeloner, der skal oprettes ({frontport_count}) skal " "matche det valgte antal bageste portpositioner ({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"Strengen {module} vil blive erstattet med placeringen af det " -"tildelte modul, hvis det er tilfældet." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5071,25 +5101,25 @@ msgstr "" "Antallet af frontporte, der skal oprettes ({frontport_count}) skal matche " "det valgte antal bageste portpositioner ({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Medlemmer" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Udgangsposition" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." msgstr "" "Placering af den første medlemsenhed. Stiges med en for hvert ekstra medlem." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "En stilling skal specificeres for det første VC-medlem." @@ -6011,12 +6041,12 @@ msgstr "position (U)" msgid "rack face" msgstr "rackflade" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "Primær IPv4" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "Primær IPv6" @@ -6189,21 +6219,21 @@ msgstr "" "Modulet skal installeres i en modulplads, der tilhører den tildelte enhed " "({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "domæne" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "virtuelt chassis" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "Den valgte master ({master}) er ikke tildelt dette virtuelle chassis." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6212,34 +6242,34 @@ msgstr "" "Kan ikke slette virtuelt chassis {self}. Der er medlemsgrænseflader, der " "danner LAG-grænseflader på tværs af chassiserne." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "identificere" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Numerisk identifikator, der er unik for den overordnede enhed" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "kommenterer" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "virtuel enhedskontekst" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "virtuelle enhedskontekster" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} er ikke en IPV{family} adresse." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "Primær IP-adresse skal tilhøre en grænseflade på den tildelte enhed." @@ -6426,7 +6456,7 @@ msgstr "Lokalt tildelt identifikator" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Funktionel rolle" @@ -6638,7 +6668,7 @@ msgstr "Tilgængelig" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Enheder" @@ -6667,8 +6697,8 @@ msgid "Site Group" msgstr "Områdegruppe" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6719,20 +6749,20 @@ msgid "Power outlets" msgstr "Strømudtag" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Grænseflader" @@ -6758,8 +6788,8 @@ msgid "Module Bay" msgstr "Modulbugt" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6788,7 +6818,7 @@ msgstr "Maksimal trækkraft (W)" msgid "Allocated draw (W)" msgstr "Tildelt lodtrækning (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6884,87 +6914,87 @@ msgstr "U Højde" msgid "Instances" msgstr "forekomster" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Konsolporte" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Konsolserverporte" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Strømstik" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Strømudtag" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Frontporte" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Bageste porte" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Enhedsbugter" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Modulbugter" @@ -7013,7 +7043,7 @@ msgstr "Rummet" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7023,28 +7053,28 @@ msgstr "Områder" msgid "Test case must set peer_termination_type" msgstr "Testcase skal indstille peer_termination_type" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Afbrudt {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Reservationer" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Enheder uden rack" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Konfigurationskontekst" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Gengivelseskonfiguration" @@ -7055,35 +7085,35 @@ msgstr "Der opstod en fejl under gengivelse af skabelonen: {error}" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Virtuelle maskiner" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Installeret enhed {device} i bugten {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Fjernet enhed {device} fra bugten {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Børn" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Tilføjet medlem {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "Kan ikke fjerne masterenheden {device} fra det virtuelle chassis." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "Fjernet {device} fra virtuelt chassis {chassis}" @@ -7266,7 +7296,6 @@ msgstr "Opdatere" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -8087,19 +8116,19 @@ msgstr "Planlæg udførelse af script til et bestemt tidspunkt" msgid "Interval at which this script is re-run (in minutes)" msgstr "Interval, hvor scriptet køres igen (i minutter)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "Databaseændringer er blevet tilbageført automatisk." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Script afbrudt med fejl: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Der opstod en undtagelse: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "Databaseændringer er blevet tilbageført på grund af fejl." @@ -9122,7 +9151,7 @@ msgstr "Slettet widget: " msgid "Error deleting widget: " msgstr "Fejl ved sletning af widget: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "Kan ikke køre script: RQ-arbejderprocessen kører ikke." @@ -9268,7 +9297,7 @@ msgid "Prefixes which contain this prefix or IP" msgstr "Præfikser, der indeholder dette præfiks eller IP" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Maskelængde" @@ -9282,7 +9311,7 @@ msgid "VLAN number (1-4094)" msgstr "VLAN-nummer (1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9394,16 +9423,16 @@ msgstr "CIDR-maske (f.eks. /24) er påkrævet." msgid "Address pattern" msgstr "Adressemønster" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Håndhæv unikt rum" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "Er privat" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9417,20 +9446,20 @@ msgstr "Er privat" msgid "RIR" msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Dato tilføjet" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "VLAN-gruppen" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9443,32 +9472,32 @@ msgstr "VLAN-gruppen" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Præfikslængde" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "Er en pool" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Behandl som fuldt udnyttet" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "VLAN-tildeling" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "DNS-navn" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9476,12 +9505,12 @@ msgstr "DNS-navn" msgid "Protocol" msgstr "protokol" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "Gruppe-ID" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9493,12 +9522,12 @@ msgstr "Gruppe-ID" msgid "Authentication type" msgstr "Autentificeringstype" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Autentificeringsnøgle" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9510,26 +9539,26 @@ msgstr "Autentificeringsnøgle" msgid "Authentication" msgstr "Autentificering" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Områdetype" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "VLAN-ID-intervaller" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Anvendelsesområde" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "VLAN-ID-intervaller" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Område & Gruppe" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9556,8 +9585,8 @@ msgstr "VLANs gruppe (hvis nogen)" msgid "Parent device of assigned interface (if any)" msgstr "Overordnet enhed med tildelt grænseflade (hvis nogen)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9583,40 +9612,60 @@ msgstr "Er primær" msgid "Make this the primary IP for the assigned device" msgstr "Gør dette til den primære IP for den tildelte enhed" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "Ingen enhed eller virtuel maskine angivet; kan ikke indstilles som primær IP" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "Ingen grænseflade angivet; kan ikke indstilles som primær IP" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Autentificeringstype" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Omfangstype (app og model)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Tildelt VLAN-gruppe" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "IP-protokol" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Påkrævet, hvis den ikke er tildelt en VM" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Påkrævet, hvis den ikke er tildelt en enhed" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} er ikke tildelt denne enhed/VM." @@ -9698,7 +9747,7 @@ msgstr "Tildelt til en grænseflade" msgid "DNS Name" msgstr "DNS-navn" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9709,13 +9758,13 @@ msgstr "VLAN'er" msgid "Contains VLAN ID" msgstr "Indeholder VLAN ID" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "VLAN-ID" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9726,7 +9775,7 @@ msgstr "VLAN-ID" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9755,8 +9804,8 @@ msgstr "Område/VLAN-tildeling" msgid "IP Range" msgstr "IP-rækkevidde" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "FHRP-gruppen" @@ -9765,47 +9814,57 @@ msgstr "FHRP-gruppen" msgid "Make this the primary IP for the device/VM" msgstr "Gør dette til den primære IP for enheden/VM" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "NAT IP (indvendigt)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "En IP-adresse kan kun tildeles et enkelt objekt." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Kan ikke omtildele IP-adresse, mens den er angivet som den primære IP for " -"det overordnede objekt" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "Kun IP-adresser, der er tildelt en grænseflade, kan betegnes som primære " "IP'er." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Virtuel IP-adresse" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "Opgaven findes allerede" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "VLAN-id'er" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "VLAN'er til børn" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9813,33 +9872,33 @@ msgstr "" "Kommasepareret liste over et eller flere portnumre. Et interval kan angives " "ved hjælp af en bindestreg." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Serviceskabelon" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Havn (er)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Serviceydelse" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Serviceskabelon" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "Fra skabelon" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Brugerdefineret" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10122,6 +10181,14 @@ msgstr "" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Duplikat IP-adresse fundet i {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Kan ikke omtildele IP-adresse, mens den er angivet som den primære IP for " +"det overordnede objekt" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Kun IPv6-adresser kan tildeles SLAAC-status" @@ -10174,40 +10241,48 @@ msgstr "Kan ikke indstille scope_type uden scope_id." msgid "Cannot set scope_id without scope_type." msgstr "Kan ikke indstille scope_id uden scope_type." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Intervaller kan ikke overlappe hinanden." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"Maksimal børneVID skal være større end eller lig med minimum børns VID " -"({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "Det specifikke område, som dette VLAN er tildelt (hvis nogen)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "VLAN-gruppe (valgfrit)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "Numerisk VLAN-id (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Driftsstatus for dette VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "Den primære funktion af denne VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10216,7 +10291,7 @@ msgstr "" "VLAN er tildelt til gruppe {group} (anvendelsesområde: {scope}); kan ikke " "også tildele til området {site}." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "" @@ -10980,17 +11055,12 @@ msgstr "IPsec-politikker" msgid "IPSec Profiles" msgstr "IPsec-profiler" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Virtualisering" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Virtuelle diske" @@ -11152,7 +11222,7 @@ msgstr "Systemet" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11400,19 +11470,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Række {i}: Objekt med ID {id} findes ikke" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "Nej {object_type} blev udvalgt." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Omdøbt {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Slettet {count} {object_type}" @@ -11444,7 +11514,7 @@ msgstr "Synkroniseret {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} skal implementere get_children ()" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11788,9 +11858,7 @@ msgid "Circuit Type" msgstr "Kredsløbstype" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11801,7 +11869,6 @@ msgstr "Tilføj" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12090,35 +12157,35 @@ msgstr "dage" msgid "Indefinite" msgstr "Ubestemt" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Ikke installeret" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Oversigt" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Installere" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Plugin Detaljer" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Resumé" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Licens" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Versionshistorik" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Lokale installationsinstruktioner" @@ -12462,8 +12529,8 @@ msgstr "Tilføj en tjeneste" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12536,20 +12603,24 @@ msgstr "Konfiguration" msgid "Context Data" msgstr "Kontekstdata" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Renderet konfiguration" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Hent" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Ingen konfigurationsskabelon fundet" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12571,7 +12642,6 @@ msgid "Local Config Context Data" msgstr "Lokale konfigurationskontekstdata" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12618,12 +12688,12 @@ msgid "VM Role" msgstr "VM-rolle" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Modelnavn" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Varenummer" @@ -12762,7 +12832,7 @@ msgstr "MAC-adresse" msgid "Wireless Link" msgstr "Trådløs forbindelse" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "jævnaldrende" @@ -13386,7 +13456,7 @@ msgstr "Du har ikke tilladelse til at køre scripts" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Kør script" @@ -13399,27 +13469,32 @@ msgstr "Fejl ved indlæsning af script" msgid "Script no longer exists in the source file." msgstr "Script findes ikke længere i kildefilen." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Sidste løb" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "Script findes ikke længere i kildefilen" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Aldrig" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Kør igen" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Ingen scripts fundet" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13740,7 +13815,7 @@ msgstr "Alle notifikationer" msgid "Select" msgstr "Vælg" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Nulstil" @@ -14224,6 +14299,10 @@ msgstr "Ressourcer" msgid "Add Virtual Disk" msgstr "Tilføj virtuel disk" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15291,13 +15370,13 @@ msgid "Memory (MB)" msgstr "Hukommelse (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Disk (GB)" +msgid "Disk (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Størrelse (GB)" +msgid "Size (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15476,68 +15555,80 @@ msgstr "virtuel disk" msgid "virtual disks" msgstr "virtuelle diske" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Tilføjet {count} enheder til klynge {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Fjernet {count} enheder fra klynge {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPsec - Transport" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec - Tunnel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP-i-IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GREE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Hub" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "Talede" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Aggressiv" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Vigtigste" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Foruddelte nøgler" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Certifikater" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "RSA signaturer" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "DSA signaturer" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15546,23 +15637,27 @@ msgstr "DSA signaturer" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Gruppe {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Ethernet Privat LAN" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Ethernet virtuelt privat LAN" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Ethernet privat træ" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Ethernet virtuelt privat træ" diff --git a/netbox/translations/de/LC_MESSAGES/django.mo b/netbox/translations/de/LC_MESSAGES/django.mo index fdcad7156..1a628bec8 100644 Binary files a/netbox/translations/de/LC_MESSAGES/django.mo and b/netbox/translations/de/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/de/LC_MESSAGES/django.po b/netbox/translations/de/LC_MESSAGES/django.po index 4635cd650..37178c46e 100644 --- a/netbox/translations/de/LC_MESSAGES/django.po +++ b/netbox/translations/de/LC_MESSAGES/django.po @@ -8,9 +8,9 @@ # Niklas, 2024 # fepilins, 2024 # Steffen, 2024 +# haagehan, 2024 # Jeremy Stretch, 2024 # Robin Reinhardt, 2024 -# haagehan, 2024 # chbally, 2024 # #, fuzzy @@ -18,7 +18,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" "Last-Translator: chbally, 2024\n" "Language-Team: German (https://app.transifex.com/netbox-community/teams/178115/de/)\n" @@ -94,8 +94,8 @@ msgstr "Dein Passwort wurde erfolgreich geändert." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -108,7 +108,7 @@ msgstr "Provisionierung" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -119,8 +119,8 @@ msgid "Active" msgstr "Aktiv" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Offline" @@ -133,7 +133,7 @@ msgstr "Deprovisionierung" msgid "Decommissioned" msgstr "Stillgelegt" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Primär" @@ -206,12 +206,12 @@ msgstr "Standortgruppe (URL-Slug)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -220,18 +220,17 @@ msgstr "Standortgruppe (URL-Slug)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -339,10 +338,10 @@ msgstr "Abschlusspunkt A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -394,7 +393,7 @@ msgstr "Transportnetzgruppe (SLUG)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -409,33 +408,33 @@ msgstr "ASNs" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -444,7 +443,7 @@ msgstr "ASNs" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -459,7 +458,7 @@ msgstr "ASNs" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -479,7 +478,7 @@ msgstr "ASNs" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -572,10 +571,10 @@ msgid "Service ID" msgstr "Dienst ID" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -596,16 +595,16 @@ msgstr "Farbe" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -660,14 +659,14 @@ msgstr "Providerkonto" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -676,13 +675,13 @@ msgstr "Providerkonto" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -693,7 +692,7 @@ msgstr "Providerkonto" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -729,30 +728,30 @@ msgstr "Status" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -822,11 +821,11 @@ msgstr "Service Parameter" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -858,11 +857,11 @@ msgstr "Portgeschwindigkeit (Kbit/s)" msgid "Upstream speed (Kbps)" msgstr "Upstream Geschwindigkeit (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Als verbunden markieren" @@ -909,10 +908,10 @@ msgstr "Transportnetz Typ" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -922,13 +921,13 @@ msgstr "Betriebsstatus" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -953,12 +952,12 @@ msgstr "Providernetzwerk" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -975,9 +974,9 @@ msgstr "Providernetzwerk" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1006,8 +1005,8 @@ msgid "Contacts" msgstr "Kontakte" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1015,13 +1014,12 @@ msgstr "Kontakte" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1034,16 +1032,16 @@ msgid "Region" msgstr "Region" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1055,7 +1053,7 @@ msgstr "Standortgruppe" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1094,9 +1092,9 @@ msgstr "Konto" msgid "Term Side" msgstr "Terminationsseite" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1106,11 +1104,11 @@ msgstr "Zuweisung" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1182,20 +1180,20 @@ msgid "Unique circuit ID" msgstr "Eindeutige Transportnetz-ID" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "Status" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "installiert" @@ -1318,11 +1316,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1333,7 +1331,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1421,7 +1419,7 @@ msgstr "Providernetzwerke" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1432,7 +1430,7 @@ msgstr "Providernetzwerke" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1463,7 +1461,7 @@ msgstr "Providernetzwerke" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1628,7 +1626,7 @@ msgstr "Abgeschlossen" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Fehlgeschlagen" @@ -1695,7 +1693,7 @@ msgid "Cancelled" msgstr "Abgebrochen" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Lokal" @@ -1782,8 +1780,8 @@ msgid "User name" msgstr "Benutzername" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1887,7 +1885,7 @@ msgid "Completed before" msgstr "Abgeschlossen vor" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1955,9 +1953,9 @@ msgstr "" msgid "Rack Elevations" msgstr "Rackübersichten" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Stromversorgung" @@ -2060,7 +2058,7 @@ msgstr "" "({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2120,7 +2118,7 @@ msgstr "Typ" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2240,60 +2238,60 @@ msgstr "verwaltete Datei" msgid "managed files" msgstr "verwaltete Dateien" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "geplant" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "Intervall" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Wiederholungsintervall (in Minuten)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "gestartet" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "abgeschlossen" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "Daten" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "Fehler" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "Job-ID" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "Job" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "Jobs" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "Jobs können diesem Objekttyp nicht zugewiesen werden ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "" "Ungültiger Status für die Beendigung des Jobs. Es stehen folgende Optionen " "zur Auswahl: {choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" @@ -2378,7 +2376,7 @@ msgstr "Maximale NetBox-Version" msgid "No plugin data found" msgstr "Keine Plugin-Daten gefunden" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Autor" @@ -2386,7 +2384,7 @@ msgstr "Autor" msgid "Installed" msgstr "Installiert" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Zertifiziert" @@ -2512,11 +2510,11 @@ msgstr "Job {id}wurde gestoppt" msgid "Failed to stop job {id}" msgstr "Fehler beim Stoppen des Job {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "Der Plugin-Katalog konnte nicht geladen werden" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Plugin {name} nicht gefunden" @@ -2536,7 +2534,7 @@ msgid "Staging" msgstr "Bereitstellung" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Außerbetriebnahme" @@ -2600,7 +2598,7 @@ msgstr "Veraltet" msgid "Millimeters" msgstr "Millimeter" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "Zoll" @@ -2614,15 +2612,15 @@ msgstr "Front- zu Rückseite" msgid "Rear to front" msgstr "Rück- zu Frontseite" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2702,7 +2700,7 @@ msgid "Top to bottom" msgstr "Von oben nach unten" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Passiv" @@ -2731,8 +2729,8 @@ msgid "Proprietary" msgstr "Propritär" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Andere" @@ -2745,24 +2743,24 @@ msgstr "ITA/International" msgid "Physical" msgstr "Physikalisch" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Virtuell" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Funknetze" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Virtuelle Schnittstellen" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2771,27 +2769,27 @@ msgstr "Virtuelle Schnittstellen" msgid "Bridge" msgstr "Bridge" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Link Aggregation Group (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (fest)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (modular)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (Backplane)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Mobilfunk" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2799,130 +2797,130 @@ msgstr "Mobilfunk" msgid "Serial" msgstr "Seriell" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Koaxial" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "Stapelnd" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Halb" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Voll" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Automatisch" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Untagged" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Tagged" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Tagged (Alle)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "IEEE-Standard" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "Passiv 24 V (2 Paare)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "Passiv 24 V (4 Paare)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "Passiv 48 V (2 Paare)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "Passiv 48 V (4 Paare)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Kupfer" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Glasfaser" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Faser" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Verbunden" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Kilometer" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Meter" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Zentimeter" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Meilen" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Fuß" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Kilogramm" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Gramm" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "Pfund" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Unzen" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Redundant" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Einphasig" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Dreiphasig" @@ -3168,7 +3166,7 @@ msgstr "Clustergruppe (ID)" msgid "Device model (slug)" msgstr "Gerätemodell (URL-Slug)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "Hat volle Tiefe" @@ -3290,21 +3288,21 @@ msgstr "Zugewiesenes VLAN" msgid "Assigned VID" msgstr "Zugewiesene VID" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3371,7 +3369,7 @@ msgid "LAG interface (ID)" msgstr "LAG-Schnittstelle (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Virtual Device Context" @@ -3445,7 +3443,7 @@ msgstr "Tags" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3462,38 +3460,38 @@ msgstr "" "Alphanumerische Bereiche werden unterstützt. (Muss der Anzahl der Namen " "entsprechen, die erstellt werden.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Name des Kontakts" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Telefon des Kontakts" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "E-Mail des Kontakts" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Zeitzone" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3503,58 +3501,59 @@ msgstr "Zeitzone" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Hersteller" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Formfaktor" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Breite" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Höhe (HE)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Absteigende Höheneinheiten (HE)" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Äußere Breite" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Äußere Tiefe" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Äußere Einheit" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Einbautiefe" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3565,10 +3564,10 @@ msgstr "Einbautiefe" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3577,61 +3576,61 @@ msgstr "Einbautiefe" msgid "Weight" msgstr "Gewicht" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Maximales Gewicht" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Gewichtseinheit" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Rack-Typ" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Äußere Abmessungen" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Abmessungen" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Nummerierung" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3659,45 +3658,50 @@ msgstr "Nummerierung" msgid "Role" msgstr "Rolle" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Racktyp" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Seriennummer" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Asset-Tag" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Luftstrom" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3707,64 +3711,64 @@ msgstr "Luftstrom" msgid "Rack" msgstr "Rack" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Hardware" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Standard-Betriebssystem" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Artikelnummer" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "Höheneinheit" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Von der Nutzung ausschließen" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Gerätetyp" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Modultyp" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Gehäuse" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "VM-Rolle" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3775,19 +3779,19 @@ msgstr "VM-Rolle" msgid "Config template" msgstr "Konfigurationsvorlage" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Gerätetyp" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Geräterolle" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3801,14 +3805,36 @@ msgstr "Geräterolle" msgid "Platform" msgstr "Betriebssystem" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Cluster" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3818,9 +3844,9 @@ msgstr "Betriebssystem" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3829,10 +3855,10 @@ msgstr "Betriebssystem" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3859,7 +3885,7 @@ msgstr "Betriebssystem" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3869,23 +3895,28 @@ msgstr "Betriebssystem" msgid "Device" msgstr "Gerät" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Konfiguration" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Virtualisierung" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Modultyp" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3903,109 +3934,109 @@ msgstr "Modultyp" msgid "Label" msgstr "Label" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Länge" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Längeneinheit" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Domäne" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "Stromverteiler" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Versorgung" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Phase" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Spannung" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Stromstärke" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Max. Auslastung" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Maximale Auslastung" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Maximale Leistungsaufnahme (Watt)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Zugewiesene Leistungsaufnahme" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Zugewiesene Leistungsaufnahme (Watt)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Stromanschluss" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Phasenlage" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Nur Management" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "PoE-Modus" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "PoE-Typ" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "WLAN Funktion" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4019,17 +4050,17 @@ msgstr "WLAN Funktion" msgid "Module" msgstr "Modul" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "LAG" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Virtual Device Contexts" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4038,7 +4069,7 @@ msgstr "Virtual Device Contexts" msgid "Speed" msgstr "Geschwindigkeit" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4052,76 +4083,88 @@ msgstr "Geschwindigkeit" msgid "Mode" msgstr "Modus" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "VLAN-Gruppe" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "Untagged VLAN" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "Getaggte VLANs" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "Hinzufügen eines getaggten VLANs" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "Getaggte VLANs entfernen" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "WLAN-Gruppe" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "WLANs" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Adressierung" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Dienst / Port" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Verwandte Schnittstellen" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "802.1Q-Switching" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "Hinzufügen/Entfernen" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "Der Schnittstellenmodus muss gesetzt werden, um VLANs zuzuweisen" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "" "Einer Endgeräteschnittstelle (Access) können keine getaggten VLANs " @@ -4149,9 +4192,9 @@ msgstr "Zugewiesene Gruppe" msgid "available options" msgstr "verfügbare Optionen" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4173,15 +4216,15 @@ msgstr "Der Hersteller dieses Racktyps" msgid "The lowest-numbered position in the rack" msgstr "Die Position mit der niedrigsten Nummer im Rack" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Breite von Schiene zu Schiene (in Zoll)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Einheit für Außenmaße" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Einheit für Rackgewichte" @@ -4193,158 +4236,149 @@ msgstr "Name des zugewiesenen Mandanten " msgid "Name of assigned role" msgstr "Name der zugewiesenen Rolle" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "Racktyp Modell" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Richtung des Luftstroms" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "Die Breite muss festgelegt werden, wenn kein Racktyp angegeben wird." + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" +"Die Anzahl HE muss festgelegt werden, wenn kein Racktyp angegeben wird." + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Übergeordneter Standort" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Lokation des Racks (falls vorhanden)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Einheiten" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Kommagetrennte Liste einzelner Einheitennummern" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "Der Hersteller, der diesen Gerätetyp herstellt" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "Das Standard-Betriebssystem für Geräte diesen Typs (optional)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Gewicht des Geräts" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Einheit für das Gerätegewicht" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Gewicht des Moduls" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Einheit für das Modulgewicht" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Betriebssystem-Zuweisungen auf diesen Hersteller beschränken" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Zugewiesene Rolle" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Gerätetyp Hersteller" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Gerätetyp Modell" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Zugewiesenes Betriebssystem" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Virtuelles Gehäuse" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Cluster" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Virtualisierungscluster" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Zugewiesene Lokation (falls vorhanden)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Zugewiesenes Rack (falls vorhanden)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Ausrichtung" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Montierte Rackseite" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Übergeordnetes Gerät (für untergeordnete Geräte)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Geräteeinsatz" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" "Geräteschacht, in dem dieses Gerät installiert ist (für untergeordnete " "Geräte)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "Das Gerät, in dem dieses Modul installiert ist" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Moduleinsatz" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "Der Modulschacht, in dem dieses Modul installiert ist" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "Der Typ des Moduls" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Komponenten replizieren" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4352,87 +4386,87 @@ msgstr "" "Automatisches Ausfüllen von Komponenten, die diesem Modultyp zugeordnet sind" " (standardmäßig aktiviert)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Komponenten übernehmen" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Übernehmen Sie bereits bestehende Komponenten" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Anschlusstyp" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Anschlussgeschwindigkeit in Bit/s" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Ausgangstyp" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Lokaler Stromanschluss, der diese Steckdose speist" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Elektrische Phase (für dreiphasige Stromkreise)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Übergeordnete Schnittstelle" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Überbrückte Schnittstelle" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Lag" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Übergeordnete LAG-Schnittstelle" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "Vdcs" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" "VDC-Namen, getrennt durch Kommas, umgeben von doppelten Anführungszeichen. " "Beispiel:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Physikalisches Medium" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Duplex" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "PoE-Modus" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "PoE-Typ" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "IEEE 802.1Q-Betriebsmodus (für L2-Schnittstellen)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4440,173 +4474,173 @@ msgstr "IEEE 802.1Q-Betriebsmodus (für L2-Schnittstellen)" msgid "Assigned VRF" msgstr "Zugewiesenes VRF" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Rf-Rolle" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "WLAN Rolle (AP/Station)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} ist dem Gerät {device} nicht zugewiesen" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Rückseitenanschluss" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Entsprechender Rückanschluss" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Klassifizierung des physikalischen Mediums" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Installiertes Gerät" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "In diesem Schacht installiertes untergeordnetes Gerät" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Untergeordnetes Gerät wurde nicht gefunden." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Artikel aus dem übergeordneten Inventar" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Komponententyp" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Komponententyp" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Name der Komponente" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Name der Komponente" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Komponente wurde nicht gefunden: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Gerät Seite A" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Name des Geräts" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Typ Seite A" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Typ des Abschlusspunktes" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Name der Seite A" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Name des Abschlusspunktes" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Gerät Seite B" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Typ Seite B" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Name der Seite B" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Status der Verbindung" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "" "Seite {side_upper}: {device} {termination_object} ist bereits verbunden" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} Seitlicher Abschluss nicht gefunden: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Master" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Mastergerät" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Name des übergeordneten Standorts" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "vorgeschalteter Stromverteiler" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Primär oder redundant" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Versorgungsart (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Ein- oder Dreiphasig" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "Primäre IPv4" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "IPv4-Adresse mit Maske, z. B. 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "Primäre IPv6" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "IPv6-Adresse mit Präfixlänge, z. B. 2001:db8: :1/64" @@ -4695,10 +4729,6 @@ msgstr "Übergeordnete Gruppe" msgid "Facility" msgstr "Einrichtung" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Racktyp" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Funktion" @@ -4735,7 +4765,7 @@ msgid "Has virtual device contexts" msgstr "Hat Virtual Device Contexts" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Clustergruppe" @@ -4774,7 +4804,7 @@ msgstr "Art" msgid "Mgmt only" msgstr "Nur Verwaltung" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4881,36 +4911,51 @@ msgstr "" msgid "Characteristics" msgstr "Charakteristiken" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" +"Alphanumerische Bereiche werden für die Massenerstellung unterstützt. Groß- " +"und Kleinschreibung und Typen innerhalb eines einzigen Bereichs werden nicht" +" unterstützt (Beispiel: [ge, xe] -0/0/ [0-9]). Das Token " +"{module}, falls vorhanden, wird beim Erstellen eines neuen " +"Moduls automatisch durch den Positionswert ersetzt." + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Konsolenanschlussvorlage" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Port-Vorlage für Konsolenserver" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Frontanschluss-Vorlage" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Schnittstellen-Vorlage" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Vorlage für Steckdosen" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Vorlage für Stromverteiler" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Vorlage für den hinteren Anschluss" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4934,7 +4979,7 @@ msgstr "Vorlage für den hinteren Anschluss" msgid "Interface" msgstr "Schnittstelle" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4942,14 +4987,14 @@ msgstr "Schnittstelle" msgid "Console Port" msgstr "Konsolenanschluss" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Konsolenserveranschluss" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4960,7 +5005,7 @@ msgstr "Konsolenserveranschluss" msgid "Front Port" msgstr "Frontanschluss" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4973,41 +5018,41 @@ msgstr "Frontanschluss" msgid "Rear Port" msgstr "Rückanschluss" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Stromanschluss" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Stromabgang" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Komponentenzuweisung" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "" "Ein InventoryItem kann nur einer einzelnen Komponente zugewiesen werden." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "LAG-Schnittstelle" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Filtern Sie VLANs, die für die Zuweisung nach Gruppen verfügbar sind." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "untergeordnetes Gerät" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -5015,35 +5060,35 @@ msgstr "" "Untergeordnete Geräte müssen zuerst erstellt und dem Standort und dem Rack " "des übergeordneten Geräts zugewiesen werden." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Konsolenanschluss" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Konsolenserveranschluss" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Frontanschluss" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "Stromabgang" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Inventar-Artikel" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Rolle des Inventarartikels" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5061,12 +5106,12 @@ msgstr "" "{pattern_count} werden erwartet." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Rückanschlüsse" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" "Wählen Sie für jeden zu erstellenden Frontanschluss eine hintere Anschluss-" @@ -5082,16 +5127,7 @@ msgstr "" "muss mit der ausgewählten Anzahl der hinteren Anschlusspositionen " "übereinstimmen ({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"Die Zeichenkette {module} wird durch die Position des " -"zugewiesenen Moduls ersetzt, falls vorhanden." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5101,18 +5137,18 @@ msgstr "" "der ausgewählten Anzahl der hinteren Anschlusspositionen übereinstimmen " "({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Mitglieder" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Ausgangsposition" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." @@ -5120,7 +5156,7 @@ msgstr "" "Position des ersten Mitgliedsgeräts. Erhöht sich für jedes weitere Mitglied " "um eins." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "Für das erste VC-Mitglied muss eine Position angegeben werden." @@ -5691,7 +5727,7 @@ msgid "" "not part of virtual chassis {virtual_chassis}." msgstr "" "Die gewählte Bridge-Schnittstelle ({interface}) gehört zu {device}, das " -"nicht Teil des virtuellen Chassis ist {virtual_chassis}." +"nicht Teil des virtuellen Chassis {virtual_chassis}ist." #: netbox/dcim/models/device_components.py:828 msgid "Virtual interfaces cannot have a parent LAG interface." @@ -5718,7 +5754,7 @@ msgid "" " virtual chassis {virtual_chassis}." msgstr "" "Die gewählte LAG-Schnittstelle ({lag}) gehört zu {device}, das nicht Teil " -"des virtuellen Chassis ist {virtual_chassis}." +"des virtuellen Chassis {virtual_chassis} ist." #: netbox/dcim/models/device_components.py:856 msgid "Virtual interfaces cannot have a PoE mode." @@ -6086,12 +6122,12 @@ msgstr "Position (HE)" msgid "rack face" msgstr "Rackseite" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "primäre IPv4-Adresse" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "primäre IPv6-Adresse" @@ -6270,15 +6306,15 @@ msgstr "" "Das Modul muss in einem Modulschacht installiert werden, der zum " "zugewiesenen Gerät gehört ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "Domäne" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "virtuelles Gehäuse" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." @@ -6286,7 +6322,7 @@ msgstr "" "Der gewählte Master ({master}) ist diesem virtuellen Chassis nicht " "zugewiesen." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6295,34 +6331,34 @@ msgstr "" "Das virtuelle Gehäuse kann nicht gelöscht werden {self}. Es gibt " "Mitgliedsschnittstellen, die gehäuseübergreifende LAG-Schnittstellen bilden." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "identifizieren" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Numerische Kennung, die für das übergeordnete Gerät eindeutig ist" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "Kommentare" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "Virtual Device Context" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "Virtual Device Context" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} ist keine IPv{family}-Adresse." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" "Die primäre IP-Adresse muss zu einer Schnittstelle auf dem zugewiesenen " @@ -6516,7 +6552,7 @@ msgstr "Lokal zugewiesener Bezeichner" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Funktionelle Rolle" @@ -6738,7 +6774,7 @@ msgstr "Erreichbar" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Geräte" @@ -6767,8 +6803,8 @@ msgid "Site Group" msgstr "Standortgruppe" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6819,20 +6855,20 @@ msgid "Power outlets" msgstr "Steckdosen" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Schnittstellen" @@ -6858,8 +6894,8 @@ msgid "Module Bay" msgstr "Moduleinsatz" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6888,7 +6924,7 @@ msgstr "Maximaler Stromverbrauch (W)" msgid "Allocated draw (W)" msgstr "Zugewiesener Stromverbrauch (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6984,87 +7020,87 @@ msgstr "Höhe in HE" msgid "Instances" msgstr "Instanzen" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Konsolenanschlüsse" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Konsolenserveranschlüsse" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Stromanschlüsse" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Steckdosen" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Frontanschlüsse" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Rückanschlüsse" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Geräteeinsätze" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Moduleinsätze" @@ -7113,7 +7149,7 @@ msgstr "Platz" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7123,28 +7159,28 @@ msgstr "Standorte" msgid "Test case must set peer_termination_type" msgstr "Der Testfall muss peer_termination_type setzen" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Verbindung von {count} {type} unterbrochen" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Rackreservierungen" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Nicht in einem Rack befindliche Geräte" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Konfigurationsvorlage" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Konfiguration rendern" @@ -7155,37 +7191,37 @@ msgstr "Ein Fehler ist beim Rendern der Vorlage aufgetreten: {error}" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Virtuelle Maschinen" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Gerät {device} im Schacht {device_bay} installiert." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Gerät {device} im Schacht {device_bay} entfernt." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Untergeordnet" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Mitglied hinzugefügt {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "" "Ein Hauptgerät (Master Device) {device} kann von einem virtuellen Gehäuse " "nicht entfernt werden." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "{device} vom virtuellen Gehäuse {chassis} entfernt." @@ -7369,7 +7405,6 @@ msgstr "Aktualisieren" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -8138,8 +8173,8 @@ msgid "" "Enter parameters to pass to the action in JSON format." msgstr "" -"Geben Sie Parameter ein, die an die Aktion übergeben werden sollen JSON formatieren." +"Geben Sie Parameter ein, die an die Aktion übergeben werden sollen, in JSON formatiert." #: netbox/extras/forms/model_forms.py:394 #: netbox/templates/extras/eventrule.html:10 @@ -8215,19 +8250,19 @@ msgstr "Planen Sie die Ausführung des Skripts auf eine festgelegte Zeit" msgid "Interval at which this script is re-run (in minutes)" msgstr "Intervall, in dem dieses Skript erneut ausgeführt wird (in Minuten)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "Datenbankänderungen wurden automatisch rückgängig gemacht." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Das Skript wurde mit einem Fehler abgebrochen: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Eine Ausnahme ist aufgetreten: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "Datenbankänderungen wurden aufgrund eines Fehlers rückgängig gemacht." @@ -9247,12 +9282,12 @@ msgstr "" #: netbox/extras/validators.py:133 #, python-brace-format msgid "Invalid attribute \"{name}\" for request" -msgstr "Ungültiges Attribut“{name}„zur Anfrage" +msgstr "Ungültiges Attribut \"{name}\" zur Anfrage" #: netbox/extras/validators.py:150 #, python-brace-format msgid "Invalid attribute \"{name}\" for {model}" -msgstr "Ungültiges Attribut“{name}„für {model}" +msgstr "Ungültiges Attribut “{name}\" für {model}" #: netbox/extras/views.py:960 msgid "Your dashboard has been reset." @@ -9274,7 +9309,7 @@ msgstr "Gelöschtes Widget: " msgid "Error deleting widget: " msgstr "Fehler beim Löschen des Widgets: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "" "Das Skript kann nicht ausgeführt werden: Der RQ-Worker-Prozess läuft nicht." @@ -9425,7 +9460,7 @@ msgid "Prefixes which contain this prefix or IP" msgstr "Präfixe, die dieses Präfix oder diese IP enthalten" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Länge der Maske" @@ -9439,7 +9474,7 @@ msgid "VLAN number (1-4094)" msgstr "VLAN-Nummer (1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9551,16 +9586,16 @@ msgstr "Eine CIDR-Maske (z. B. /24) ist erforderlich." msgid "Address pattern" msgstr "Adressmuster" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Erzwingen Sie einzigartigen Speicherplatz" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "Ist privat" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9574,20 +9609,20 @@ msgstr "Ist privat" msgid "RIR" msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "hinzugefügt am" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "VLAN-Gruppe" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9600,32 +9635,32 @@ msgstr "VLAN-Gruppe" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Länge des Prefixes" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "Ist ein Pool" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Als voll ausgelastet behandeln" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "VLAN-Zuweisung" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "DNS-Name" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9633,12 +9668,12 @@ msgstr "DNS-Name" msgid "Protocol" msgstr "Protokoll" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "Gruppen-ID" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9650,12 +9685,12 @@ msgstr "Gruppen-ID" msgid "Authentication type" msgstr "Typ der Authentifizierung" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Authentifizierungsschlüssel" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9667,26 +9702,26 @@ msgstr "Authentifizierungsschlüssel" msgid "Authentication" msgstr "Authentifizierung" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Art des Geltungsbereichs" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "VLAN-ID-Bereiche" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Geltungsbereich" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "VLAN-ID-Bereiche" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Standort und Gruppe" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9713,8 +9748,8 @@ msgstr "VLAN-Gruppe (falls vorhanden)" msgid "Parent device of assigned interface (if any)" msgstr "Übergeordnetes Gerät der zugewiesenen Schnittstelle (falls vorhanden)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9740,42 +9775,66 @@ msgstr "Ist primär" msgid "Make this the primary IP for the assigned device" msgstr "Machen Sie dies zur primären IP für das zugewiesene Gerät" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "Ist Out-Of-Band" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" +"Geben Sie dies als Out-of-Band-IP-Adresse für das zugewiesene Gerät an" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "Kein Gerät oder virtuelle Maschine angegeben; kann nicht als primäre IP " "festgelegt werden" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" +"Kein Gerät angegeben; kann nicht als Out-of-Band-IP eingerichtet werden" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "Out-of-Band-IP für virtuelle Maschinen kann nicht eingerichtet werden" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "" "Keine Schnittstelle angegeben; kann nicht als primäre IP festgelegt werden" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" +"Keine Schnittstelle angegeben; kann nicht als Out-of-Band-IP festgelegt " +"werden" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Authentifizierungstyp" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Art des Umfangs (App und Modell)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Zugewiesene VLAN-Gruppe" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "IP-Protokoll" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Erforderlich, wenn es keiner VM zugewiesen ist" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Erforderlich, wenn es keinem Gerät zugewiesen ist" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} ist diesem Gerät/dieser VM nicht zugewiesen." @@ -9857,7 +9916,7 @@ msgstr "Einer Schnittstelle zugewiesen" msgid "DNS Name" msgstr "DNS-Name" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9868,13 +9927,13 @@ msgstr "VLANs" msgid "Contains VLAN ID" msgstr "Enthält VLAN-ID" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "VLAN-ID" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9885,7 +9944,7 @@ msgstr "VLAN-ID" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9914,8 +9973,8 @@ msgstr "Standort-/VLAN-Zuweisung" msgid "IP Range" msgstr "IP-Bereich" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "FHRP-Gruppe" @@ -9924,47 +9983,63 @@ msgstr "FHRP-Gruppe" msgid "Make this the primary IP for the device/VM" msgstr "Machen Sie dies zur primären IP für das Gerät/die VM" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "Machen Sie dies zur Out-of-Band-IP für das Gerät" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "NAT IP (innen)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "Eine IP-Adresse kann nur einem einzigen Objekt zugewiesen werden." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Die IP-Adresse kann nicht neu zugewiesen werden, solange sie als primäre IP " -"für das übergeordnete Objekt festgelegt ist" +"Die primäre IP-Adresse für das übergeordnete Gerät/die virtuelle Maschine " +"kann nicht neu zugewiesen werden" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" +"Out-of-Band-IP-Adresse für das übergeordnete Gerät kann nicht neu zugewiesen" +" werden" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "Nur IP-Adressen, die einer Schnittstelle zugewiesen sind, können als primäre" " IPs festgelegt werden." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" +"Nur IP-Adressen, die einer Geräteschnittstelle zugewiesen sind, können als " +"Out-of-Band-IP für ein Gerät festgelegt werden." + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Virtuelle IP-Adresse" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "Zuweisung ist bereits vorhanden" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "VLAN-IDs" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "Untergeordnete VLANs" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9972,33 +10047,33 @@ msgstr "" "Kommagetrennte Liste mit einer oder mehreren Portnummern. Ein Bereich kann " "mit einem Bindestrich angegeben werden." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Vorlage für den Service" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Port(s)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Dienst / Port" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Dienstevorlagen (Ports)" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "Aus Vorlage" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Benutzerdefiniert" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10289,6 +10364,14 @@ msgstr "" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Doppelte IP-Adresse gefunden in {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Die IP-Adresse kann nicht neu zugewiesen werden, solange sie als primäre IP " +"für das übergeordnete Objekt festgelegt ist" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Nur IPv6-Adressen kann der SLAAC-Status zugewiesen werden" @@ -10345,41 +10428,53 @@ msgstr "scope_type kann nicht ohne scope_id gesetzt werden." msgid "Cannot set scope_id without scope_type." msgstr "scope_id kann nicht ohne scope_type gesetzt werden." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" +"Start-VLAN-ID im Bereich ({value}) darf nicht kleiner sein als {minimum}" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" +"Ende der VLAN-ID im Bereich ({value}) darf {maximum}nicht überschreiten " + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" +"Die End-VLAN-ID im Bereich muss größer oder gleich der Start-VLAN-ID sein " +"({range})" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Bereiche dürfen sich nicht überschneiden." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"Die maximale untergeordnete VID muss größer oder gleich der Mindest-VID für " -"untergeordnete VIDs sein ({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "" "Der spezifische Standort, der dieses VLAN zugewiesen ist (falls vorhanden)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "VLAN-Gruppe (optional)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "Numerische VLAN-ID (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Betriebsstatus dieses VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "Die Hauptfunktion dieses VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10388,7 +10483,7 @@ msgstr "" "VLAN ist der Gruppe {group} (Scope: {scope}) zugewiesen; kann nicht auch dem" " Standort {site} zugewiesen werden." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "" @@ -11156,17 +11251,12 @@ msgstr "IPSec-Richtlinien" msgid "IPSec Profiles" msgstr "IPSec-Profile" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Virtualisierung" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Virtuelle Festplatten" @@ -11328,7 +11418,7 @@ msgstr "System" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11582,19 +11672,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Reihe {i}: Objekt mit ID {id} existiert nicht" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "Kein {object_type}ausgewählt" -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Umbenannt {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Gelöscht {count} {object_type}" @@ -11626,7 +11716,7 @@ msgstr "Synchronisiert {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} muss get_children () implementieren" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11973,9 +12063,7 @@ msgid "Circuit Type" msgstr "Transportnetz Typ" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11986,7 +12074,6 @@ msgstr "Hinzufügen" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12276,35 +12363,35 @@ msgstr "Tage" msgid "Indefinite" msgstr "Unbestimmt" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Nicht installiert" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Überblick" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Installieren" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Plugin Details" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Zusammenfassung" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Lizenz" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Versionshistorie" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Lokale Installationsanweisungen" @@ -12649,8 +12736,8 @@ msgstr "Einen Dienst hinzufügen" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12723,20 +12810,24 @@ msgstr "Konfig" msgid "Context Data" msgstr "Kontextdaten" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Gerenderte Konfiguration" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Herunterladen" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Keine Konfigurationsvorlage gefunden" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "Fehler beim Rendern der Vorlage" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "Diesem Gerät wurde keine Konfigurationsvorlage zugewiesen." #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12758,7 +12849,6 @@ msgid "Local Config Context Data" msgstr "Lokale Konfigurationskontextdaten" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12805,12 +12895,12 @@ msgid "VM Role" msgstr "VM-Rolle" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Name des Modells" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Teilnummer" @@ -12949,7 +13039,7 @@ msgstr "MAC-Adresse" msgid "Wireless Link" msgstr "Funkverbindung" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Peer" @@ -13574,7 +13664,7 @@ msgstr "Sie sind nicht berechtigt, Skripts auszuführen" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Skript ausführen" @@ -13587,27 +13677,32 @@ msgstr "Fehler beim Laden des Skripts" msgid "Script no longer exists in the source file." msgstr "Das Skript ist in der Quelldatei nicht mehr vorhanden." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Letzter Lauf" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "Das Skript ist in der Quelldatei nicht mehr vorhanden" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Niemals" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Nochmal ausführen" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "Skripte konnten nicht aus dem Modul geladen werden %(module)s" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Keine Skripte gefunden" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13930,7 +14025,7 @@ msgstr "Alle Benachrichtigungen" msgid "Select" msgstr "Auswählen" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Zurücksetzen" @@ -14415,6 +14510,11 @@ msgstr "Ressourcen" msgid "Add Virtual Disk" msgstr "Virtuelles Laufwerk hinzufügen" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" +"Für diese virtuelle Maschine wurde keine Konfigurationsvorlage zugewiesen." + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -14426,7 +14526,7 @@ msgstr "IKE-Version" #: netbox/templates/vpn/ikepolicy.html:29 msgid "Pre-Shared Key" -msgstr "Vorab geteilter Schlüssel" +msgstr "Pre-Shared Key" #: netbox/templates/vpn/ikepolicy.html:33 #: netbox/templates/wireless/inc/authentication_attrs.html:20 @@ -15295,7 +15395,7 @@ msgstr "" #: netbox/utilities/forms/utils.py:276 #, python-brace-format msgid "Invalid related object attribute for column \"{field}\": {to_field}" -msgstr "Ungültiges verwandtes Objektattribut für Spalte“{field}„: {to_field}" +msgstr "Ungültiges verwandtes Objektattribut für Spalte“{field}\": {to_field}" #: netbox/utilities/forms/utils.py:284 #, python-brace-format @@ -15504,13 +15604,13 @@ msgid "Memory (MB)" msgstr "Speicher (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Festplatte (GB)" +msgid "Disk (MB)" +msgstr "Festplatte (MB)" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Größe (GB)" +msgid "Size (MB)" +msgstr "Größe (MB)" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15544,7 +15644,7 @@ msgstr "" #: netbox/virtualization/forms/model_forms.py:192 msgid "Optionally pin this VM to a specific host device within the cluster" msgstr "" -"Pinnen Sie diese VM optional an ein bestimmtes Host-Gerät innerhalb des " +"Verbinden Sie diese VM optional an ein bestimmtes Host-Gerät innerhalb des " "Clusters an" #: netbox/virtualization/forms/model_forms.py:221 @@ -15701,68 +15801,80 @@ msgstr "virtuelle Festplatte" msgid "virtual disks" msgstr "virtuelle Festplatten" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Füge {count} Geräte zum Cluster {cluster}hinzu " -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Entferne {count}Geräte vom Cluster {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPSec - Transport" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPSec-Tunnel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP-in-IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GRE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "WireGuard" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "OpenVPN" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "L2TP" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "PPTP" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Hub" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "Spoke" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Aggressiv" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Haupt" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Vorab geteilte Schlüssel (Preshared Keys)" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Zertifikate" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "RSA-Signaturen" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "DSA-Signaturen" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15771,23 +15883,27 @@ msgstr "DSA-Signaturen" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Gruppe {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Privates Ethernet-LAN" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Virtuelles privates Ethernet-LAN" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Privater Ethernet-Baum" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Virtueller privater Ethernet-Baum" diff --git a/netbox/translations/en/LC_MESSAGES/django.po b/netbox/translations/en/LC_MESSAGES/django.po index 44b7b82a0..5d1188333 100644 --- a/netbox/translations/en/LC_MESSAGES/django.po +++ b/netbox/translations/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-16 05:01+0000\n" +"POT-Creation-Date: 2025-01-04 05:02+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -82,8 +82,8 @@ msgstr "" #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -96,7 +96,7 @@ msgstr "" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -107,8 +107,8 @@ msgid "Active" msgstr "" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "" @@ -121,7 +121,7 @@ msgstr "" msgid "Decommissioned" msgstr "" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "" @@ -145,7 +145,7 @@ msgstr "" #: netbox/dcim/filtersets.py:464 netbox/dcim/filtersets.py:1021 #: netbox/dcim/filtersets.py:1368 netbox/dcim/filtersets.py:1903 #: netbox/dcim/filtersets.py:2146 netbox/dcim/filtersets.py:2204 -#: netbox/ipam/filtersets.py:339 netbox/ipam/filtersets.py:959 +#: netbox/ipam/filtersets.py:341 netbox/ipam/filtersets.py:961 #: netbox/virtualization/filtersets.py:45 #: netbox/virtualization/filtersets.py:173 netbox/vpn/filtersets.py:358 msgid "Region (ID)" @@ -157,8 +157,8 @@ msgstr "" #: netbox/dcim/filtersets.py:471 netbox/dcim/filtersets.py:1028 #: netbox/dcim/filtersets.py:1375 netbox/dcim/filtersets.py:1910 #: netbox/dcim/filtersets.py:2153 netbox/dcim/filtersets.py:2211 -#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:346 -#: netbox/ipam/filtersets.py:966 netbox/virtualization/filtersets.py:52 +#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:348 +#: netbox/ipam/filtersets.py:968 netbox/virtualization/filtersets.py:52 #: netbox/virtualization/filtersets.py:180 netbox/vpn/filtersets.py:353 msgid "Region (slug)" msgstr "" @@ -168,8 +168,8 @@ msgstr "" #: netbox/dcim/filtersets.py:346 netbox/dcim/filtersets.py:477 #: netbox/dcim/filtersets.py:1034 netbox/dcim/filtersets.py:1381 #: netbox/dcim/filtersets.py:1916 netbox/dcim/filtersets.py:2159 -#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:352 -#: netbox/ipam/filtersets.py:972 netbox/virtualization/filtersets.py:58 +#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:354 +#: netbox/ipam/filtersets.py:974 netbox/virtualization/filtersets.py:58 #: netbox/virtualization/filtersets.py:186 msgid "Site group (ID)" msgstr "" @@ -180,7 +180,7 @@ msgstr "" #: netbox/dcim/filtersets.py:1041 netbox/dcim/filtersets.py:1388 #: netbox/dcim/filtersets.py:1923 netbox/dcim/filtersets.py:2166 #: netbox/dcim/filtersets.py:2224 netbox/extras/filtersets.py:515 -#: netbox/ipam/filtersets.py:359 netbox/ipam/filtersets.py:979 +#: netbox/ipam/filtersets.py:361 netbox/ipam/filtersets.py:981 #: netbox/virtualization/filtersets.py:65 #: netbox/virtualization/filtersets.py:193 msgid "Site group (slug)" @@ -194,12 +194,12 @@ msgstr "" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -208,18 +208,17 @@ msgstr "" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -251,8 +250,8 @@ msgstr "" #: netbox/circuits/filtersets.py:62 netbox/circuits/filtersets.py:229 #: netbox/circuits/filtersets.py:274 netbox/dcim/filtersets.py:242 #: netbox/dcim/filtersets.py:363 netbox/dcim/filtersets.py:458 -#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:238 -#: netbox/ipam/filtersets.py:369 netbox/ipam/filtersets.py:989 +#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:240 +#: netbox/ipam/filtersets.py:371 netbox/ipam/filtersets.py:991 #: netbox/virtualization/filtersets.py:75 #: netbox/virtualization/filtersets.py:203 netbox/vpn/filtersets.py:363 msgid "Site (slug)" @@ -271,13 +270,13 @@ msgstr "" #: netbox/circuits/filtersets.py:95 netbox/circuits/filtersets.py:122 #: netbox/circuits/filtersets.py:156 netbox/circuits/filtersets.py:283 -#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:243 +#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:245 msgid "Provider (ID)" msgstr "" #: netbox/circuits/filtersets.py:101 netbox/circuits/filtersets.py:128 #: netbox/circuits/filtersets.py:162 netbox/circuits/filtersets.py:289 -#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:249 +#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:251 msgid "Provider (slug)" msgstr "" @@ -306,8 +305,8 @@ msgstr "" #: netbox/dcim/filtersets.py:452 netbox/dcim/filtersets.py:1045 #: netbox/dcim/filtersets.py:1393 netbox/dcim/filtersets.py:1928 #: netbox/dcim/filtersets.py:2170 netbox/dcim/filtersets.py:2229 -#: netbox/ipam/filtersets.py:232 netbox/ipam/filtersets.py:363 -#: netbox/ipam/filtersets.py:983 netbox/virtualization/filtersets.py:69 +#: netbox/ipam/filtersets.py:234 netbox/ipam/filtersets.py:365 +#: netbox/ipam/filtersets.py:985 netbox/virtualization/filtersets.py:69 #: netbox/virtualization/filtersets.py:197 netbox/vpn/filtersets.py:368 msgid "Site (ID)" msgstr "" @@ -327,7 +326,7 @@ msgstr "" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 #: netbox/templates/inc/filter_list.html:46 @@ -381,7 +380,7 @@ msgstr "" #: netbox/circuits/forms/bulk_edit.py:30 netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -395,33 +394,33 @@ msgstr "" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -430,7 +429,7 @@ msgstr "" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 netbox/templates/dcim/devicebay.html:32 @@ -443,7 +442,7 @@ msgstr "" #: netbox/templates/dcim/location.html:33 #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -463,7 +462,7 @@ msgstr "" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -554,10 +553,10 @@ msgid "Service ID" msgstr "" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -577,16 +576,16 @@ msgstr "" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -638,29 +637,29 @@ msgstr "" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 #: netbox/dcim/forms/filtersets.py:1059 netbox/dcim/forms/filtersets.py:1170 #: netbox/dcim/tables/devices.py:140 netbox/dcim/tables/devices.py:817 -#: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 +#: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:70 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -671,7 +670,7 @@ msgstr "" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -706,30 +705,30 @@ msgstr "" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -798,11 +797,11 @@ msgstr "" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -834,11 +833,11 @@ msgstr "" msgid "Upstream speed (Kbps)" msgstr "" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "" @@ -884,10 +883,10 @@ msgstr "" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -897,13 +896,13 @@ msgstr "" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -928,12 +927,12 @@ msgstr "" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -950,9 +949,9 @@ msgstr "" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -981,8 +980,8 @@ msgid "Contacts" msgstr "" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -990,13 +989,12 @@ msgstr "" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1009,16 +1007,16 @@ msgid "Region" msgstr "" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1030,7 +1028,7 @@ msgstr "" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1068,9 +1066,9 @@ msgstr "" msgid "Term Side" msgstr "" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1080,11 +1078,11 @@ msgstr "" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:1001 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1155,20 +1153,20 @@ msgid "Unique circuit ID" msgstr "" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "" @@ -1285,10 +1283,10 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 netbox/dcim/models/devices.py:593 -#: netbox/dcim/models/devices.py:1330 netbox/dcim/models/devices.py:1395 +#: netbox/dcim/models/devices.py:1335 netbox/dcim/models/devices.py:1400 #: netbox/dcim/models/power.py:39 netbox/dcim/models/power.py:92 #: netbox/dcim/models/racks.py:262 netbox/dcim/models/sites.py:138 #: netbox/extras/models/configs.py:36 netbox/extras/models/configs.py:215 @@ -1299,7 +1297,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1386,7 +1384,7 @@ msgstr "" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1396,7 +1394,7 @@ msgstr "" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 netbox/templates/core/rq_worker.html:43 +#: netbox/templates/core/plugin.html:54 netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 #: netbox/templates/dcim/devicebay.html:24 @@ -1426,7 +1424,7 @@ msgstr "" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1510,7 +1508,7 @@ msgstr "" #: netbox/circuits/tables/providers.py:82 #: netbox/circuits/tables/providers.py:107 netbox/dcim/tables/devices.py:1036 #: netbox/dcim/tables/devicetypes.py:92 netbox/dcim/tables/modules.py:29 -#: netbox/dcim/tables/modules.py:72 netbox/dcim/tables/power.py:39 +#: netbox/dcim/tables/modules.py:73 netbox/dcim/tables/power.py:39 #: netbox/dcim/tables/power.py:96 netbox/dcim/tables/racks.py:84 #: netbox/dcim/tables/racks.py:145 netbox/dcim/tables/racks.py:225 #: netbox/dcim/tables/sites.py:108 netbox/extras/tables/tables.py:582 @@ -1587,7 +1585,7 @@ msgstr "" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "" @@ -1654,7 +1652,7 @@ msgid "Cancelled" msgstr "" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "" @@ -1741,8 +1739,8 @@ msgid "User name" msgstr "" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1846,7 +1844,7 @@ msgid "Completed before" msgstr "" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1911,9 +1909,9 @@ msgstr "" msgid "Rack Elevations" msgstr "" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "" @@ -2013,7 +2011,7 @@ msgid "Change logging is not supported for this object type ({type})." msgstr "" #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2072,7 +2070,7 @@ msgstr "" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "" @@ -2188,58 +2186,58 @@ msgstr "" msgid "managed files" msgstr "" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "" -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" @@ -2320,7 +2318,7 @@ msgstr "" msgid "No plugin data found" msgstr "" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "" @@ -2328,7 +2326,7 @@ msgstr "" msgid "Installed" msgstr "" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "" @@ -2454,11 +2452,11 @@ msgstr "" msgid "Failed to stop job {id}" msgstr "" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "" @@ -2477,7 +2475,7 @@ msgid "Staging" msgstr "" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "" @@ -2541,7 +2539,7 @@ msgstr "" msgid "Millimeters" msgstr "" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "" @@ -2555,15 +2553,15 @@ msgstr "" msgid "Rear to front" msgstr "" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 netbox/dcim/forms/object_import.py:176 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 netbox/dcim/forms/object_import.py:176 #: netbox/dcim/tables/devices.py:656 netbox/dcim/tables/devices.py:869 #: netbox/dcim/tables/devices.py:954 netbox/extras/tables/tables.py:223 #: netbox/ipam/tables/fhrp.py:59 netbox/ipam/tables/ip.py:378 @@ -2642,7 +2640,7 @@ msgid "Top to bottom" msgstr "" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "" @@ -2671,8 +2669,8 @@ msgid "Proprietary" msgstr "" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "" @@ -2685,24 +2683,24 @@ msgstr "" msgid "Physical" msgstr "" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2711,27 +2709,27 @@ msgstr "" msgid "Bridge" msgstr "" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2739,130 +2737,130 @@ msgstr "" msgid "Serial" msgstr "" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "" @@ -2893,7 +2891,7 @@ msgid "Parent site group (slug)" msgstr "" #: netbox/dcim/filtersets.py:164 netbox/extras/filtersets.py:364 -#: netbox/ipam/filtersets.py:841 netbox/ipam/filtersets.py:993 +#: netbox/ipam/filtersets.py:843 netbox/ipam/filtersets.py:995 msgid "Group (ID)" msgstr "" @@ -2951,15 +2949,15 @@ msgstr "" #: netbox/dcim/filtersets.py:411 netbox/dcim/filtersets.py:892 #: netbox/dcim/filtersets.py:994 netbox/dcim/filtersets.py:1850 -#: netbox/ipam/filtersets.py:381 netbox/ipam/filtersets.py:493 -#: netbox/ipam/filtersets.py:1003 netbox/virtualization/filtersets.py:210 +#: netbox/ipam/filtersets.py:383 netbox/ipam/filtersets.py:495 +#: netbox/ipam/filtersets.py:1005 netbox/virtualization/filtersets.py:210 msgid "Role (ID)" msgstr "" #: netbox/dcim/filtersets.py:417 netbox/dcim/filtersets.py:898 #: netbox/dcim/filtersets.py:1000 netbox/dcim/filtersets.py:1856 -#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:387 -#: netbox/ipam/filtersets.py:499 netbox/ipam/filtersets.py:1009 +#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:389 +#: netbox/ipam/filtersets.py:501 netbox/ipam/filtersets.py:1011 #: netbox/virtualization/filtersets.py:216 msgid "Role (slug)" msgstr "" @@ -3108,7 +3106,7 @@ msgstr "" msgid "Device model (slug)" msgstr "" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "" @@ -3157,7 +3155,7 @@ msgstr "" msgid "Device model" msgstr "" -#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:632 +#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:634 #: netbox/vpn/filtersets.py:102 netbox/vpn/filtersets.py:401 msgid "Interface (ID)" msgstr "" @@ -3171,8 +3169,8 @@ msgid "Module bay (ID)" msgstr "" #: netbox/dcim/filtersets.py:1333 netbox/dcim/filtersets.py:1425 -#: netbox/ipam/filtersets.py:611 netbox/ipam/filtersets.py:851 -#: netbox/ipam/filtersets.py:1115 netbox/virtualization/filtersets.py:161 +#: netbox/ipam/filtersets.py:613 netbox/ipam/filtersets.py:853 +#: netbox/ipam/filtersets.py:1117 netbox/virtualization/filtersets.py:161 #: netbox/vpn/filtersets.py:379 msgid "Device (ID)" msgstr "" @@ -3181,8 +3179,8 @@ msgstr "" msgid "Rack (name)" msgstr "" -#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:606 -#: netbox/ipam/filtersets.py:846 netbox/ipam/filtersets.py:1121 +#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:608 +#: netbox/ipam/filtersets.py:848 netbox/ipam/filtersets.py:1123 #: netbox/vpn/filtersets.py:374 msgid "Device (name)" msgstr "" @@ -3230,21 +3228,21 @@ msgstr "" msgid "Assigned VID" msgstr "" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 -#: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 -#: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 -#: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:318 +#: netbox/ipam/filtersets.py:329 netbox/ipam/filtersets.py:485 +#: netbox/ipam/filtersets.py:586 netbox/ipam/filtersets.py:597 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3263,19 +3261,19 @@ msgstr "" msgid "VRF" msgstr "" -#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:322 -#: netbox/ipam/filtersets.py:333 netbox/ipam/filtersets.py:489 -#: netbox/ipam/filtersets.py:590 netbox/ipam/filtersets.py:601 +#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:324 +#: netbox/ipam/filtersets.py:335 netbox/ipam/filtersets.py:491 +#: netbox/ipam/filtersets.py:592 netbox/ipam/filtersets.py:603 msgid "VRF (RD)" msgstr "" -#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1030 +#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1032 #: netbox/vpn/filtersets.py:342 msgid "L2VPN (ID)" msgstr "" #: netbox/dcim/filtersets.py:1630 netbox/dcim/forms/filtersets.py:1433 -#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1036 +#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1038 #: netbox/ipam/forms/filtersets.py:518 netbox/ipam/tables/vlans.py:137 #: netbox/templates/dcim/interface.html:93 netbox/templates/ipam/vlan.html:66 #: netbox/templates/vpn/l2vpntermination.html:12 @@ -3311,7 +3309,7 @@ msgid "LAG interface (ID)" msgstr "" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "" @@ -3384,7 +3382,7 @@ msgstr "" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3399,98 +3397,99 @@ msgid "" "created.)" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 netbox/dcim/forms/object_import.py:187 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 netbox/dcim/forms/object_import.py:187 #: netbox/dcim/tables/devices.py:96 netbox/dcim/tables/devices.py:172 #: netbox/dcim/tables/devices.py:940 netbox/dcim/tables/devicetypes.py:80 #: netbox/dcim/tables/devicetypes.py:308 netbox/dcim/tables/modules.py:20 -#: netbox/dcim/tables/modules.py:60 netbox/dcim/tables/racks.py:58 +#: netbox/dcim/tables/modules.py:61 netbox/dcim/tables/racks.py:58 #: netbox/dcim/tables/racks.py:132 netbox/templates/dcim/devicetype.html:14 #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3501,10 +3500,10 @@ msgstr "" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3513,60 +3512,60 @@ msgstr "" msgid "Weight" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 netbox/dcim/forms/object_import.py:181 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 netbox/dcim/forms/object_import.py:181 #: netbox/dcim/tables/devices.py:169 netbox/dcim/tables/devices.py:809 #: netbox/dcim/tables/devices.py:937 netbox/dcim/tables/devicetypes.py:304 #: netbox/dcim/tables/racks.py:129 netbox/extras/filtersets.py:552 -#: netbox/ipam/forms/bulk_edit.py:260 netbox/ipam/forms/bulk_edit.py:310 -#: netbox/ipam/forms/bulk_edit.py:358 netbox/ipam/forms/bulk_edit.py:556 +#: netbox/ipam/forms/bulk_edit.py:261 netbox/ipam/forms/bulk_edit.py:311 +#: netbox/ipam/forms/bulk_edit.py:359 netbox/ipam/forms/bulk_edit.py:511 #: netbox/ipam/forms/bulk_import.py:197 netbox/ipam/forms/bulk_import.py:262 -#: netbox/ipam/forms/bulk_import.py:298 netbox/ipam/forms/bulk_import.py:455 +#: netbox/ipam/forms/bulk_import.py:298 netbox/ipam/forms/bulk_import.py:479 #: netbox/ipam/forms/filtersets.py:237 netbox/ipam/forms/filtersets.py:289 #: netbox/ipam/forms/filtersets.py:360 netbox/ipam/forms/filtersets.py:509 #: netbox/ipam/forms/model_forms.py:188 netbox/ipam/forms/model_forms.py:221 -#: netbox/ipam/forms/model_forms.py:250 netbox/ipam/forms/model_forms.py:643 +#: netbox/ipam/forms/model_forms.py:250 netbox/ipam/forms/model_forms.py:676 #: netbox/ipam/tables/ip.py:258 netbox/ipam/tables/ip.py:316 #: netbox/ipam/tables/ip.py:367 netbox/ipam/tables/vlans.py:130 #: netbox/ipam/tables/vlans.py:235 netbox/templates/dcim/device.html:182 @@ -3593,45 +3592,50 @@ msgstr "" msgid "Role" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 netbox/templates/dcim/modulebay.html:70 #: netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3641,62 +3645,62 @@ msgstr "" msgid "Rack" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 -#: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:66 #: netbox/templates/dcim/module.html:65 netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3707,19 +3711,19 @@ msgstr "" msgid "Config template" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3733,14 +3737,36 @@ msgstr "" msgid "Platform" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3750,8 +3776,8 @@ msgstr "" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 netbox/dcim/forms/object_create.py:257 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 netbox/dcim/forms/object_create.py:249 #: netbox/dcim/tables/connections.py:22 netbox/dcim/tables/connections.py:41 #: netbox/dcim/tables/connections.py:60 netbox/dcim/tables/devices.py:285 #: netbox/dcim/tables/devices.py:371 netbox/dcim/tables/devices.py:412 @@ -3759,11 +3785,11 @@ msgstr "" #: netbox/dcim/tables/devices.py:597 netbox/dcim/tables/devices.py:697 #: netbox/dcim/tables/devices.py:754 netbox/dcim/tables/devices.py:801 #: netbox/dcim/tables/devices.py:861 netbox/dcim/tables/devices.py:930 -#: netbox/dcim/tables/devices.py:1057 netbox/dcim/tables/modules.py:52 +#: netbox/dcim/tables/devices.py:1057 netbox/dcim/tables/modules.py:53 #: netbox/extras/forms/filtersets.py:321 netbox/ipam/forms/bulk_import.py:304 -#: netbox/ipam/forms/bulk_import.py:481 netbox/ipam/forms/filtersets.py:551 -#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/forms/model_forms.py:679 -#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:738 +#: netbox/ipam/forms/bulk_import.py:505 netbox/ipam/forms/filtersets.py:551 +#: netbox/ipam/forms/model_forms.py:323 netbox/ipam/forms/model_forms.py:712 +#: netbox/ipam/forms/model_forms.py:745 netbox/ipam/forms/model_forms.py:771 #: netbox/ipam/tables/vlans.py:180 netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3789,7 +3815,7 @@ msgstr "" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3799,23 +3825,28 @@ msgstr "" msgid "Device" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3833,107 +3864,107 @@ msgstr "" msgid "Label" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -3946,17 +3977,17 @@ msgstr "" msgid "Module" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -3965,7 +3996,7 @@ msgstr "" msgid "Speed" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -3979,76 +4010,88 @@ msgstr "" msgid "Mode" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "" @@ -4074,9 +4117,9 @@ msgstr "" msgid "available options" msgstr "" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4098,15 +4141,15 @@ msgstr "" msgid "The lowest-numbered position in the rack" msgstr "" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "" @@ -4118,240 +4161,230 @@ msgstr "" msgid "Name of assigned role" msgstr "" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4359,171 +4392,171 @@ msgstr "" msgid "Assigned VRF" msgstr "" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 netbox/dcim/forms/object_import.py:117 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "" -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "" @@ -4604,10 +4637,6 @@ msgstr "" msgid "Facility" msgstr "" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "" @@ -4644,7 +4673,7 @@ msgid "Has virtual device contexts" msgstr "" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "" @@ -4682,7 +4711,7 @@ msgstr "" msgid "Mgmt only" msgstr "" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4781,36 +4810,45 @@ msgstr "" msgid "Characteristics" msgstr "" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: [ge,xe]-0/0/[0-9]). The token {module}, if present, will be automatically " +"replaced with the position value when creating a new module." +msgstr "" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4833,7 +4871,7 @@ msgstr "" msgid "Interface" msgstr "" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4841,14 +4879,14 @@ msgstr "" msgid "Console Port" msgstr "" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4859,7 +4897,7 @@ msgstr "" msgid "Front Port" msgstr "" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4872,73 +4910,73 @@ msgstr "" msgid "Rear Port" msgstr "" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "" -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "" -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the " "parent device." msgstr "" -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "" #: netbox/dcim/forms/object_create.py:48 netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -4952,12 +4990,12 @@ msgid "" msgstr "" #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" @@ -4968,38 +5006,31 @@ msgid "" "match the selected number of rear port positions ({rearport_count})." msgstr "" -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " "selected number of rear port positions ({rearport_count})." msgstr "" -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." msgstr "" -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "" @@ -5875,12 +5906,12 @@ msgstr "" msgid "rack face" msgstr "" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "" @@ -6038,54 +6069,54 @@ msgid "" "device ({device})." msgstr "" -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "The selected master ({master}) is not assigned to this virtual chassis." msgstr "" -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " "form a cross-chassis LAG interfaces." msgstr "" -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "" -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" @@ -6268,7 +6299,7 @@ msgstr "" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "" @@ -6473,7 +6504,7 @@ msgstr "" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "" @@ -6501,8 +6532,8 @@ msgid "Site Group" msgstr "" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6553,20 +6584,20 @@ msgid "Power outlets" msgstr "" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "" @@ -6586,14 +6617,14 @@ msgstr "" msgid "Inventory items" msgstr "" -#: netbox/dcim/tables/devices.py:305 netbox/dcim/tables/modules.py:56 +#: netbox/dcim/tables/devices.py:305 netbox/dcim/tables/modules.py:57 #: netbox/templates/dcim/modulebay.html:17 msgid "Module Bay" msgstr "" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6622,7 +6653,7 @@ msgstr "" msgid "Allocated draw (W)" msgstr "" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6718,87 +6749,87 @@ msgstr "" msgid "Instances" msgstr "" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "" @@ -6847,7 +6878,7 @@ msgstr "" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 netbox/extras/forms/model_forms.py:517 -#: netbox/ipam/forms/bulk_edit.py:130 netbox/ipam/forms/model_forms.py:153 +#: netbox/ipam/forms/bulk_edit.py:131 netbox/ipam/forms/model_forms.py:153 #: netbox/ipam/tables/asn.py:66 netbox/netbox/navigation/menu.py:15 #: netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -6857,28 +6888,28 @@ msgstr "" msgid "Test case must set peer_termination_type" msgstr "" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "" @@ -6889,35 +6920,35 @@ msgstr "" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "" -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "" -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "" -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "" @@ -7100,7 +7131,6 @@ msgstr "" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -7306,12 +7336,12 @@ msgstr "" msgid "Show your personal bookmarks" msgstr "" -#: netbox/extras/events.py:147 +#: netbox/extras/events.py:151 #, python-brace-format msgid "Unknown action type for an event rule: {action_type}" msgstr "" -#: netbox/extras/events.py:192 +#: netbox/extras/events.py:196 #, python-brace-format msgid "Cannot import events pipeline {name} error: {error}" msgstr "" @@ -7887,19 +7917,19 @@ msgstr "" msgid "Interval at which this script is re-run (in minutes)" msgstr "" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "" -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "" -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "" -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "" @@ -8864,7 +8894,7 @@ msgstr "" msgid "Error deleting widget: " msgstr "" -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "" @@ -8980,129 +9010,129 @@ msgstr "" msgid "Exporting L2VPN (identifier)" msgstr "" -#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:281 +#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:283 #: netbox/ipam/forms/model_forms.py:229 netbox/ipam/tables/ip.py:212 #: netbox/templates/ipam/prefix.html:12 msgid "Prefix" msgstr "" #: netbox/ipam/filtersets.py:159 netbox/ipam/filtersets.py:198 -#: netbox/ipam/filtersets.py:221 +#: netbox/ipam/filtersets.py:223 msgid "RIR (ID)" msgstr "" #: netbox/ipam/filtersets.py:165 netbox/ipam/filtersets.py:204 -#: netbox/ipam/filtersets.py:227 +#: netbox/ipam/filtersets.py:229 msgid "RIR (slug)" msgstr "" -#: netbox/ipam/filtersets.py:285 +#: netbox/ipam/filtersets.py:287 msgid "Within prefix" msgstr "" -#: netbox/ipam/filtersets.py:289 +#: netbox/ipam/filtersets.py:291 msgid "Within and including prefix" msgstr "" -#: netbox/ipam/filtersets.py:293 +#: netbox/ipam/filtersets.py:295 msgid "Prefixes which contain this prefix or IP" msgstr "" -#: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/filtersets.py:306 netbox/ipam/filtersets.py:574 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "" -#: netbox/ipam/filtersets.py:373 netbox/vpn/filtersets.py:427 +#: netbox/ipam/filtersets.py:375 netbox/vpn/filtersets.py:427 msgid "VLAN (ID)" msgstr "" -#: netbox/ipam/filtersets.py:377 netbox/vpn/filtersets.py:422 +#: netbox/ipam/filtersets.py:379 netbox/vpn/filtersets.py:422 msgid "VLAN number (1-4094)" msgstr "" -#: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:473 netbox/ipam/filtersets.py:477 +#: netbox/ipam/filtersets.py:569 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" msgstr "" -#: netbox/ipam/filtersets.py:479 +#: netbox/ipam/filtersets.py:481 msgid "Ranges which contain this prefix or IP" msgstr "" -#: netbox/ipam/filtersets.py:507 netbox/ipam/filtersets.py:563 +#: netbox/ipam/filtersets.py:509 netbox/ipam/filtersets.py:565 msgid "Parent prefix" msgstr "" -#: netbox/ipam/filtersets.py:616 netbox/ipam/filtersets.py:856 -#: netbox/ipam/filtersets.py:1131 netbox/vpn/filtersets.py:385 +#: netbox/ipam/filtersets.py:618 netbox/ipam/filtersets.py:858 +#: netbox/ipam/filtersets.py:1133 netbox/vpn/filtersets.py:385 msgid "Virtual machine (name)" msgstr "" -#: netbox/ipam/filtersets.py:621 netbox/ipam/filtersets.py:861 -#: netbox/ipam/filtersets.py:1125 netbox/virtualization/filtersets.py:282 +#: netbox/ipam/filtersets.py:623 netbox/ipam/filtersets.py:863 +#: netbox/ipam/filtersets.py:1127 netbox/virtualization/filtersets.py:282 #: netbox/virtualization/filtersets.py:321 netbox/vpn/filtersets.py:390 msgid "Virtual machine (ID)" msgstr "" -#: netbox/ipam/filtersets.py:627 netbox/vpn/filtersets.py:97 +#: netbox/ipam/filtersets.py:629 netbox/vpn/filtersets.py:97 #: netbox/vpn/filtersets.py:396 msgid "Interface (name)" msgstr "" -#: netbox/ipam/filtersets.py:638 netbox/vpn/filtersets.py:108 +#: netbox/ipam/filtersets.py:640 netbox/vpn/filtersets.py:108 #: netbox/vpn/filtersets.py:407 msgid "VM interface (name)" msgstr "" -#: netbox/ipam/filtersets.py:643 netbox/vpn/filtersets.py:113 +#: netbox/ipam/filtersets.py:645 netbox/vpn/filtersets.py:113 msgid "VM interface (ID)" msgstr "" -#: netbox/ipam/filtersets.py:648 +#: netbox/ipam/filtersets.py:650 msgid "FHRP group (ID)" msgstr "" -#: netbox/ipam/filtersets.py:652 +#: netbox/ipam/filtersets.py:654 msgid "Is assigned to an interface" msgstr "" -#: netbox/ipam/filtersets.py:656 +#: netbox/ipam/filtersets.py:658 msgid "Is assigned" msgstr "" -#: netbox/ipam/filtersets.py:668 +#: netbox/ipam/filtersets.py:670 msgid "Service (ID)" msgstr "" -#: netbox/ipam/filtersets.py:673 +#: netbox/ipam/filtersets.py:675 msgid "NAT inside IP address (ID)" msgstr "" -#: netbox/ipam/filtersets.py:1041 netbox/ipam/forms/bulk_import.py:322 +#: netbox/ipam/filtersets.py:1043 netbox/ipam/forms/bulk_import.py:322 msgid "Assigned interface" msgstr "" -#: netbox/ipam/filtersets.py:1046 +#: netbox/ipam/filtersets.py:1048 msgid "Assigned VM interface" msgstr "" -#: netbox/ipam/filtersets.py:1136 +#: netbox/ipam/filtersets.py:1138 msgid "IP address (ID)" msgstr "" -#: netbox/ipam/filtersets.py:1142 netbox/ipam/models/ip.py:788 +#: netbox/ipam/filtersets.py:1144 netbox/ipam/models/ip.py:788 msgid "IP address" msgstr "" -#: netbox/ipam/filtersets.py:1167 +#: netbox/ipam/filtersets.py:1169 msgid "Primary IPv4 (ID)" msgstr "" -#: netbox/ipam/filtersets.py:1172 +#: netbox/ipam/filtersets.py:1174 msgid "Primary IPv6 (ID)" msgstr "" @@ -9135,16 +9165,16 @@ msgstr "" msgid "Address pattern" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9158,20 +9188,20 @@ msgstr "" msgid "RIR" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9184,32 +9214,32 @@ msgstr "" msgid "VLAN" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9217,12 +9247,12 @@ msgstr "" msgid "Protocol" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 #: netbox/wireless/forms/bulk_import.py:65 @@ -9233,12 +9263,12 @@ msgstr "" msgid "Authentication type" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 netbox/wireless/forms/bulk_edit.py:149 @@ -9249,26 +9279,26 @@ msgstr "" msgid "Authentication" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9295,8 +9325,8 @@ msgstr "" msgid "Parent device of assigned interface (if any)" msgstr "" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 netbox/virtualization/filtersets.py:288 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 #: netbox/virtualization/forms/bulk_edit.py:326 @@ -9321,39 +9351,59 @@ msgstr "" msgid "Make this the primary IP for the assigned device" msgstr "" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "" @@ -9435,7 +9485,7 @@ msgstr "" msgid "DNS Name" msgstr "" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9446,13 +9496,13 @@ msgstr "" msgid "Contains VLAN ID" msgstr "" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9462,7 +9512,7 @@ msgstr "" #: netbox/virtualization/forms/filtersets.py:242 #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 -#: netbox/virtualization/tables/virtualmachines.py:190 netbox/vpn/choices.py:45 +#: netbox/virtualization/tables/virtualmachines.py:190 netbox/vpn/choices.py:53 #: netbox/vpn/forms/filtersets.py:293 netbox/vpn/forms/model_forms.py:160 #: netbox/vpn/forms/model_forms.py:171 netbox/vpn/forms/model_forms.py:273 #: netbox/vpn/forms/model_forms.py:454 @@ -9491,8 +9541,8 @@ msgstr "" msgid "IP Range" msgstr "" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 netbox/templates/ipam/fhrpgroup.html:19 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "" @@ -9500,74 +9550,86 @@ msgstr "" msgid "Make this the primary IP for the device/VM" msgstr "" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "" -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "" -#: netbox/ipam/forms/model_forms.py:569 netbox/templates/ipam/vlangroup.html:42 +#: netbox/ipam/forms/model_forms.py:602 netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." msgstr "" -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -9838,6 +9900,12 @@ msgstr "" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "" @@ -9887,45 +9955,55 @@ msgstr "" msgid "Cannot set scope_id without scope_type." msgstr "" -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "" -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " "site {site}." msgstr "" -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "" @@ -10677,17 +10755,12 @@ msgstr "" msgid "IPSec Profiles" msgstr "" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "" @@ -10849,7 +10922,7 @@ msgstr "" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11088,19 +11161,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "" @@ -11132,7 +11205,7 @@ msgstr "" msgid "{class_name} must implement get_children()" msgstr "" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11469,9 +11542,7 @@ msgid "Circuit Type" msgstr "" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11482,7 +11553,6 @@ msgstr "" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -11769,35 +11839,35 @@ msgstr "" msgid "Indefinite" msgstr "" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "" @@ -12138,8 +12208,8 @@ msgstr "" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12212,19 +12282,23 @@ msgstr "" msgid "Context Data" msgstr "" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." msgstr "" #: netbox/templates/dcim/device_edit.html:44 @@ -12247,7 +12321,6 @@ msgid "Local Config Context Data" msgstr "" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12292,12 +12365,12 @@ msgid "VM Role" msgstr "" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "" @@ -12436,7 +12509,7 @@ msgstr "" msgid "Wireless Link" msgstr "" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "" @@ -13025,7 +13098,7 @@ msgstr "" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "" @@ -13038,27 +13111,32 @@ msgstr "" msgid "Script no longer exists in the source file." msgstr "" -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "" -#: netbox/templates/extras/script_list.html:138 -msgid "No Scripts Found" +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" msgstr "" #: netbox/templates/extras/script_list.html:141 +msgid "No Scripts Found" +msgstr "" + +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13834,6 +13912,10 @@ msgstr "" msgid "Add Virtual Disk" msgstr "" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -14838,12 +14920,12 @@ msgid "Memory (MB)" msgstr "" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" +msgid "Disk (MB)" msgstr "" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" +msgid "Size (MB)" msgstr "" #: netbox/virtualization/forms/bulk_import.py:44 @@ -15010,68 +15092,80 @@ msgstr "" msgid "virtual disks" msgstr "" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15080,23 +15174,27 @@ msgstr "" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "" diff --git a/netbox/translations/es/LC_MESSAGES/django.mo b/netbox/translations/es/LC_MESSAGES/django.mo index 86fb45730..47dfa187f 100644 Binary files a/netbox/translations/es/LC_MESSAGES/django.mo and b/netbox/translations/es/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/es/LC_MESSAGES/django.po b/netbox/translations/es/LC_MESSAGES/django.po index bacc34b10..7bedaedaa 100644 --- a/netbox/translations/es/LC_MESSAGES/django.po +++ b/netbox/translations/es/LC_MESSAGES/django.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" "Last-Translator: Jeremy Stretch, 2024\n" "Language-Team: Spanish (https://app.transifex.com/netbox-community/teams/178115/es/)\n" @@ -88,8 +88,8 @@ msgstr "La contraseña se ha cambiado correctamente." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -102,7 +102,7 @@ msgstr "Aprovisionamiento" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -113,8 +113,8 @@ msgid "Active" msgstr "Activo" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Desconectado" @@ -127,7 +127,7 @@ msgstr "Desaprovisionamiento" msgid "Decommissioned" msgstr "Desmantelado" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Primaria" @@ -200,12 +200,12 @@ msgstr "Grupo de sitios (slug)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -214,18 +214,17 @@ msgstr "Grupo de sitios (slug)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -333,10 +332,10 @@ msgstr "Terminación A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -388,7 +387,7 @@ msgstr "Grupo de circuitos (slug)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -403,33 +402,33 @@ msgstr "ASNs" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -438,7 +437,7 @@ msgstr "ASNs" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -453,7 +452,7 @@ msgstr "ASNs" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -473,7 +472,7 @@ msgstr "ASNs" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -566,10 +565,10 @@ msgid "Service ID" msgstr "ID de servicio" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -590,16 +589,16 @@ msgstr "Color" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -654,14 +653,14 @@ msgstr "Cuenta de proveedor" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -670,13 +669,13 @@ msgstr "Cuenta de proveedor" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -687,7 +686,7 @@ msgstr "Cuenta de proveedor" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -723,30 +722,30 @@ msgstr "Estado" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -816,11 +815,11 @@ msgstr "Parámetros de servicio" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -852,11 +851,11 @@ msgstr "Velocidad del puerto (Kbps)" msgid "Upstream speed (Kbps)" msgstr "Velocidad de subida (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Marcar conectado" @@ -903,10 +902,10 @@ msgstr "Tipo de circuito" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -916,13 +915,13 @@ msgstr "Estado operativo" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -947,12 +946,12 @@ msgstr "Red de proveedores" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -969,9 +968,9 @@ msgstr "Red de proveedores" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1000,8 +999,8 @@ msgid "Contacts" msgstr "Contactos" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1009,13 +1008,12 @@ msgstr "Contactos" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1028,16 +1026,16 @@ msgid "Region" msgstr "Región" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1049,7 +1047,7 @@ msgstr "Grupo de sitios" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1088,9 +1086,9 @@ msgstr "Cuenta" msgid "Term Side" msgstr "Lado del término" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1100,11 +1098,11 @@ msgstr "Asignación" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1176,20 +1174,20 @@ msgid "Unique circuit ID" msgstr "ID de circuito único" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "estado" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "instalada" @@ -1311,11 +1309,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1326,7 +1324,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1414,7 +1412,7 @@ msgstr "redes de proveedores" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1425,7 +1423,7 @@ msgstr "redes de proveedores" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1456,7 +1454,7 @@ msgstr "redes de proveedores" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1620,7 +1618,7 @@ msgstr "Completado" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Falló" @@ -1687,7 +1685,7 @@ msgid "Cancelled" msgstr "Cancelado" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Local" @@ -1774,8 +1772,8 @@ msgid "User name" msgstr "Nombre de usuario" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1879,7 +1877,7 @@ msgid "Completed before" msgstr "Completado antes" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1946,9 +1944,9 @@ msgstr "" msgid "Rack Elevations" msgstr "Elevaciones de estanterías" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Potencia" @@ -2049,7 +2047,7 @@ msgstr "" "El registro de cambios no es compatible con este tipo de objeto ({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2109,7 +2107,7 @@ msgstr "tipo" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2230,60 +2228,60 @@ msgstr "archivo gestionado" msgid "managed files" msgstr "archivos gestionados" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "programado" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "intervalo" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Intervalo de recurrencia (en minutos)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "iniciado" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "completado" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "dato" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "error" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "ID de trabajo" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "trabajo" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "trabajos" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "No se pueden asignar trabajos a este tipo de objeto ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "" "Estado no válido para la terminación del trabajo. Las opciones son: " "{choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" @@ -2368,7 +2366,7 @@ msgstr "Versión máxima de NetBox" msgid "No plugin data found" msgstr "No se han encontrado datos de complementos" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "autor" @@ -2376,7 +2374,7 @@ msgstr "autor" msgid "Installed" msgstr "Instalado" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Certificado" @@ -2502,11 +2500,11 @@ msgstr "Trabajo {id} se ha detenido." msgid "Failed to stop job {id}" msgstr "No se pudo detener el trabajo {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "No se pudo cargar el catálogo de complementos" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Plugin {name} no se encontró" @@ -2526,7 +2524,7 @@ msgid "Staging" msgstr "Puesta en escena" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Desmantelamiento" @@ -2590,7 +2588,7 @@ msgstr "Obsoleto" msgid "Millimeters" msgstr "Milímetros" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "Pulgadas" @@ -2604,15 +2602,15 @@ msgstr "De adelante hacia atrás" msgid "Rear to front" msgstr "De atrás hacia adelante" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2692,7 +2690,7 @@ msgid "Top to bottom" msgstr "De arriba a abajo" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Pasivo" @@ -2721,8 +2719,8 @@ msgid "Proprietary" msgstr "Proprietario" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Otros" @@ -2735,24 +2733,24 @@ msgstr "ITA/Internacional" msgid "Physical" msgstr "Físico" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Virtual" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "inalámbrico" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Interfaces virtuales" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2761,27 +2759,27 @@ msgstr "Interfaces virtuales" msgid "Bridge" msgstr "puente" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Grupo de agregación de enlaces (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (fijo)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (modular)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (placa base)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Celular" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2789,130 +2787,130 @@ msgstr "Celular" msgid "Serial" msgstr "serie" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Coaxial" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "Apilamiento" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Mitad" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Lleno" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Auto" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Acceso" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Etiquetado" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Etiquetado (Todos)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "Estándar IEEE" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "Pasivo 24 V (2 pares)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "Pasivo de 24 V (4 pares)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "Pasivo 48 V (2 pares)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "Pasivo de 48 V (4 pares)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Cobre" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Fibra óptica" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Fibra" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Conectado" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Kilómetros" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Medidores" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Centímetros" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Millas" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Pies" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Kilogramos" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Gramos" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "Libras" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Onzas" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Redundante" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Monofásico" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Trifásico" @@ -3158,7 +3156,7 @@ msgstr "Grupo de clústeres (ID)" msgid "Device model (slug)" msgstr "Modelo de dispositivo (slug)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "Es de profundidad total" @@ -3280,21 +3278,21 @@ msgstr "VLAN asignada" msgid "Assigned VID" msgstr "VID asignado" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3361,7 +3359,7 @@ msgid "LAG interface (ID)" msgstr "Interfaz LAG (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Contexto de dispositivo virtual" @@ -3435,7 +3433,7 @@ msgstr "Etiquetas" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3452,38 +3450,38 @@ msgstr "" "Se admiten los rangos alfanuméricos. (Debe coincidir con el número de " "nombres que se están creando)." -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Nombre de contacto" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Teléfono de contacto" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "Correo electrónico de contacto" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Zona horaria" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3493,58 +3491,59 @@ msgstr "Zona horaria" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "fabricante" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Factor de forma" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Anchura" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Altura (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Unidades descendentes" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Anchura exterior" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Profundidad exterior" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Unidad exterior" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Profundidad de montaje" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3555,10 +3554,10 @@ msgstr "Profundidad de montaje" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3567,61 +3566,61 @@ msgstr "Profundidad de montaje" msgid "Weight" msgstr "Peso" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Peso máximo" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Unidad de peso" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Tipo de bastidor" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Dimensiones exteriores" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Dimensiones" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Numeración" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3649,45 +3648,50 @@ msgstr "Numeración" msgid "Role" msgstr "Rol" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Tipo de bastidor" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Número de serie" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Etiqueta de activo" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Flujo de aire" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3697,64 +3701,64 @@ msgstr "Flujo de aire" msgid "Rack" msgstr "Estante" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Hardware" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Plataforma predeterminada" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Número de pieza" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "Altura en U" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Excluir de la utilización" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Tipo de dispositivo" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Tipo de módulo" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Chasis" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "Función de máquina virtual" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3765,19 +3769,19 @@ msgstr "Función de máquina virtual" msgid "Config template" msgstr "Plantilla de configuración" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Tipo de dispositivo" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Función del dispositivo" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3791,14 +3795,36 @@ msgstr "Función del dispositivo" msgid "Platform" msgstr "Plataforma" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Clúster" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3808,9 +3834,9 @@ msgstr "Plataforma" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3819,10 +3845,10 @@ msgstr "Plataforma" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3849,7 +3875,7 @@ msgstr "Plataforma" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3859,23 +3885,28 @@ msgstr "Plataforma" msgid "Device" msgstr "Dispositivo" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Configuración" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Virtualización" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Tipo de módulo" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3893,109 +3924,109 @@ msgstr "Tipo de módulo" msgid "Label" msgstr "Etiqueta" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Longitud" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Unidad de longitud" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Dominio" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "Panel de alimentación" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Suministro" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Fase" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Tensión" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Amperaje" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Utilización máxima" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Sorteo máximo" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Consumo máximo de energía (vatios)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Sorteo asignado" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Consumo de energía asignado (vatios)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Puerto de alimentación" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Pierna de alimentación" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Solo administración" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "Modo PoE" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "Tipo de PoE" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Función inalámbrica" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4009,17 +4040,17 @@ msgstr "Función inalámbrica" msgid "Module" msgstr "Módulo" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "DESFASE" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Contextos de dispositivos virtuales" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4028,7 +4059,7 @@ msgstr "Contextos de dispositivos virtuales" msgid "Speed" msgstr "Velocidad" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4042,76 +4073,88 @@ msgstr "Velocidad" msgid "Mode" msgstr "Modo" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "Grupo de VLAN" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "VLAN sin etiquetar" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "VLAN etiquetadas" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Grupo LAN inalámbrico" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "LAN inalámbricas" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Dirigiéndose" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Operación" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Interfaces relacionadas" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "Conmutación 802.1Q" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "Se debe especificar el modo de interfaz para asignar las VLAN" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "Una interfaz de acceso no puede tener asignadas VLAN etiquetadas." @@ -4137,9 +4180,9 @@ msgstr "Grupo asignado" msgid "available options" msgstr "opciones disponibles" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4161,15 +4204,15 @@ msgstr "El fabricante de este tipo de bastidor" msgid "The lowest-numbered position in the rack" msgstr "La posición con el número más bajo del estante" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Ancho de raíl a raíl (en pulgadas)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Unidad para dimensiones exteriores" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Unidad para pesas de cremallera" @@ -4181,159 +4224,149 @@ msgstr "Nombre del inquilino asignado" msgid "Name of assigned role" msgstr "Nombre de la función asignada" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Dirección del flujo de aire" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Sitio para padres" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Ubicación del bastidor (si existe)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Unidades" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Lista separada por comas de números de unidades individuales" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "El fabricante que produce este tipo de dispositivo" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "" "La plataforma predeterminada para dispositivos de este tipo (opcional)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Peso del dispositivo" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Unidad para el peso del dispositivo" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Peso del módulo" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Unidad para el peso del módulo" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Limite las asignaciones de plataforma a este fabricante" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Función asignada" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Fabricante del tipo de dispositivo" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Modelo de tipo de dispositivo" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Plataforma asignada" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Chasis virtual" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Clúster" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Clúster de virtualización" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Ubicación asignada (si la hay)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Bastidor asignado (si lo hay)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Cara" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Cara de bastidor montada" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Dispositivo principal (para dispositivos infantiles)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Compartimento para dispositivos" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" "Compartimento de dispositivos en el que está instalado este dispositivo " "(para dispositivos infantiles)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "El dispositivo en el que está instalado este módulo" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Compartimento de módulos" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "El compartimiento del módulo en el que está instalado este módulo" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "El tipo de módulo" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Replicar componentes" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4341,87 +4374,87 @@ msgstr "" "Rellenar automáticamente los componentes asociados a este tipo de módulo " "(activado de forma predeterminada)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Adopte componentes" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Adopte los componentes ya existentes" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Tipo de puerto" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Velocidad de puerto en bps" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Tipo de toma" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Puerto de alimentación local que alimenta esta toma" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Fase eléctrica (para circuitos trifásicos)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Interfaz principal" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Interfaz puenteada" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Retraso" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Interfaz LAG principal" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "VDC" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" "Los nombres de los VDC están separados por comas y entre comillas dobles. " "Ejemplo:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Medio físico" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Dúplex" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "Modo Poe" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Tipo de Poe" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "Modo operativo IEEE 802.1Q (para interfaces L2)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4429,172 +4462,172 @@ msgstr "Modo operativo IEEE 802.1Q (para interfaces L2)" msgid "Assigned VRF" msgstr "VRF asignado" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Rol RF" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Función inalámbrica (AP/estación)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} no está asignado al dispositivo {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Puerto trasero" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Puerto trasero correspondiente" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Clasificación de medios físicos" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Dispositivo instalado" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "Dispositivo infantil instalado en esta bahía" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "No se encontró el dispositivo infantil." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Artículo del inventario principal" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Tipo de componente" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Tipo de componente" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Nombre del componente" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Nombre del componente" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "No se encontró el componente: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Dispositivo del lado A" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Nombre del dispositivo" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Tipo de lado A" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Tipo de terminación" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Nombre de la cara A" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Nombre de terminación" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Dispositivo Side B" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Tipo de lado B" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Nombre de la cara B" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Estado de conexión" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "Lado {side_upper}: {device} {termination_object} ya está conectado" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} no se encontró la terminación lateral: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Maestro" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Dispositivo maestro" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Nombre del sitio principal" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "Panel de alimentación ascendente" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Primario o redundante" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Tipo de alimentación (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Monofásico o trifásico" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "IPv4 principal" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "Dirección IPv4 con máscara, p. ej. 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "IPv6 principal" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "Dirección IPv6 con longitud de prefijo, por ejemplo, 2001:db8: :1/64" @@ -4682,10 +4715,6 @@ msgstr "Grupo de padres" msgid "Facility" msgstr "Instalación" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Tipo de bastidor" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Función" @@ -4722,7 +4751,7 @@ msgid "Has virtual device contexts" msgstr "Tiene contextos de dispositivos virtuales" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Grupo de clústeres" @@ -4761,7 +4790,7 @@ msgstr "Amable" msgid "Mgmt only" msgstr "Solo administración" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4867,36 +4896,46 @@ msgstr "" msgid "Characteristics" msgstr "Características" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Plantilla de puerto de consola" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Plantilla de puerto de servidor de consola" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Plantilla de puerto frontal" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Plantilla de interfaz" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Plantilla de toma de corriente" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Plantilla de puerto de alimentación" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Plantilla de puerto trasero" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4920,7 +4959,7 @@ msgstr "Plantilla de puerto trasero" msgid "Interface" msgstr "Interfaz" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4928,14 +4967,14 @@ msgstr "Interfaz" msgid "Console Port" msgstr "Puerto de consola" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Puerto de servidor de consola" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4946,7 +4985,7 @@ msgstr "Puerto de servidor de consola" msgid "Front Port" msgstr "Puerto frontal" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4959,40 +4998,40 @@ msgstr "Puerto frontal" msgid "Rear Port" msgstr "Puerto trasero" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Puerto de alimentación" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Toma de corriente" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Asignación de componentes" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "Un InventoryItem solo se puede asignar a un único componente." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "Interfaz LAG" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Filtre las VLAN disponibles para la asignación por grupo." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Dispositivo infantil" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -5000,35 +5039,35 @@ msgstr "" "Los dispositivos secundarios primero deben crearse y asignarse al sitio y al" " rack del dispositivo principal." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Puerto de consola" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Puerto de servidor de consola" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Puerto frontal" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "toma de corriente" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Artículo de inventario" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Función del artículo de inventario" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5046,12 +5085,12 @@ msgstr "" "{pattern_count} se esperan." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Puertos traseros" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" "Seleccione una asignación de puerto posterior para cada puerto frontal que " @@ -5067,16 +5106,7 @@ msgstr "" "({frontport_count}) debe coincidir con el número seleccionado de posiciones " "de los puertos traseros ({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"La cadena {module} se sustituirá por la posición del módulo " -"asignado, si lo hubiera." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5086,18 +5116,18 @@ msgstr "" "coincidir con el número seleccionado de posiciones de los puertos traseros " "({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Miembros" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Posición inicial" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." @@ -5105,7 +5135,7 @@ msgstr "" "Posición del primer dispositivo miembro. Aumenta en uno por cada miembro " "adicional." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "Se debe especificar un puesto para el primer miembro del VC." @@ -6059,12 +6089,12 @@ msgstr "posición (U)" msgid "rack face" msgstr "cara del estante" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "IPv4 principal" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "IPv6 principal" @@ -6244,22 +6274,22 @@ msgstr "" "El módulo debe instalarse en un compartimiento de módulos que pertenezca al " "dispositivo asignado ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "dominio" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "chasis virtual" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "" "El maestro seleccionado ({master}) no está asignado a este chasis virtual." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6268,34 +6298,34 @@ msgstr "" "No se puede eliminar el chasis virtual {self}. Hay interfaces miembros que " "forman interfaces LAG entre chasis." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "identificador" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Identificador numérico exclusivo del dispositivo principal" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "comentarios" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "contexto de dispositivo virtual" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "contextos de dispositivos virtuales" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} no es un IPv{family} dirección." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" "La dirección IP principal debe pertenecer a una interfaz del dispositivo " @@ -6489,7 +6519,7 @@ msgstr "Identificador asignado localmente" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Función funcional" @@ -6700,7 +6730,7 @@ msgstr "Accesible" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Dispositivos" @@ -6729,8 +6759,8 @@ msgid "Site Group" msgstr "Grupo de sitios" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6781,20 +6811,20 @@ msgid "Power outlets" msgstr "tomas de corriente" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Interfaces" @@ -6820,8 +6850,8 @@ msgid "Module Bay" msgstr "Bahía de módulos" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6850,7 +6880,7 @@ msgstr "Consumo máximo (W)" msgid "Allocated draw (W)" msgstr "Sorteo asignado (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6946,87 +6976,87 @@ msgstr "Altura en U" msgid "Instances" msgstr "Instancias" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Puertos de consola" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Puertos de servidor de consola" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Puertos de alimentación" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Tomas de corriente" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Puertos frontales" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Puertos traseros" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Bahías de dispositivos" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Bahías de módulos" @@ -7075,7 +7105,7 @@ msgstr "Espacio" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7085,28 +7115,28 @@ msgstr "Sitios" msgid "Test case must set peer_termination_type" msgstr "El caso de prueba debe establecer peer_termination_type" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Desconectado {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Reservaciones" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Dispositivos no rakeados" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Contexto de configuración" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Configuración de renderizado" @@ -7117,37 +7147,37 @@ msgstr "Se ha producido un error al renderizar la plantilla: {error}" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Máquinas virtuales" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Dispositivo instalado {device} en la bahía {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Dispositivo eliminado {device} desde la bahía {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Niños" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Miembro agregado {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "" "No se puede eliminar el dispositivo maestro {device} desde el chasis " "virtual." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "Eliminado {device} desde un chasis virtual {chassis}" @@ -7330,7 +7360,6 @@ msgstr "Actualización" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -8166,19 +8195,19 @@ msgstr "Programe la ejecución del script a una hora determinada" msgid "Interval at which this script is re-run (in minutes)" msgstr "Intervalo en el que se vuelve a ejecutar este script (en minutos)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "Los cambios en la base de datos se han revertido automáticamente." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Secuencia de comandos abortada con un error: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Se ha producido una excepción: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "Los cambios en la base de datos se han revertido debido a un error." @@ -9219,7 +9248,7 @@ msgstr "Widget eliminado: " msgid "Error deleting widget: " msgstr "Error al eliminar el widget: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "" "No se puede ejecutar el script: el proceso de trabajo de RQ no se está " @@ -9368,7 +9397,7 @@ msgid "Prefixes which contain this prefix or IP" msgstr "Prefijos que contienen este prefijo o IP" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Longitud de la máscara" @@ -9382,7 +9411,7 @@ msgid "VLAN number (1-4094)" msgstr "Número de VLAN (1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9494,16 +9523,16 @@ msgstr "Se requiere una máscara CIDR (por ejemplo, /24)." msgid "Address pattern" msgstr "Patrón de direcciones" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Haga valer un espacio único" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "Es privado" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9517,20 +9546,20 @@ msgstr "Es privado" msgid "RIR" msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Fecha añadida" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "Grupo VLAN" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9543,32 +9572,32 @@ msgstr "Grupo VLAN" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Longitud del prefijo" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "Es una piscina" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Tratar como si se hubiera utilizado por completo" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "Asignación de VLAN" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "Nombre DNS" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9576,12 +9605,12 @@ msgstr "Nombre DNS" msgid "Protocol" msgstr "Protocolo" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "ID de grupo" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9593,12 +9622,12 @@ msgstr "ID de grupo" msgid "Authentication type" msgstr "Tipo de autenticación" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Clave de autenticación" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9610,26 +9639,26 @@ msgstr "Clave de autenticación" msgid "Authentication" msgstr "AUTENTICACIÓN" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Tipo de ámbito" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "Intervalos de ID de VLAN" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Alcance" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "Intervalos de ID de VLAN" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Sitio y grupo" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9656,8 +9685,8 @@ msgstr "Grupo de VLAN (si lo hay)" msgid "Parent device of assigned interface (if any)" msgstr "Dispositivo principal de la interfaz asignada (si existe)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9683,42 +9712,62 @@ msgstr "Es primaria" msgid "Make this the primary IP for the assigned device" msgstr "Conviértase en la IP principal del dispositivo asignado" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "No se especificó ningún dispositivo o máquina virtual; no se puede " "establecer como IP principal" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "" "No se especificó ninguna interfaz; no se puede establecer como IP principal" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Tipo de autenticación" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Tipo de ámbito (aplicación y modelo)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Grupo de VLAN asignado" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "Protocolo IP" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Obligatorio si no está asignado a una VM" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Obligatorio si no está asignado a un dispositivo" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} no está asignado a este dispositivo/máquina virtual." @@ -9800,7 +9849,7 @@ msgstr "Asignado a una interfaz" msgid "DNS Name" msgstr "Nombre DNS" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9811,13 +9860,13 @@ msgstr "VLAN" msgid "Contains VLAN ID" msgstr "Contiene el identificador de VLAN" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "IDENTIFICADOR DE VLAN" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9828,7 +9877,7 @@ msgstr "IDENTIFICADOR DE VLAN" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9857,8 +9906,8 @@ msgstr "Asignación de sitio/VLAN" msgid "IP Range" msgstr "Rango de IP" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "Grupo FHRP" @@ -9867,47 +9916,57 @@ msgstr "Grupo FHRP" msgid "Make this the primary IP for the device/VM" msgstr "Haga que esta sea la IP principal del dispositivo/VM" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "NAT IP (interior)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "Solo se puede asignar una dirección IP a un único objeto." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"No se puede reasignar la dirección IP mientras esté designada como la IP " -"principal del objeto principal" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "Solo las direcciones IP asignadas a una interfaz se pueden designar como IP " "principales." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Dirección IP virtual" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "La asignación ya existe" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "ID de VLAN" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "VLAN secundarias" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9915,33 +9974,33 @@ msgstr "" "Lista separada por comas de uno o más números de puerto. Se puede " "especificar un rango mediante un guión." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Plantilla de servicio" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Puerto (s)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Servicio" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Plantilla de servicio" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "Desde plantilla" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Personalizado" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10226,6 +10285,14 @@ msgstr "" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Se encontró una dirección IP duplicada en {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"No se puede reasignar la dirección IP mientras esté designada como la IP " +"principal del objeto principal" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Solo a las direcciones IPv6 se les puede asignar el estado SLAAC" @@ -10281,40 +10348,48 @@ msgstr "No se puede establecer scope_type sin scope_id." msgid "Cannot set scope_id without scope_type." msgstr "No se puede establecer scope_id sin scope_type." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Los rangos no se pueden superponer." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"El VID infantil máximo debe ser mayor o igual al VID infantil mínimo " -"({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "El sitio específico al que está asignada esta VLAN (si existe)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "Grupo de VLAN (opcional)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "ID de VLAN numérico (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Estado operativo de esta VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "La función principal de esta VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10323,7 +10398,7 @@ msgstr "" "La VLAN está asignada al grupo {group} (alcance: {scope}); no se puede " "asignar también al sitio {site}." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "El VID debe estar en rangos {ranges} para VLAN en grupo {group}" @@ -11096,17 +11171,12 @@ msgstr "Políticas IPSec" msgid "IPSec Profiles" msgstr "Perfiles IPSec" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Virtualización" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Discos virtuales" @@ -11268,7 +11338,7 @@ msgstr "Sistema" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11516,19 +11586,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Fila {i}: Objeto con ID {id} no existe" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "No {object_type} fueron seleccionados." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Renombrado {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Eliminado {count} {object_type}" @@ -11562,7 +11632,7 @@ msgstr "Sincronizado {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} debe implementar get_children ()" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11908,9 +11978,7 @@ msgid "Circuit Type" msgstr "Tipo de circuito" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11921,7 +11989,6 @@ msgstr "Añadir" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12211,35 +12278,35 @@ msgstr "días" msgid "Indefinite" msgstr "Indefinido" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "No instalado" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Visión general" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Instalar" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Detalles del plugin" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Resumen" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Licencia" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Historial de versiones" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Instrucciones de instalación local" @@ -12585,8 +12652,8 @@ msgstr "Añadir un servicio" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12659,20 +12726,24 @@ msgstr "Configuración" msgid "Context Data" msgstr "Datos de contexto" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Configuración renderizada" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Descargar" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "No se encontró ninguna plantilla de configuración" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12694,7 +12765,6 @@ msgid "Local Config Context Data" msgstr "Datos de contexto de configuración local" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12741,12 +12811,12 @@ msgid "VM Role" msgstr "Función de máquina virtual" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Nombre del modelo" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Número de pieza" @@ -12885,7 +12955,7 @@ msgstr "Dirección MAC" msgid "Wireless Link" msgstr "Enlace inalámbrico" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Par" @@ -13510,7 +13580,7 @@ msgstr "No tiene permiso para ejecutar scripts" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Ejecutar script" @@ -13523,27 +13593,32 @@ msgstr "Error al cargar el script" msgid "Script no longer exists in the source file." msgstr "El script ya no existe en el archivo fuente." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Última ejecución" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "La secuencia de comandos ya no está presente en el archivo fuente" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Nunca" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Corre otra vez" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "No se encontró ningún script" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13865,7 +13940,7 @@ msgstr "Todas las notificaciones" msgid "Select" msgstr "Seleccione" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Restablecer" @@ -14350,6 +14425,10 @@ msgstr "Recursos" msgid "Add Virtual Disk" msgstr "Agregar disco virtual" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15435,13 +15514,13 @@ msgid "Memory (MB)" msgstr "Memoria (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Disco (GB)" +msgid "Disk (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Tamaño (GB)" +msgid "Size (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15628,68 +15707,80 @@ msgstr "disco virtual" msgid "virtual disks" msgstr "discos virtuales" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Añadido {count} dispositivos para agrupar {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Eliminado {count} dispositivos del clúster {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPSec - Transporte" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPSec - Túnel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP en IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GRIS" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Hub" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "Habló" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Agresivo" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Principal" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Claves previamente compartidas" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Certificados" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "Firmas RSA" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "Firmas de la DSA" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15698,23 +15789,27 @@ msgstr "Firmas de la DSA" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Grupo {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "LAN privada Ethernet" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "LAN privada virtual Ethernet" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Árbol privado de Ethernet" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Árbol privado virtual de Ethernet" diff --git a/netbox/translations/fr/LC_MESSAGES/django.mo b/netbox/translations/fr/LC_MESSAGES/django.mo index bf80d8fca..b7f504a16 100644 Binary files a/netbox/translations/fr/LC_MESSAGES/django.mo and b/netbox/translations/fr/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/fr/LC_MESSAGES/django.po b/netbox/translations/fr/LC_MESSAGES/django.po index 25b02e3a4..6abecb68b 100644 --- a/netbox/translations/fr/LC_MESSAGES/django.po +++ b/netbox/translations/fr/LC_MESSAGES/django.po @@ -18,7 +18,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" "Last-Translator: Jeremy Stretch, 2024\n" "Language-Team: French (https://app.transifex.com/netbox-community/teams/178115/fr/)\n" @@ -95,8 +95,8 @@ msgstr "Votre mot de passe a été modifié avec succès." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -109,7 +109,7 @@ msgstr "Approvisionnement" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -120,8 +120,8 @@ msgid "Active" msgstr "Actif" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Hors ligne" @@ -134,7 +134,7 @@ msgstr "Déprovisionnement" msgid "Decommissioned" msgstr "Mis hors service" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Primaire" @@ -207,12 +207,12 @@ msgstr "Groupe de sites (slug)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -221,18 +221,17 @@ msgstr "Groupe de sites (slug)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -340,10 +339,10 @@ msgstr "Terminaison A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -395,7 +394,7 @@ msgstr "Groupe de circuits (slug)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -410,33 +409,33 @@ msgstr "Numéros d'AS" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -445,7 +444,7 @@ msgstr "Numéros d'AS" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -460,7 +459,7 @@ msgstr "Numéros d'AS" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -480,7 +479,7 @@ msgstr "Numéros d'AS" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -573,10 +572,10 @@ msgid "Service ID" msgstr "Identifiant du service" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -597,16 +596,16 @@ msgstr "Couleur" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -661,14 +660,14 @@ msgstr "Identifiant de compte du prestataire" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -677,13 +676,13 @@ msgstr "Identifiant de compte du prestataire" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -694,7 +693,7 @@ msgstr "Identifiant de compte du prestataire" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -730,30 +729,30 @@ msgstr "Statut" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -823,11 +822,11 @@ msgstr "Paramètres du service" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -859,11 +858,11 @@ msgstr "Vitesse du port (Kbits/s)" msgid "Upstream speed (Kbps)" msgstr "Vitesse ascendante (Kbits/s)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Marquer comme connecté" @@ -910,10 +909,10 @@ msgstr "Type de circuit" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -923,13 +922,13 @@ msgstr "État opérationnel" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -954,12 +953,12 @@ msgstr "Réseau de fournisseurs" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -976,9 +975,9 @@ msgstr "Réseau de fournisseurs" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1007,8 +1006,8 @@ msgid "Contacts" msgstr "Contacts" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1016,13 +1015,12 @@ msgstr "Contacts" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1035,16 +1033,16 @@ msgid "Region" msgstr "Région" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1056,7 +1054,7 @@ msgstr "Groupe de sites" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1095,9 +1093,9 @@ msgstr "Compte" msgid "Term Side" msgstr "Côté terme" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1107,11 +1105,11 @@ msgstr "Affectation" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1183,20 +1181,20 @@ msgid "Unique circuit ID" msgstr "ID de circuit unique" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "statut" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "installé" @@ -1318,11 +1316,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1333,7 +1331,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1421,7 +1419,7 @@ msgstr "réseaux de fournisseurs" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1432,7 +1430,7 @@ msgstr "réseaux de fournisseurs" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1463,7 +1461,7 @@ msgstr "réseaux de fournisseurs" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1628,7 +1626,7 @@ msgstr "Terminé" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Échoué" @@ -1695,7 +1693,7 @@ msgid "Cancelled" msgstr "Annulé" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Local" @@ -1782,8 +1780,8 @@ msgid "User name" msgstr "Nom d'utilisateur" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1887,7 +1885,7 @@ msgid "Completed before" msgstr "Terminé avant" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1956,9 +1954,9 @@ msgstr "" msgid "Rack Elevations" msgstr "Élévations des baies" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Puissance" @@ -2061,7 +2059,7 @@ msgstr "" "d'objet ({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2121,7 +2119,7 @@ msgstr "type" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2243,60 +2241,60 @@ msgstr "fichier géré" msgid "managed files" msgstr "fichiers gérés" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "prévu" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "intervalle" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Intervalle de récurrence (en minutes)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "commencé" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "terminé" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "données" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "erreur" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "ID de tâche" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "emploi" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "emplois" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "Les tâches ne peuvent pas être attribuées à ce type d'objet ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "" "Statut invalide pour l'arrêt de la tâche. Les choix sont les suivants : " "{choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" @@ -2381,7 +2379,7 @@ msgstr "Version maximale de NetBox" msgid "No plugin data found" msgstr "Aucune donnée de plug-in trouvée" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Auteur" @@ -2389,7 +2387,7 @@ msgstr "Auteur" msgid "Installed" msgstr "Installé" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Certifié" @@ -2515,11 +2513,11 @@ msgstr "Poste {id} a été arrêté." msgid "Failed to stop job {id}" msgstr "Impossible d'arrêter la tâche {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "Le catalogue des plugins n'a pas pu être chargé" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Plug-in {name} introuvable" @@ -2539,7 +2537,7 @@ msgid "Staging" msgstr "Mise en scène" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Démantèlement" @@ -2603,7 +2601,7 @@ msgstr "Obsolète" msgid "Millimeters" msgstr "Millimètres" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "Pouces" @@ -2617,15 +2615,15 @@ msgstr "De l'avant vers l'arrière" msgid "Rear to front" msgstr "De l'arrière vers l'avant" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2705,7 +2703,7 @@ msgid "Top to bottom" msgstr "De haut en bas" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Passif" @@ -2734,8 +2732,8 @@ msgid "Proprietary" msgstr "Propriétaire" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Autres" @@ -2748,24 +2746,24 @@ msgstr "ITA/International" msgid "Physical" msgstr "Physique" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Virtuel" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Sans fil" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Interfaces virtuelles" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2774,27 +2772,27 @@ msgstr "Interfaces virtuelles" msgid "Bridge" msgstr "Passerelle" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Groupe d'agrégation de liens (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (fixe)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (modulaire)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (panneau arrière)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Cellulaire" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2802,130 +2800,130 @@ msgstr "Cellulaire" msgid "Serial" msgstr "Série" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Coaxiale" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "Empilage" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "La moitié" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Complet" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Automatique" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Accès" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Tagué" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Tagué (Tous)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "Norme IEEE" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "24 V passif (2 paires)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "24 V passif (4 paires)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "48 V passif (2 paires)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "48 V passif (4 paires)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Cuivre" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "fibre optique" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Fibre" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Connecté" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Kilomètres" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Compteurs" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Centimètres" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Miles" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Pieds" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Kilogrammes" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Grammes" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "Livres" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Onces" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Redondant" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Monophasé" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Triphasé" @@ -3171,7 +3169,7 @@ msgstr "Groupe de clusters (ID)" msgid "Device model (slug)" msgstr "Modèle d'appareil (slug)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "Est en pleine profondeur" @@ -3293,21 +3291,21 @@ msgstr "VLAN attribué" msgid "Assigned VID" msgstr "VID attribué" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3374,7 +3372,7 @@ msgid "LAG interface (ID)" msgstr "Interface LAG (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Contexte du périphérique virtuel" @@ -3448,7 +3446,7 @@ msgstr "Balises" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3465,38 +3463,38 @@ msgstr "" "Les plages alphanumériques sont prises en charge. (Doit correspondre au " "nombre de noms en cours de création.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Nom du contact" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Téléphone de contact" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "Adresse électronique de contact" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Fuseau horaire" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3506,58 +3504,59 @@ msgstr "Fuseau horaire" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Fabricant" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Facteur de forme" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Largeur" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Hauteur (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Unités décroissantes" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Largeur extérieure" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Profondeur extérieure" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Unité extérieure" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Profondeur de montage" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3568,10 +3567,10 @@ msgstr "Profondeur de montage" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3580,61 +3579,61 @@ msgstr "Profondeur de montage" msgid "Weight" msgstr "Poids" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Poids maximum" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Unité de poids" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Type de rack" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Dimensions extérieures" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Dimensions" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Numérotation" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3662,45 +3661,50 @@ msgstr "Numérotation" msgid "Role" msgstr "Rôle" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Type de baie" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Numéro de série" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Étiquette d'actif" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Débit d'air" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3710,64 +3714,64 @@ msgstr "Débit d'air" msgid "Rack" msgstr "Baie" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Matériel" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Plateforme par défaut" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Numéro de pièce" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "Hauteur en U" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Exclure de l'utilisation" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Type d'appareil" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Type de module" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Châssis" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "rôle de machine virtuelle" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3778,19 +3782,19 @@ msgstr "rôle de machine virtuelle" msgid "Config template" msgstr "Modèle de configuration" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Type d'appareil" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Rôle de l'appareil" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3804,14 +3808,36 @@ msgstr "Rôle de l'appareil" msgid "Platform" msgstr "Plateforme" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Cluster" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3821,9 +3847,9 @@ msgstr "Plateforme" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3832,10 +3858,10 @@ msgstr "Plateforme" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3862,7 +3888,7 @@ msgstr "Plateforme" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3872,23 +3898,28 @@ msgstr "Plateforme" msgid "Device" msgstr "Appareil" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Configuration" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Virtualisation" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Type de module" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3906,109 +3937,109 @@ msgstr "Type de module" msgid "Label" msgstr "Libellé" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Longueur" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Unité de longueur" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Domaine" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "panneau d'alimentation" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Approvisionnement" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Phase" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "tension" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Ampérage" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Utilisation maximale" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Tirage maximum" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Consommation électrique maximale (watts)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Tirage au sort attribué" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Consommation électrique allouée (watts)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "port d'alimentation" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Patte d'alimentation" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Gestion uniquement" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "Mode PoE" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "Type PoE" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Rôle sans fil" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4022,17 +4053,17 @@ msgstr "Rôle sans fil" msgid "Module" msgstr "Modules" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "DÉCALAGE" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Contextes des appareils virtuels" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4041,7 +4072,7 @@ msgstr "Contextes des appareils virtuels" msgid "Speed" msgstr "Vitesse" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4055,76 +4086,88 @@ msgstr "Vitesse" msgid "Mode" msgstr "Mode" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "groupe VLAN" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "VLAN non balisé" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "VLAN balisés" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Groupe LAN sans fil" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "Réseaux locaux sans fil" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Adressage" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Fonctionnement" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Interfaces associées" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "Commutation 802.1Q" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "Le mode d'interface doit être spécifié pour attribuer des VLAN" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "" "Des tags de VLAN ne peuvent pas être associés à une interface d'accès." @@ -4151,9 +4194,9 @@ msgstr "Groupe associé" msgid "available options" msgstr "options disponibles" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4175,15 +4218,15 @@ msgstr "Le fabricant de ce type de rack" msgid "The lowest-numbered position in the rack" msgstr "La position la plus basse du rack" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Largeur rail à rail (en pouces)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Unité pour les dimensions extérieures" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Unité poids de la baie" @@ -4195,158 +4238,148 @@ msgstr "Nom du locataire associé" msgid "Name of assigned role" msgstr "Nom du rôle attribué" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Direction du flux d'air" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Site parent" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Emplacement de la baie (le cas échéant)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Unités" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Liste de numéros d'unités individuels séparés par des virgules" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "Le fabricant qui produit ce type d'appareil" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "Plateforme par défaut pour les appareils de ce type (facultatif)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Poids de l'appareil" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Unité de poids de l'appareil" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Poids du module" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Unité pour le poids du module" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Limiter les affectations de plateforme à ce fabricant" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Rôle attribué" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Fabricant du type d'appareil" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Type d'appareil et modèle" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Plateforme attribuée" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Châssis virtuel" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Cluster" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Cluster de virtualisation" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Emplacement attribué (le cas échéant)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Baie attribuée (le cas échéant)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Visage" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Face montée en baie" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Appareil parent (pour les appareils pour enfants)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Baie pour appareils" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" "Baie d'appareils dans laquelle cet appareil est installé (pour les appareils" " pour enfants)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "L'appareil sur lequel ce module est installé" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Baie modulaire" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "La baie du module dans laquelle ce module est installé" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "Le type de module" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Répliquer les composants" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4354,86 +4387,86 @@ msgstr "" "Remplir automatiquement les composants associés à ce type de module (activé " "par défaut)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Adoptez des composants" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Adoptez des composants déjà existants" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Type de port" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Vitesse du port en bits/s" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Type de prise" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Port d'alimentation local qui alimente cette prise" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Phase électrique (pour circuits triphasés)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Interface pour les parents" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Interface pontée" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Retard" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Interface LAG parent" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "VDC" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" "Noms de VDC séparés par des virgules, entre guillemets doubles. Exemple :" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Support physique" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Duplex" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "Mode PoE" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Type de poteau" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "Mode de fonctionnement IEEE 802.1Q (pour interfaces L2)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4441,172 +4474,172 @@ msgstr "Mode de fonctionnement IEEE 802.1Q (pour interfaces L2)" msgid "Assigned VRF" msgstr "VRF attribué" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Rôle RF" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Rôle sans fil (AP/station)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} n'est pas attribué à l'appareil {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Port arrière" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Port arrière correspondant" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Classification des supports physiques" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Appareil installé" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "Appareil pour enfant installé dans cette baie" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Appareil pour enfant introuvable." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Article d'inventaire parent" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Type de composant" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Type de composant" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Nom du composant" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Nom du composant" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Composant introuvable : {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Appareil côté A" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Nom de l'appareil" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Côté A type" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Type de terminaison" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Nom de la face A" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Nom de terminaison" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Appareil Side B" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Type de face B" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Nom de la face B" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "État de la connexion" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "Côté {side_upper}: {device} {termination_object} est déjà connecté" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} terminaison latérale introuvable : {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Maître" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Appareil principal" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Nom du site parent" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "Panneau d'alimentation en amont" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Principal ou redondant" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Type d'alimentation (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Monophasé ou triphasé" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "IPv4 principal" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "Adresse IPv4 avec masque, par exemple 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "IPv6 principal" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "Adresse IPv6 avec longueur de préfixe, par exemple 2001:db8 : :1/64" @@ -4695,10 +4728,6 @@ msgstr "Groupe de parents" msgid "Facility" msgstr "Datacentre" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Type de baie" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Fonction" @@ -4735,7 +4764,7 @@ msgid "Has virtual device contexts" msgstr "Possède des contextes de périphériques virtuels" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Groupe de clusters" @@ -4774,7 +4803,7 @@ msgstr "Type" msgid "Mgmt only" msgstr "Gestion uniquement" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4879,36 +4908,46 @@ msgstr "Remplir automatiquement les composants associés à ce type de module" msgid "Characteristics" msgstr "Caractéristiques" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Modèle de port de console" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Modèle de port de serveur de console" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Modèle de port avant" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Modèle d'interface" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Modèle de prise de courant" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Modèle de port d'alimentation" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Modèle de port arrière" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4932,7 +4971,7 @@ msgstr "Modèle de port arrière" msgid "Interface" msgstr "Interface" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4940,14 +4979,14 @@ msgstr "Interface" msgid "Console Port" msgstr "Port de console" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Port du serveur de consoles" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4958,7 +4997,7 @@ msgstr "Port du serveur de consoles" msgid "Front Port" msgstr "Port avant" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4971,40 +5010,40 @@ msgstr "Port avant" msgid "Rear Port" msgstr "Port arrière" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Port d'alimentation" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Prise de courant" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Affectation des composants" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "Un item d'inventaire ne peut être attribué qu'à un seul composant." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "Interface LAG" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Filtrez les VLAN disponibles pour une attribution par groupe." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Appareil pour enfants" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -5012,35 +5051,35 @@ msgstr "" "Les appareils enfants doivent d'abord être créés et affectés au site et à la" " baie de l'appareil parent." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Port de console" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Port du serveur de console" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Port avant" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "prise de courant" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Article d'inventaire" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Rôle de l'article d'inventaire" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5058,12 +5097,12 @@ msgstr "" "sont attendus." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Ports arrière" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "Associer un port arrière à chaque port avant en cours de création." @@ -5077,16 +5116,7 @@ msgstr "" "correspondre au nombre sélectionné de positions des ports arrière " "({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"La chaîne {module} sera remplacée par la position du module " -"attribué si nécessaire." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5095,18 +5125,18 @@ msgstr "" "Le nombre de ports frontaux à créer ({frontport_count}) doit correspondre au" " nombre sélectionné de positions des ports arrière ({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Membres" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Position initiale" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." @@ -5114,7 +5144,7 @@ msgstr "" "Position du premier dispositif membre. Augmente d'une unité pour chaque " "membre supplémentaire." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "Une position doit être spécifiée pour le premier membre du VC." @@ -6067,12 +6097,12 @@ msgstr "position (U)" msgid "rack face" msgstr "face de la baie" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "IPv4 principal" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "IPv6 principal" @@ -6252,22 +6282,22 @@ msgstr "" "Le module doit être installé dans une baie de modules appartenant au " "périphérique attribué ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "domaine" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "châssis virtuel" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "" "Le master sélectionné ({master}) n'est pas attribué à ce châssis virtuel." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6276,34 +6306,34 @@ msgstr "" "Impossible de supprimer le châssis virtuel {self}. Il existe des interfaces " "membres qui forment des interfaces LAG inter-châssis." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "identificateur" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Identifiant numérique propre à l'appareil parent" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "commentaires" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "contexte du périphérique virtuel" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "contextes de périphériques virtuels" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} n'est pas un IPV{family} adresse." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" "L'adresse IP principale doit appartenir à une interface sur l'appareil " @@ -6497,7 +6527,7 @@ msgstr "Identifiant attribué localement" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Rôle fonctionnel" @@ -6708,7 +6738,7 @@ msgstr "Joignable" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Appareils" @@ -6737,8 +6767,8 @@ msgid "Site Group" msgstr "Groupe de sites" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6789,20 +6819,20 @@ msgid "Power outlets" msgstr "Prises de courant" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Interfaces" @@ -6828,8 +6858,8 @@ msgid "Module Bay" msgstr "Module Bay" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6858,7 +6888,7 @@ msgstr "Tirage maximal (W)" msgid "Allocated draw (W)" msgstr "Tirage alloué (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6954,87 +6984,87 @@ msgstr "Hauteur en U" msgid "Instances" msgstr "Instances" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Ports de console" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Ports du serveur de consoles" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Ports d'alimentation" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Prises de courant" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Ports avant" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Ports arrière" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Baies pour appareils" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Baies pour modules" @@ -7083,7 +7113,7 @@ msgstr "Espace" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7093,28 +7123,28 @@ msgstr "Sites" msgid "Test case must set peer_termination_type" msgstr "Le scénario de test doit définir peer_termination_type" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Déconnecté {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Réservations" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Appareils non rackés" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Contexte de configuration" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Configuration du rendu" @@ -7125,37 +7155,37 @@ msgstr "Une erreur s'est produite lors du rendu du modèle : {error}" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Machines virtuelles" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Appareil installé {device} dans la baie {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Appareil retiré {device} depuis la baie {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Enfants" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Membre ajouté {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "" "Impossible de supprimer le périphérique principal {device} depuis le châssis" " virtuel." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "Supprimé {device} depuis un châssis virtuel {chassis}" @@ -7339,7 +7369,6 @@ msgstr "Mise à jour" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -8178,21 +8207,21 @@ msgstr "Planifier l'exécution du script à une heure définie" msgid "Interval at which this script is re-run (in minutes)" msgstr "Intervalle auquel ce script est réexécuté (en minutes)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "" "Les modifications apportées à la base de données ont été annulées " "automatiquement." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Le script a été abandonné avec une erreur : " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Une exception s'est produite : " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "" "Les modifications apportées à la base de données ont été annulées en raison " @@ -9246,7 +9275,7 @@ msgstr "Widget supprimé : " msgid "Error deleting widget: " msgstr "Erreur lors de la suppression du widget : " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "" "Impossible d'exécuter le script : le processus de travail RQ n'est pas en " @@ -9395,7 +9424,7 @@ msgid "Prefixes which contain this prefix or IP" msgstr "Préfixes contenant ce préfixe ou cette adresse IP" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Longueur du masque" @@ -9409,7 +9438,7 @@ msgid "VLAN number (1-4094)" msgstr "Numéro de VLAN (1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9521,16 +9550,16 @@ msgstr "Un masque CIDR (par exemple /24) est requis." msgid "Address pattern" msgstr "Modèle d'adresse" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Forcer l'unicité des préfixes IP" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "Est privé" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9544,20 +9573,20 @@ msgstr "Est privé" msgid "RIR" msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Date d'ajout" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "Groupe VLAN" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9570,32 +9599,32 @@ msgstr "Groupe VLAN" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Longueur du préfixe" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "C'est une piscine" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Traiter comme s'il avait été pleinement utilisé" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "Attribution de VLAN" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "Nom DNS" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9603,12 +9632,12 @@ msgstr "Nom DNS" msgid "Protocol" msgstr "Protocole" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "ID de groupe" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9620,12 +9649,12 @@ msgstr "ID de groupe" msgid "Authentication type" msgstr "Type d'authentification" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Clé d'authentification" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9637,26 +9666,26 @@ msgstr "Clé d'authentification" msgid "Authentication" msgstr "Authentification" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Type de portée" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "Plages d'ID VLAN" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Champ" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "Plages d'ID VLAN" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Site et groupe" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9683,8 +9712,8 @@ msgstr "Le groupe du VLAN (le cas échéant)" msgid "Parent device of assigned interface (if any)" msgstr "Appareil parent auquel est attribuée l'interface (le cas échéant)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9710,43 +9739,63 @@ msgstr "Est principal" msgid "Make this the primary IP for the assigned device" msgstr "Faites-en l'adresse IP principale de l'appareil attribué" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "Aucun périphérique ou machine virtuelle spécifié ; impossible de le définir " "comme adresse IP principale" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "" "Aucune interface spécifiée ; impossible de définir comme adresse IP " "principale" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Type d'authentification" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Type de scope (application et modèle)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Groupe VLAN attribué" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "Protocole IP" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Obligatoire s'il n'est pas attribué à une machine virtuelle" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Obligatoire s'il n'est pas attribué à un appareil" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} n'est pas attribué à cet appareil/à cette machine virtuelle." @@ -9828,7 +9877,7 @@ msgstr "Affecté à une interface" msgid "DNS Name" msgstr "Nom DNS" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9839,13 +9888,13 @@ msgstr "VLAN" msgid "Contains VLAN ID" msgstr "Contient un ID de VLAN" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "IDENTIFIANT DE VLAN" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9856,7 +9905,7 @@ msgstr "IDENTIFIANT DE VLAN" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9885,8 +9934,8 @@ msgstr "Affectation de site/VLAN" msgid "IP Range" msgstr "Plage IP" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "Groupe FHRP" @@ -9896,47 +9945,57 @@ msgid "Make this the primary IP for the device/VM" msgstr "" "Faites-en l'adresse IP principale de l'appareil/de la machine virtuelle" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "IP NAT (interne)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "Une adresse IP ne peut être attribuée qu'à un seul objet." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Impossible de réattribuer l'adresse IP lorsqu'elle est désignée comme " -"adresse IP principale pour l'objet parent" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "Seules les adresses IP attribuées à une interface peuvent être désignées " "comme adresses IP principales." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Adresse IP virtuelle" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "L'affectation existe déjà" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "ID de VLAN" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "VLAN pour enfants" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9944,33 +10003,33 @@ msgstr "" "Liste séparée par des virgules d'un ou de plusieurs numéros de port. Une " "plage peut être spécifiée à l'aide d'un trait d'union." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Modèle de service" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Port (x)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Service" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Modèle de service" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "À partir du modèle" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Personnalisé" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10260,6 +10319,14 @@ msgstr "" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Adresse IP dupliquée trouvée dans {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Impossible de réattribuer l'adresse IP lorsqu'elle est désignée comme " +"adresse IP principale pour l'objet parent" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "" @@ -10316,40 +10383,48 @@ msgstr "Impossible de définir scope_type sans scope_id." msgid "Cannot set scope_id without scope_type." msgstr "Impossible de définir scope_id sans scope_type." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Les plages ne peuvent pas se chevaucher." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"La VID maximale pour les enfants doit être supérieure ou égale à la VID " -"minimale pour les enfants ({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "Le site spécifique auquel ce VLAN est associé (le cas échéant)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "Groupe VLAN (facultatif)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "ID VLAN numérique (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "État opérationnel de ce VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "La principale fonction de ce VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10358,7 +10433,7 @@ msgstr "" "Le VLAN est associé au groupe {group} (champ d'application : {scope}) ; ne " "peut pas également être associé au site {site}." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "" @@ -11139,17 +11214,12 @@ msgstr "Politiques IPSec" msgid "IPSec Profiles" msgstr "Profils IPSec" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Virtualisation" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Disques virtuels" @@ -11311,7 +11381,7 @@ msgstr "Système" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11562,19 +11632,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Rangée {i}: Objet avec identifiant {id} n'existe pas" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "Non {object_type} ont été sélectionnés." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Renommé {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Supprimé {count} {object_type}" @@ -11608,7 +11678,7 @@ msgstr "Synchronisé {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} doit implémenter get_children ()" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11955,9 +12025,7 @@ msgid "Circuit Type" msgstr "Type de circuit" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11968,7 +12036,6 @@ msgstr "Ajouter" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12258,35 +12325,35 @@ msgstr "jours" msgid "Indefinite" msgstr "Indéfini" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Non installé" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Vue d'ensemble" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Installer" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Détails du plugin" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Résumé" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Licence" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Historique des versions" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Instructions d'installation locales" @@ -12631,8 +12698,8 @@ msgstr "Ajouter un service" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12705,20 +12772,24 @@ msgstr "Configuration" msgid "Context Data" msgstr "Données de contexte" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Configuration rendue" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Télécharger" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Aucun modèle de configuration trouvé" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12740,7 +12811,6 @@ msgid "Local Config Context Data" msgstr "Données contextuelles de configuration locales" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12787,12 +12857,12 @@ msgid "VM Role" msgstr "Rôle de la machine virtuelle" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Nom du modèle" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Numéro de pièce" @@ -12931,7 +13001,7 @@ msgstr "Adresse MAC" msgid "Wireless Link" msgstr "Liaison sans fil" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Peer" @@ -13557,7 +13627,7 @@ msgstr "Vous n'avez pas le droit d'exécuter des scripts" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Exécuter le script" @@ -13570,27 +13640,32 @@ msgstr "Erreur de chargement du script" msgid "Script no longer exists in the source file." msgstr "Le script n'existe plus dans le fichier source." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Dernière exécution" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "Le script n'est plus présent dans le fichier source" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Jamais" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Exécutez à nouveau" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Aucun script trouvé" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13913,7 +13988,7 @@ msgstr "Toutes les notifications" msgid "Select" msgstr "Sélectionner" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Réinitialiser" @@ -14397,6 +14472,10 @@ msgstr "Ressources" msgid "Add Virtual Disk" msgstr "Ajouter un disque virtuel" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15479,13 +15558,13 @@ msgid "Memory (MB)" msgstr "Mémoire (Mo)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Disque (Go)" +msgid "Disk (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Taille (Go)" +msgid "Size (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15673,68 +15752,80 @@ msgstr "disque virtuel" msgid "virtual disks" msgstr "disques virtuels" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Ajouté {count} appareils à mettre en cluster {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Supprimé {count} appareils du cluster {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPSec - Transport" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec - Tunnel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP dans IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GRE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Hub" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "Spoke" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Agressif" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Principal" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Clés pré-partagées" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Certificats" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "Signatures RSA" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "Signatures DSA" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15743,23 +15834,27 @@ msgstr "Signatures DSA" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Groupe {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Réseau local privé Ethernet" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Réseau local privé virtuel Ethernet" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Arbre privé Ethernet" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Arbre privé virtuel Ethernet" diff --git a/netbox/translations/it/LC_MESSAGES/django.mo b/netbox/translations/it/LC_MESSAGES/django.mo index 839e15400..01dc8e853 100644 Binary files a/netbox/translations/it/LC_MESSAGES/django.mo and b/netbox/translations/it/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/it/LC_MESSAGES/django.po b/netbox/translations/it/LC_MESSAGES/django.po index 2619db447..21a038c55 100644 --- a/netbox/translations/it/LC_MESSAGES/django.po +++ b/netbox/translations/it/LC_MESSAGES/django.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" "Last-Translator: Jeremy Stretch, 2024\n" "Language-Team: Italian (https://app.transifex.com/netbox-community/teams/178115/it/)\n" @@ -91,8 +91,8 @@ msgstr "La tua password è stata cambiata con successo." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -105,7 +105,7 @@ msgstr "Approvvigionamento" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -116,8 +116,8 @@ msgid "Active" msgstr "Attivo" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Offline" @@ -130,7 +130,7 @@ msgstr "Deprovisioning" msgid "Decommissioned" msgstr "Dismesso" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Primaria" @@ -203,12 +203,12 @@ msgstr "Gruppo del sito (slug)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -217,18 +217,17 @@ msgstr "Gruppo del sito (slug)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -336,10 +335,10 @@ msgstr "Terminazione A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -391,7 +390,7 @@ msgstr "Gruppo di circuiti (slug)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -406,33 +405,33 @@ msgstr "ASN" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -441,7 +440,7 @@ msgstr "ASN" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -456,7 +455,7 @@ msgstr "ASN" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -476,7 +475,7 @@ msgstr "ASN" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -569,10 +568,10 @@ msgid "Service ID" msgstr "ID del servizio" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -593,16 +592,16 @@ msgstr "Colore" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -657,14 +656,14 @@ msgstr "Provider account " #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -673,13 +672,13 @@ msgstr "Provider account " #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -690,7 +689,7 @@ msgstr "Provider account " #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -726,30 +725,30 @@ msgstr "Status" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -819,11 +818,11 @@ msgstr "Parametri del servizio" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -855,11 +854,11 @@ msgstr "Port speed (Kbps)" msgid "Upstream speed (Kbps)" msgstr "Upstream speed (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Segna connesso" @@ -906,10 +905,10 @@ msgstr "Tipo di circuito" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -919,13 +918,13 @@ msgstr "Stato operativo" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -950,12 +949,12 @@ msgstr "Provider network" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -972,9 +971,9 @@ msgstr "Provider network" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1003,8 +1002,8 @@ msgid "Contacts" msgstr "Contatti" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1012,13 +1011,12 @@ msgstr "Contatti" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1031,16 +1029,16 @@ msgid "Region" msgstr "Regione" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1052,7 +1050,7 @@ msgstr "Gruppo del sito" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1091,9 +1089,9 @@ msgstr "Account" msgid "Term Side" msgstr "Lato del termine" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1103,11 +1101,11 @@ msgstr "Assegnazione" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1179,20 +1177,20 @@ msgid "Unique circuit ID" msgstr "ID univoco del circuito" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "stato" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "installato" @@ -1314,11 +1312,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1329,7 +1327,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1417,7 +1415,7 @@ msgstr "reti di fornitori" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1428,7 +1426,7 @@ msgstr "reti di fornitori" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1459,7 +1457,7 @@ msgstr "reti di fornitori" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1625,7 +1623,7 @@ msgstr "Completato" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Fallito" @@ -1692,7 +1690,7 @@ msgid "Cancelled" msgstr "Annullato" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Locale" @@ -1779,8 +1777,8 @@ msgid "User name" msgstr "Nome utente" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1884,7 +1882,7 @@ msgid "Completed before" msgstr "Completato prima" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1950,9 +1948,9 @@ msgstr "" msgid "Rack Elevations" msgstr "Elevazioni dei rack" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Energia" @@ -2055,7 +2053,7 @@ msgstr "" " ({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2115,7 +2113,7 @@ msgstr "tipo" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2236,60 +2234,60 @@ msgstr "file gestito" msgid "managed files" msgstr "file gestiti" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "pianificata" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "intervallo" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Intervallo di ricorrenza (in minuti)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "iniziato" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "completato" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "dato" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "errore" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "ID lavoro" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "occupazione" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "lavori" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "" "I lavori non possono essere assegnati a questo tipo di oggetto ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "" "Stato non valido per la cessazione del lavoro. Le scelte sono: {choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" @@ -2374,7 +2372,7 @@ msgstr "Versione massima di NetBox" msgid "No plugin data found" msgstr "Nessun dato del plugin trovato" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Autore" @@ -2382,7 +2380,7 @@ msgstr "Autore" msgid "Installed" msgstr "Installato" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Certificato" @@ -2508,11 +2506,11 @@ msgstr "Lavoro {id} è stato fermato." msgid "Failed to stop job {id}" msgstr "Interruzione del lavoro non riuscita {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "Impossibile caricare il catalogo dei plugin" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Plugin {name} non trovato" @@ -2532,7 +2530,7 @@ msgid "Staging" msgstr "Messa in scena" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Smantellamento" @@ -2596,7 +2594,7 @@ msgstr "Obsoleto" msgid "Millimeters" msgstr "Millimetri" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "Pollici" @@ -2610,15 +2608,15 @@ msgstr "Da anteriore a posteriore" msgid "Rear to front" msgstr "Posteriore/anteriore" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2698,7 +2696,7 @@ msgid "Top to bottom" msgstr "Dall'alto verso il basso" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Passivo" @@ -2727,8 +2725,8 @@ msgid "Proprietary" msgstr "Proprietario" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Altro" @@ -2741,24 +2739,24 @@ msgstr "ITA/Internazionale" msgid "Physical" msgstr "Fisico" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Virtuale" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Wireless" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Interfacce virtuali" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2767,27 +2765,27 @@ msgstr "Interfacce virtuali" msgid "Bridge" msgstr "ponte" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Link Aggregation Group (GAL)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (fisso)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (modulare)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (backplane)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Cellulare" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2795,130 +2793,130 @@ msgstr "Cellulare" msgid "Serial" msgstr "Seriale" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Coassiale" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "impilamento" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Metà" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Completo" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Auto" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Accesso" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Taggato" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Contrassegnati (tutti)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "Norma IEEE" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "24V passivo (2 coppie)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "24V passivo (4 coppie)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "48V passivo (2 coppie)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "48V passivo (4 coppie)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Rame" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Fibra ottica" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Fibra" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Connesso" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Chilometri" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Metri" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Centimetri" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Miglia" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Piedi" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Chilogrammi" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Grammi" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "Sterline" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Once" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Ridondante" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Monofase" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Trifase" @@ -3164,7 +3162,7 @@ msgstr "Gruppo cluster (ID)" msgid "Device model (slug)" msgstr "Modello del dispositivo (slug)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "È a piena profondità" @@ -3286,21 +3284,21 @@ msgstr "VLAN assegnata" msgid "Assigned VID" msgstr "VID assegnato" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3367,7 +3365,7 @@ msgid "LAG interface (ID)" msgstr "Interfaccia LAG (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Contesto del dispositivo virtuale" @@ -3441,7 +3439,7 @@ msgstr "Etichette" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3458,38 +3456,38 @@ msgstr "" "Sono supportati gli intervalli alfanumerici. (Deve corrispondere al numero " "di nomi da creare.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Nome del contatto" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Telefono di contatto" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "E-mail di contatto" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Fuso orario" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3499,58 +3497,59 @@ msgstr "Fuso orario" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Produttore" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Fattore di forma" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Larghezza" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Altezza (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Unità discendenti" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Larghezza esterna" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Profondità esterna" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Unità esterna" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Profondità di montaggio" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3561,10 +3560,10 @@ msgstr "Profondità di montaggio" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3573,61 +3572,61 @@ msgstr "Profondità di montaggio" msgid "Weight" msgstr "Peso" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Peso massimo" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Unità di peso" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Tipo di rack" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Dimensioni esterne" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Dimensioni" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Numerazione" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3655,45 +3654,50 @@ msgstr "Numerazione" msgid "Role" msgstr "Ruolo" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Tipo di rack" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Numero di serie" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Etichetta dell'asset" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Flusso d'aria" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3703,64 +3707,64 @@ msgstr "Flusso d'aria" msgid "Rack" msgstr "cremagliera" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Hardware" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Piattaforma predefinita" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Numero del pezzo" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "Altezza U" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Escludi dall'utilizzo" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Tipo di dispositivo" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Tipo di modulo" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Telaio" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "Ruolo VM" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3771,19 +3775,19 @@ msgstr "Ruolo VM" msgid "Config template" msgstr "Modello di configurazione" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Tipo di dispositivo" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Ruolo del dispositivo" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3797,14 +3801,36 @@ msgstr "Ruolo del dispositivo" msgid "Platform" msgstr "piattaforma" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Grappolo" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3814,9 +3840,9 @@ msgstr "piattaforma" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3825,10 +3851,10 @@ msgstr "piattaforma" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3855,7 +3881,7 @@ msgstr "piattaforma" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3865,23 +3891,28 @@ msgstr "piattaforma" msgid "Device" msgstr "Dispositivo" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Configurazione" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Virtualizzazione" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Tipo di modulo" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3899,109 +3930,109 @@ msgstr "Tipo di modulo" msgid "Label" msgstr "Etichetta" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Lunghezza" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Unità di lunghezza" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Dominio" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "Pannello di alimentazione" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Fornitura" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Fase" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Voltaggio" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Amperaggio" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Utilizzo massimo" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Pareggio massimo" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Potenza massima assorbita (watt)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Pareggio assegnato" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Potenza assorbita allocata (watt)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Porta di alimentazione" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Gamba di alimentazione" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Solo gestione" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "modalità PoE" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "Tipo PoE" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Ruolo wireless" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4015,17 +4046,17 @@ msgstr "Ruolo wireless" msgid "Module" msgstr "Modulo" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "RITARDO" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Contesti dei dispositivi virtuali" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4034,7 +4065,7 @@ msgstr "Contesti dei dispositivi virtuali" msgid "Speed" msgstr "Velocità" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4048,77 +4079,89 @@ msgstr "Velocità" msgid "Mode" msgstr "modalità" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "Gruppo VLAN" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "VLAN senza tag" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "Taggato VLAN" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Gruppo LAN wireless" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "LAN wireless" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Indirizzamento" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Operazione" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Interfacce correlate" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "Commutazione 802.1Q" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "" "La modalità di interfaccia deve essere specificata per assegnare le VLAN" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "" "A un'interfaccia di accesso non possono essere assegnate VLAN con tag." @@ -4145,9 +4188,9 @@ msgstr "Gruppo assegnato" msgid "available options" msgstr "opzioni disponibili" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4169,15 +4212,15 @@ msgstr "Il produttore di questo tipo di rack" msgid "The lowest-numbered position in the rack" msgstr "La posizione con il numero più basso nel rack" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Larghezza da rotaia a rotaia (in pollici)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Unità per dimensioni esterne" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Unità per pesi a scaffale" @@ -4189,158 +4232,148 @@ msgstr "Nome dell'inquilino assegnato" msgid "Name of assigned role" msgstr "Nome del ruolo assegnato" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Direzione del flusso d'aria" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Sito principale" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Posizione del rack (se presente)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Unità" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Elenco separato da virgole di numeri di unità individuali" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "Il produttore che produce questo tipo di dispositivo" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "La piattaforma predefinita per dispositivi di questo tipo (opzionale)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Peso del dispositivo" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Unità per il peso del dispositivo" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Peso del modulo" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Unità per il peso del modulo" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Limita le assegnazioni delle piattaforme a questo produttore" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Ruolo assegnato" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Produttore del tipo di dispositivo" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Tipo di dispositivo modello" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Piattaforma assegnata" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Chassis virtuale" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Grappolo" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Cluster di virtualizzazione" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Posizione assegnata (se presente)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Rack assegnato (se presente)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Viso" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Faccia del rack montata" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Dispositivo principale (per dispositivi per bambini)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Alloggiamento per dispositivi" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" "Alloggiamento del dispositivo in cui è installato questo dispositivo (per " "dispositivi per bambini)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "Il dispositivo in cui è installato questo modulo" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "alloggiamento per moduli" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "L'alloggiamento del modulo in cui è installato questo modulo" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "Il tipo di modulo" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Componenti replicati" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4348,86 +4381,86 @@ msgstr "" "Compila automaticamente i componenti associati a questo tipo di modulo " "(abilitato per impostazione predefinita)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Adotta i componenti" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Adotta componenti già esistenti" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Tipo di porta" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Velocità della porta in bps" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Tipo di presa" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Porta di alimentazione locale che alimenta questa presa" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Fase elettrica (per circuiti trifase)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Interfaccia principale" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Interfaccia con ponte" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Ritardo" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Interfaccia LAG principale" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "Vdc" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" "Nomi VDC separati da virgole, racchiusi tra virgolette doppie. Esempio:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Supporto fisico" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Duplex" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "modalità Poe" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Tipo Poe" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "Modalità operativa IEEE 802.1Q (per interfacce L2)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4435,173 +4468,173 @@ msgstr "Modalità operativa IEEE 802.1Q (per interfacce L2)" msgid "Assigned VRF" msgstr "VRF assegnato" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Ruolo Rf" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Ruolo wireless (AP/stazione)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} non è assegnato al dispositivo {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Porta posteriore" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Porta posteriore corrispondente" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Classificazione del mezzo fisico" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Dispositivo installato" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "" "Dispositivo per bambini installato all'interno di questo alloggiamento" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Dispositivo secondario non trovato." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Articolo di inventario principale" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Tipo di componente" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Tipo di componente" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Nome del componente" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Nome del componente" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Componente non trovato: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Dispositivo lato A" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Nome del dispositivo" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Tipo Lato A" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Tipo di terminazione" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Nome del lato A" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Nome della cessazione" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Dispositivo lato B" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Tipo B laterale" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Nome lato B" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Stato della connessione" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "Lato {side_upper}: {device} {termination_object} è già connesso" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} terminazione laterale non trovata: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Maestro" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Dispositivo master" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Nome del sito principale" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "Pannello di alimentazione upstream" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Primario o ridondante" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Tipo di alimentazione (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Monofase o trifase" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "IPv4 primario" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "Indirizzo IPv4 con maschera, ad esempio 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "IPv6 primario" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "Indirizzo IPv6 con lunghezza del prefisso, ad esempio 2001:db8: :1/64" @@ -4689,10 +4722,6 @@ msgstr "Gruppo di genitori" msgid "Facility" msgstr "Struttura" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Tipo di rack" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Funzione" @@ -4729,7 +4758,7 @@ msgid "Has virtual device contexts" msgstr "Dispone di contesti di dispositivi virtuali" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Gruppo Cluster" @@ -4768,7 +4797,7 @@ msgstr "Gentile" msgid "Mgmt only" msgstr "Solo gestione" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4876,36 +4905,46 @@ msgstr "" msgid "Characteristics" msgstr "Caratteristiche" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Modello di porta console" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Modello di porta del server console" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Modello di porta anteriore" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Modello di interfaccia" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Modello di presa di corrente" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Modello di porta di alimentazione" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Modello di porta posteriore" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4929,7 +4968,7 @@ msgstr "Modello di porta posteriore" msgid "Interface" msgstr "Interfaccia" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4937,14 +4976,14 @@ msgstr "Interfaccia" msgid "Console Port" msgstr "Porta console" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Porta Console Server" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4955,7 +4994,7 @@ msgstr "Porta Console Server" msgid "Front Port" msgstr "Porta anteriore" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4968,40 +5007,40 @@ msgstr "Porta anteriore" msgid "Rear Port" msgstr "Porta posteriore" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Porta di alimentazione" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Presa di corrente" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Assegnazione dei componenti" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "Un InventoryItem può essere assegnato solo a un singolo componente." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "Interfaccia LAG" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Filtra le VLAN disponibili per l'assegnazione per gruppo." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Dispositivo per bambini" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -5009,35 +5048,35 @@ msgstr "" "I dispositivi secondari devono prima essere creati e assegnati al sito e al " "rack del dispositivo principale." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Porta console" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Porta console server" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Porta anteriore" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "Presa di corrente" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Articolo di inventario" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Ruolo dell'articolo di inventario" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5055,12 +5094,12 @@ msgstr "" "attesi." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Porte posteriori" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" "Seleziona un'assegnazione della porta posteriore per ogni porta anteriore da" @@ -5076,16 +5115,7 @@ msgstr "" "corrispondere al numero selezionato di posizioni delle porte posteriori " "({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"La corda {module} verrà sostituita dalla posizione del modulo " -"assegnato, se presente." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5095,18 +5125,18 @@ msgstr "" " al numero selezionato di posizioni delle porte posteriori " "({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Membri" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Posizione iniziale" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." @@ -5114,7 +5144,7 @@ msgstr "" "Posizione del primo dispositivo membro. Aumenta di uno per ogni membro " "aggiuntivo." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "È necessario specificare una posizione per il primo membro VC." @@ -6084,12 +6114,12 @@ msgstr "posizione (U)" msgid "rack face" msgstr "faccia cremagliera" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "IPv4 primario" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "IPv6 primario" @@ -6270,22 +6300,22 @@ msgstr "" "Il modulo deve essere installato all'interno di un vano del modulo " "appartenente al dispositivo assegnato ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "dominio" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "chassis virtuale" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "" "Il master selezionato ({master}) non è assegnato a questo chassis virtuale." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6294,34 +6324,34 @@ msgstr "" "Impossibile eliminare lo chassis virtuale {self}. Esistono interfacce tra i " "membri che formano interfacce GAL trasversali." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "identificatore" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Identificatore numerico univoco per il dispositivo principale" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "commenti" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "contesto del dispositivo virtuale" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "contesti dei dispositivi virtuali" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} non è un IPv{family} indirizzo." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" "L'indirizzo IP primario deve appartenere a un'interfaccia sul dispositivo " @@ -6513,7 +6543,7 @@ msgstr "Identificatore assegnato localmente" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Ruolo funzionale" @@ -6725,7 +6755,7 @@ msgstr "Raggiungibile" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Dispositivi" @@ -6754,8 +6784,8 @@ msgid "Site Group" msgstr "Gruppo del sito" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6806,20 +6836,20 @@ msgid "Power outlets" msgstr "Prese di corrente" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Interfacce" @@ -6845,8 +6875,8 @@ msgid "Module Bay" msgstr "Modulo Bay" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6875,7 +6905,7 @@ msgstr "Assorbimento massimo (W)" msgid "Allocated draw (W)" msgstr "Pareggio assegnato (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6971,87 +7001,87 @@ msgstr "Altezza U" msgid "Instances" msgstr "Istanze" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Porte console" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Porte Console Server" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Porte di alimentazione" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Prese di corrente" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Porte anteriori" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Porte posteriori" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Alloggiamenti per dispositivi" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Baie per moduli" @@ -7100,7 +7130,7 @@ msgstr "Spazio" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7110,28 +7140,28 @@ msgstr "Siti" msgid "Test case must set peer_termination_type" msgstr "Il test case deve impostare peer_termination_type" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Disconnesso {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Prenotazioni" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Dispositivi non montati su rack" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Contesto di configurazione" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Configurazione del rendering" @@ -7142,36 +7172,36 @@ msgstr "Si è verificato un errore durante il rendering del modello: {error}" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Macchine virtuali" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Dispositivo installato {device} nella baia {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Dispositivo rimosso {device} dalla baia {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Bambini" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Membro aggiunto {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "" "Impossibile rimuovere il dispositivo master {device} dallo chassis virtuale." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "Rimosso {device} da chassis virtuale {chassis}" @@ -7354,7 +7384,6 @@ msgstr "Aggiornamento" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -8192,19 +8221,19 @@ msgstr "Pianifica l'esecuzione dello script a un orario prestabilito" msgid "Interval at which this script is re-run (in minutes)" msgstr "Intervallo di riesecuzione dello script (in minuti)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "Le modifiche al database sono state annullate automaticamente." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Script interrotto con errore: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Si è verificata un'eccezione: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "Le modifiche al database sono state annullate a causa di un errore." @@ -9244,7 +9273,7 @@ msgstr "Widget eliminato: " msgid "Error deleting widget: " msgstr "Errore durante l'eliminazione del widget: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "" "Impossibile eseguire lo script: processo di lavoro RQ non in esecuzione." @@ -9394,7 +9423,7 @@ msgid "Prefixes which contain this prefix or IP" msgstr "Prefissi che contengono questo prefisso o IP" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Lunghezza della maschera" @@ -9408,7 +9437,7 @@ msgid "VLAN number (1-4094)" msgstr "Numero VLAN (1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9520,16 +9549,16 @@ msgstr "È richiesta la mascherina CIDR (ad es. /24)." msgid "Address pattern" msgstr "Schema di indirizzo" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Applica uno spazio unico" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "È privato" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9543,20 +9572,20 @@ msgstr "È privato" msgid "RIR" msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Data aggiunta" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "Gruppo VLAN" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9569,32 +9598,32 @@ msgstr "Gruppo VLAN" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Lunghezza del prefisso" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "È una piscina" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Trattare come completamente utilizzato" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "Assegnazione VLAN" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "Nome DNS" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9602,12 +9631,12 @@ msgstr "Nome DNS" msgid "Protocol" msgstr "Protocollo" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "ID gruppo" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9619,12 +9648,12 @@ msgstr "ID gruppo" msgid "Authentication type" msgstr "Tipo di autenticazione" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Chiave di autenticazione" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9636,26 +9665,26 @@ msgstr "Chiave di autenticazione" msgid "Authentication" msgstr "Autenticazione" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Tipo di ambito" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "Intervalli di ID VLAN" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Ambito" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "Intervalli di ID VLAN" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Sito e gruppo" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9682,8 +9711,8 @@ msgstr "Gruppo VLAN (se presente)" msgid "Parent device of assigned interface (if any)" msgstr "Dispositivo principale dell'interfaccia assegnata (se presente)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9709,42 +9738,62 @@ msgstr "È primario" msgid "Make this the primary IP for the assigned device" msgstr "Imposta questo indirizzo IP primario per il dispositivo assegnato" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "Nessun dispositivo o macchina virtuale specificato; non può essere impostato" " come IP primario" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "" "Nessuna interfaccia specificata; non può essere impostato come IP primario" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Tipo di autenticazione" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Tipo di ambito (app e modello)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Gruppo VLAN assegnato" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "Protocollo IP" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Obbligatorio se non assegnato a una VM" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Obbligatorio se non assegnato a un dispositivo" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} non è assegnato a questo dispositivo/macchina virtuale." @@ -9826,7 +9875,7 @@ msgstr "Assegnata a un'interfaccia" msgid "DNS Name" msgstr "Nome DNS" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9837,13 +9886,13 @@ msgstr "VLAN" msgid "Contains VLAN ID" msgstr "Contiene l'ID VLAN" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "ID VLAN" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9854,7 +9903,7 @@ msgstr "ID VLAN" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9883,8 +9932,8 @@ msgstr "Assegnazione sito/VLAN" msgid "IP Range" msgstr "Intervallo IP" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "Gruppo FHRP" @@ -9894,47 +9943,57 @@ msgid "Make this the primary IP for the device/VM" msgstr "" "Imposta questo indirizzo IP primario per il dispositivo/macchina virtuale" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "NAT IP (interno)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "Un indirizzo IP può essere assegnato a un solo oggetto." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Impossibile riassegnare l'indirizzo IP mentre è designato come IP primario " -"per l'oggetto padre" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "Solo gli indirizzi IP assegnati a un'interfaccia possono essere designati " "come IP primari." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Indirizzo IP virtuale" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "L'assegnazione esiste già" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "ID VLAN" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "VLAN per bambini" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9942,33 +10001,33 @@ msgstr "" "Elenco separato da virgole di uno o più numeri di porta. È possibile " "specificare un intervallo utilizzando un trattino." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Modello di servizio" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Porta/e" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Servizio" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Modello di servizio" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "Da modello" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Personalizzato" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10256,6 +10315,14 @@ msgstr "" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Indirizzo IP duplicato trovato in {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Impossibile riassegnare l'indirizzo IP mentre è designato come IP primario " +"per l'oggetto padre" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Solo agli indirizzi IPv6 può essere assegnato lo stato SLAAC" @@ -10311,40 +10378,48 @@ msgstr "Impossibile impostare scope_type senza scope_id." msgid "Cannot set scope_id without scope_type." msgstr "Impossibile impostare scope_id senza scope_type." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Gli intervalli non possono sovrapporsi." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"Il VID massimo per bambini deve essere maggiore o uguale al VID minimo per " -"bambini ({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "Il sito specifico a cui è assegnata questa VLAN (se presente)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "Gruppo VLAN (opzionale)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "ID VLAN numerico (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Stato operativo di questa VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "La funzione principale di questa VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10353,7 +10428,7 @@ msgstr "" "La VLAN è assegnata al gruppo {group} (scopo: {scope}); non può essere " "assegnato anche al sito {site}." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "" @@ -11129,17 +11204,12 @@ msgstr "Criteri IPSec" msgid "IPSec Profiles" msgstr "Profili IPSec" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Virtualizzazione" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Dischi virtuali" @@ -11301,7 +11371,7 @@ msgstr "Sistema" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11553,19 +11623,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Fila {i}: Oggetto con ID {id} non esiste" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "No {object_type} sono stati selezionati." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Rinominato {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Eliminato {count} {object_type}" @@ -11597,7 +11667,7 @@ msgstr "Sincronizzato {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} deve implementare get_children ()" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11942,9 +12012,7 @@ msgid "Circuit Type" msgstr "Tipo di circuito" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11955,7 +12023,6 @@ msgstr "Inserisci" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12245,35 +12312,35 @@ msgstr "giorni" msgid "Indefinite" msgstr "Indefinito" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Non installato" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Panoramica" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Installare" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Dettagli del plugin" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Riepilogo" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Licenza" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Cronologia delle versioni" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Istruzioni per l'installazione locale" @@ -12617,8 +12684,8 @@ msgstr "Aggiungi un servizio" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12691,20 +12758,24 @@ msgstr "Configurazione" msgid "Context Data" msgstr "Dati contestuali" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Configurazione renderizzata" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Scarica" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Nessun modello di configurazione trovato" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12726,7 +12797,6 @@ msgid "Local Config Context Data" msgstr "Dati di contesto di configurazione locale" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12773,12 +12843,12 @@ msgid "VM Role" msgstr "Ruolo VM" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Nome del modello" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Numero del pezzo" @@ -12917,7 +12987,7 @@ msgstr "Indirizzo MAC" msgid "Wireless Link" msgstr "Collegamento wireless" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Pari" @@ -13543,7 +13613,7 @@ msgstr "Non si dispone dell'autorizzazione per eseguire gli script" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Esegui script" @@ -13556,27 +13626,32 @@ msgstr "Errore durante il caricamento dello script" msgid "Script no longer exists in the source file." msgstr "Lo script non esiste più nel file sorgente." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Ultima corsa" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "Lo script non è più presente nel file sorgente" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Mai" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Corri ancora" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Nessuno script trovato" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13899,7 +13974,7 @@ msgstr "Tutte le notifiche" msgid "Select" msgstr "Seleziona" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Reimposta" @@ -14384,6 +14459,10 @@ msgstr "Risorse" msgid "Add Virtual Disk" msgstr "Aggiungi disco virtuale" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15462,13 +15541,13 @@ msgid "Memory (MB)" msgstr "Memoria (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Disco (GB)" +msgid "Disk (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Dimensioni (GB)" +msgid "Size (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15657,68 +15736,80 @@ msgstr "disco virtuale" msgid "virtual disks" msgstr "dischi virtuali" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Aggiunto {count} dispositivi da raggruppare {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Rimosso {count} dispositivi dal cluster {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPSec - Trasporto" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPSec - Tunnel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP in IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GRE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Hub" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "Ha parlato" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Agressivo" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Principale" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Chiavi precondivise" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Certificati" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "Firme RSA" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "Firme DSA" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15727,23 +15818,27 @@ msgstr "Firme DSA" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Gruppo {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "LAN privata Ethernet" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "LAN privata virtuale Ethernet" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Albero privato Ethernet" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Albero privato virtuale Ethernet" diff --git a/netbox/translations/ja/LC_MESSAGES/django.mo b/netbox/translations/ja/LC_MESSAGES/django.mo index db3175091..c7b76e8cb 100644 Binary files a/netbox/translations/ja/LC_MESSAGES/django.mo and b/netbox/translations/ja/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/ja/LC_MESSAGES/django.po b/netbox/translations/ja/LC_MESSAGES/django.po index 39f438041..e91bc4e2c 100644 --- a/netbox/translations/ja/LC_MESSAGES/django.po +++ b/netbox/translations/ja/LC_MESSAGES/django.po @@ -5,17 +5,17 @@ # # Translators: # Tatsuya Ueda , 2024 -# teapot, 2024 # Jeremy Stretch, 2024 +# teapot, 2024 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-13 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" -"Last-Translator: Jeremy Stretch, 2024\n" +"Last-Translator: teapot, 2024\n" "Language-Team: Japanese (https://app.transifex.com/netbox-community/teams/178115/ja/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -88,8 +88,8 @@ msgstr "パスワードは正常に変更されました。" #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -102,7 +102,7 @@ msgstr "プロビジョニング" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -113,8 +113,8 @@ msgid "Active" msgstr "アクティブ" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "オフライン" @@ -127,7 +127,7 @@ msgstr "デプロビジョニング" msgid "Decommissioned" msgstr "廃止" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "プライマリ" @@ -151,7 +151,7 @@ msgstr "非アクティブ" #: netbox/dcim/filtersets.py:464 netbox/dcim/filtersets.py:1021 #: netbox/dcim/filtersets.py:1368 netbox/dcim/filtersets.py:1903 #: netbox/dcim/filtersets.py:2146 netbox/dcim/filtersets.py:2204 -#: netbox/ipam/filtersets.py:339 netbox/ipam/filtersets.py:959 +#: netbox/ipam/filtersets.py:341 netbox/ipam/filtersets.py:961 #: netbox/virtualization/filtersets.py:45 #: netbox/virtualization/filtersets.py:173 netbox/vpn/filtersets.py:358 msgid "Region (ID)" @@ -163,8 +163,8 @@ msgstr "リージョン (ID)" #: netbox/dcim/filtersets.py:471 netbox/dcim/filtersets.py:1028 #: netbox/dcim/filtersets.py:1375 netbox/dcim/filtersets.py:1910 #: netbox/dcim/filtersets.py:2153 netbox/dcim/filtersets.py:2211 -#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:346 -#: netbox/ipam/filtersets.py:966 netbox/virtualization/filtersets.py:52 +#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:348 +#: netbox/ipam/filtersets.py:968 netbox/virtualization/filtersets.py:52 #: netbox/virtualization/filtersets.py:180 netbox/vpn/filtersets.py:353 msgid "Region (slug)" msgstr "リージョン (slug)" @@ -174,8 +174,8 @@ msgstr "リージョン (slug)" #: netbox/dcim/filtersets.py:346 netbox/dcim/filtersets.py:477 #: netbox/dcim/filtersets.py:1034 netbox/dcim/filtersets.py:1381 #: netbox/dcim/filtersets.py:1916 netbox/dcim/filtersets.py:2159 -#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:352 -#: netbox/ipam/filtersets.py:972 netbox/virtualization/filtersets.py:58 +#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:354 +#: netbox/ipam/filtersets.py:974 netbox/virtualization/filtersets.py:58 #: netbox/virtualization/filtersets.py:186 msgid "Site group (ID)" msgstr "サイトグループ (ID)" @@ -186,7 +186,7 @@ msgstr "サイトグループ (ID)" #: netbox/dcim/filtersets.py:1041 netbox/dcim/filtersets.py:1388 #: netbox/dcim/filtersets.py:1923 netbox/dcim/filtersets.py:2166 #: netbox/dcim/filtersets.py:2224 netbox/extras/filtersets.py:515 -#: netbox/ipam/filtersets.py:359 netbox/ipam/filtersets.py:979 +#: netbox/ipam/filtersets.py:361 netbox/ipam/filtersets.py:981 #: netbox/virtualization/filtersets.py:65 #: netbox/virtualization/filtersets.py:193 msgid "Site group (slug)" @@ -200,12 +200,12 @@ msgstr "サイトグループ (slug)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -214,18 +214,17 @@ msgstr "サイトグループ (slug)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -257,8 +256,8 @@ msgstr "サイト" #: netbox/circuits/filtersets.py:62 netbox/circuits/filtersets.py:229 #: netbox/circuits/filtersets.py:274 netbox/dcim/filtersets.py:242 #: netbox/dcim/filtersets.py:363 netbox/dcim/filtersets.py:458 -#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:238 -#: netbox/ipam/filtersets.py:369 netbox/ipam/filtersets.py:989 +#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:240 +#: netbox/ipam/filtersets.py:371 netbox/ipam/filtersets.py:991 #: netbox/virtualization/filtersets.py:75 #: netbox/virtualization/filtersets.py:203 netbox/vpn/filtersets.py:363 msgid "Site (slug)" @@ -277,13 +276,13 @@ msgstr "ASN" #: netbox/circuits/filtersets.py:95 netbox/circuits/filtersets.py:122 #: netbox/circuits/filtersets.py:156 netbox/circuits/filtersets.py:283 -#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:243 +#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:245 msgid "Provider (ID)" msgstr "プロバイダ (ID)" #: netbox/circuits/filtersets.py:101 netbox/circuits/filtersets.py:128 #: netbox/circuits/filtersets.py:162 netbox/circuits/filtersets.py:289 -#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:249 +#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:251 msgid "Provider (slug)" msgstr "プロバイダ (slug)" @@ -312,8 +311,8 @@ msgstr "回線タイプ (slug)" #: netbox/dcim/filtersets.py:452 netbox/dcim/filtersets.py:1045 #: netbox/dcim/filtersets.py:1393 netbox/dcim/filtersets.py:1928 #: netbox/dcim/filtersets.py:2170 netbox/dcim/filtersets.py:2229 -#: netbox/ipam/filtersets.py:232 netbox/ipam/filtersets.py:363 -#: netbox/ipam/filtersets.py:983 netbox/virtualization/filtersets.py:69 +#: netbox/ipam/filtersets.py:234 netbox/ipam/filtersets.py:365 +#: netbox/ipam/filtersets.py:985 netbox/virtualization/filtersets.py:69 #: netbox/virtualization/filtersets.py:197 netbox/vpn/filtersets.py:368 msgid "Site (ID)" msgstr "サイト (ID)" @@ -333,10 +332,10 @@ msgstr "ターミネーション A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -388,7 +387,7 @@ msgstr "回線グループ (slug)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -403,33 +402,33 @@ msgstr "ASN" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -438,7 +437,7 @@ msgstr "ASN" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -453,7 +452,7 @@ msgstr "ASN" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -473,7 +472,7 @@ msgstr "ASN" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -566,10 +565,10 @@ msgid "Service ID" msgstr "サービス ID" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -590,16 +589,16 @@ msgstr "色" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -654,14 +653,14 @@ msgstr "プロバイダアカウント" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -670,13 +669,13 @@ msgstr "プロバイダアカウント" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -687,7 +686,7 @@ msgstr "プロバイダアカウント" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -723,30 +722,30 @@ msgstr "ステータス" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -816,11 +815,11 @@ msgstr "サービス情報" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -852,11 +851,11 @@ msgstr "ポートスピード (Kbps)" msgid "Upstream speed (Kbps)" msgstr "アップストリーム速度 (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "接続済みにする" @@ -903,10 +902,10 @@ msgstr "回線のタイプ" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -916,13 +915,13 @@ msgstr "運用状況" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -947,12 +946,12 @@ msgstr "プロバイダネットワーク" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -969,9 +968,9 @@ msgstr "プロバイダネットワーク" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1000,8 +999,8 @@ msgid "Contacts" msgstr "連絡先" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1009,13 +1008,12 @@ msgstr "連絡先" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1028,16 +1026,16 @@ msgid "Region" msgstr "リージョン" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1049,7 +1047,7 @@ msgstr "サイトグループ" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1088,9 +1086,9 @@ msgstr "アカウント" msgid "Term Side" msgstr "タームサイド" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1100,11 +1098,11 @@ msgstr "割当" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:1001 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1176,20 +1174,20 @@ msgid "Unique circuit ID" msgstr "一意な回線 ID" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "状態" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "開通済" @@ -1307,11 +1305,11 @@ msgstr "回線終端をサイトとプロバイダーネットワークの両方 #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1322,7 +1320,7 @@ msgstr "回線終端をサイトとプロバイダーネットワークの両方 #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1410,7 +1408,7 @@ msgstr "プロバイダネットワーク" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1421,7 +1419,7 @@ msgstr "プロバイダネットワーク" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1452,7 +1450,7 @@ msgstr "プロバイダネットワーク" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1616,7 +1614,7 @@ msgstr "完了" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "失敗" @@ -1683,7 +1681,7 @@ msgid "Cancelled" msgstr "キャンセルされました" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "ローカル" @@ -1770,8 +1768,8 @@ msgid "User name" msgstr "ユーザ名" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1875,7 +1873,7 @@ msgid "Completed before" msgstr "以前に完了" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1940,9 +1938,9 @@ msgstr "同期するファイルをアップロードするか、データファ msgid "Rack Elevations" msgstr "ラック図" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "電源" @@ -2042,7 +2040,7 @@ msgid "Change logging is not supported for this object type ({type})." msgstr "このオブジェクトタイプ ({type}) では変更ログはサポートされていません。" #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2102,7 +2100,7 @@ msgstr "タイプ" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2218,58 +2216,58 @@ msgstr "管理対象ファイル" msgid "managed files" msgstr "管理対象ファイル" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "予定日時" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "間隔" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "繰り返し間隔 (分)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "開始日時" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "完了日時" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "データ" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "エラー" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "ジョブ ID" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "ジョブ" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "ジョブ" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "このオブジェクトタイプにはジョブを割り当てられません ({type})。" -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "ジョブ終了のステータスが無効です。選択肢は以下のとおりです。 {choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "enqueue () は schedule_at と immediate の両方の値を指定して呼び出すことはできません。" @@ -2352,7 +2350,7 @@ msgstr "NetBoxの最大バージョン" msgid "No plugin data found" msgstr "プラグインデータが見つかりません" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "著者" @@ -2360,7 +2358,7 @@ msgstr "著者" msgid "Installed" msgstr "インストール済" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "認定済" @@ -2486,11 +2484,11 @@ msgstr "ジョブ {id} 停止されました。" msgid "Failed to stop job {id}" msgstr "ジョブを停止できませんでした {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "プラグインカタログを読み込めませんでした" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "プラグイン {name} が見つかりません" @@ -2510,7 +2508,7 @@ msgid "Staging" msgstr "ステージング" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "廃止" @@ -2574,7 +2572,7 @@ msgstr "廃止済" msgid "Millimeters" msgstr "ミリメートル" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "インチ" @@ -2588,15 +2586,15 @@ msgstr "前面から背面" msgid "Rear to front" msgstr "背面から前面" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2676,7 +2674,7 @@ msgid "Top to bottom" msgstr "上から下へ" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "パッシブ" @@ -2705,8 +2703,8 @@ msgid "Proprietary" msgstr "独自規格" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "その他" @@ -2719,24 +2717,24 @@ msgstr "ITA/International" msgid "Physical" msgstr "物理" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "仮想" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "無線" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "仮想インタフェース" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2745,27 +2743,27 @@ msgstr "仮想インタフェース" msgid "Bridge" msgstr "ブリッジ" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "リンクアグリゲーション (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "イーサネット (固定)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "イーサネット (モジュール)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "イーサネット (バックプレーン)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "セルラー" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2773,130 +2771,130 @@ msgstr "セルラー" msgid "Serial" msgstr "シリアル" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "同軸" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "スタック" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "半二重" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "全二重" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "自動" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "アクセス" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "タグ付き" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "タグ付き (全て)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "IEEE スタンダード" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "パッシブ 24V (2 ペア)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "パッシブ 24V (4ペア)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "パッシブ 48V (2 ペア)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "パッシブ 48V (4ペア)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "カッパー" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "光ファイバー" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "ファイバー" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "接続済" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "キロメートル" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "メートル" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "センチメートル" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "マイル" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "フィート" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "キログラム" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "グラム" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "ポンド" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "オンス" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "冗長" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "単相" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "三相" @@ -2927,7 +2925,7 @@ msgid "Parent site group (slug)" msgstr "親サイトグループ (slug)" #: netbox/dcim/filtersets.py:164 netbox/extras/filtersets.py:364 -#: netbox/ipam/filtersets.py:841 netbox/ipam/filtersets.py:993 +#: netbox/ipam/filtersets.py:843 netbox/ipam/filtersets.py:995 msgid "Group (ID)" msgstr "グループ (ID)" @@ -2985,15 +2983,15 @@ msgstr "ラックタイプ (ID)" #: netbox/dcim/filtersets.py:411 netbox/dcim/filtersets.py:892 #: netbox/dcim/filtersets.py:994 netbox/dcim/filtersets.py:1850 -#: netbox/ipam/filtersets.py:381 netbox/ipam/filtersets.py:493 -#: netbox/ipam/filtersets.py:1003 netbox/virtualization/filtersets.py:210 +#: netbox/ipam/filtersets.py:383 netbox/ipam/filtersets.py:495 +#: netbox/ipam/filtersets.py:1005 netbox/virtualization/filtersets.py:210 msgid "Role (ID)" msgstr "ロール (ID)" #: netbox/dcim/filtersets.py:417 netbox/dcim/filtersets.py:898 #: netbox/dcim/filtersets.py:1000 netbox/dcim/filtersets.py:1856 -#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:387 -#: netbox/ipam/filtersets.py:499 netbox/ipam/filtersets.py:1009 +#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:389 +#: netbox/ipam/filtersets.py:501 netbox/ipam/filtersets.py:1011 #: netbox/virtualization/filtersets.py:216 msgid "Role (slug)" msgstr "ロール (slug)" @@ -3142,7 +3140,7 @@ msgstr "クラスタグループ (ID)" msgid "Device model (slug)" msgstr "デバイスモデル (slug)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "奥行きをすべて使うか" @@ -3191,7 +3189,7 @@ msgstr "VDC (ID)" msgid "Device model" msgstr "デバイスモデル" -#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:632 +#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:634 #: netbox/vpn/filtersets.py:102 netbox/vpn/filtersets.py:401 msgid "Interface (ID)" msgstr "インタフェース (ID)" @@ -3205,8 +3203,8 @@ msgid "Module bay (ID)" msgstr "モジュールベイ (ID)" #: netbox/dcim/filtersets.py:1333 netbox/dcim/filtersets.py:1425 -#: netbox/ipam/filtersets.py:611 netbox/ipam/filtersets.py:851 -#: netbox/ipam/filtersets.py:1115 netbox/virtualization/filtersets.py:161 +#: netbox/ipam/filtersets.py:613 netbox/ipam/filtersets.py:853 +#: netbox/ipam/filtersets.py:1117 netbox/virtualization/filtersets.py:161 #: netbox/vpn/filtersets.py:379 msgid "Device (ID)" msgstr "デバイス (ID)" @@ -3215,8 +3213,8 @@ msgstr "デバイス (ID)" msgid "Rack (name)" msgstr "ラック (名前)" -#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:606 -#: netbox/ipam/filtersets.py:846 netbox/ipam/filtersets.py:1121 +#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:608 +#: netbox/ipam/filtersets.py:848 netbox/ipam/filtersets.py:1123 #: netbox/vpn/filtersets.py:374 msgid "Device (name)" msgstr "デバイス (名前)" @@ -3264,21 +3262,21 @@ msgstr "割当 VLAN" msgid "Assigned VID" msgstr "割当 VID" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 -#: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 -#: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 -#: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:318 +#: netbox/ipam/filtersets.py:329 netbox/ipam/filtersets.py:485 +#: netbox/ipam/filtersets.py:586 netbox/ipam/filtersets.py:597 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3297,19 +3295,19 @@ msgstr "割当 VID" msgid "VRF" msgstr "VRF" -#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:322 -#: netbox/ipam/filtersets.py:333 netbox/ipam/filtersets.py:489 -#: netbox/ipam/filtersets.py:590 netbox/ipam/filtersets.py:601 +#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:324 +#: netbox/ipam/filtersets.py:335 netbox/ipam/filtersets.py:491 +#: netbox/ipam/filtersets.py:592 netbox/ipam/filtersets.py:603 msgid "VRF (RD)" msgstr "VRF (RD)" -#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1030 +#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1032 #: netbox/vpn/filtersets.py:342 msgid "L2VPN (ID)" msgstr "L2VPN (ID)" #: netbox/dcim/filtersets.py:1630 netbox/dcim/forms/filtersets.py:1433 -#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1036 +#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1038 #: netbox/ipam/forms/filtersets.py:518 netbox/ipam/tables/vlans.py:137 #: netbox/templates/dcim/interface.html:93 netbox/templates/ipam/vlan.html:66 #: netbox/templates/vpn/l2vpntermination.html:12 @@ -3345,7 +3343,7 @@ msgid "LAG interface (ID)" msgstr "LAG インタフェース (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "仮想デバイスコンテキスト" @@ -3419,7 +3417,7 @@ msgstr "タグ" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3434,38 +3432,38 @@ msgid "" "created.)" msgstr "英数字の範囲が使用できます。(作成する名前の数と一致する必要があります)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "連絡先名" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "連絡先電話番号" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "連絡先電子メール" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "タイムゾーン" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3475,58 +3473,59 @@ msgstr "タイムゾーン" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "メーカ" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "フォームファクタ" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "幅" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "高さ (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "降順" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "外形の幅" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "外形の奥行" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "外形の単位" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "取り付け奥行き" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3537,10 +3536,10 @@ msgstr "取り付け奥行き" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3549,61 +3548,61 @@ msgstr "取り付け奥行き" msgid "Weight" msgstr "重量" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "最大重量" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "重量単位" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "ラックタイプ" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "外形寸法" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "寸法" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "ナンバリング" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3631,45 +3630,50 @@ msgstr "ナンバリング" msgid "Role" msgstr "ロール" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "ラックタイプ" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "シリアル番号" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "アセットタグ" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "エアフロー" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3679,64 +3683,64 @@ msgstr "エアフロー" msgid "Rack" msgstr "ラック" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "ハードウェア" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "デフォルトプラットフォーム" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "パーツ番号" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "ユニット数" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "ラック利用率に含めない" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "デバイスタイプ" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "モジュールタイプ" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "シャーシ" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "VMのロール" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3747,19 +3751,19 @@ msgstr "VMのロール" msgid "Config template" msgstr "設定テンプレート" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "デバイスタイプ" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "デバイスロール" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3773,14 +3777,36 @@ msgstr "デバイスロール" msgid "Platform" msgstr "プラットフォーム" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "クラスタ" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3790,9 +3816,9 @@ msgstr "プラットフォーム" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3801,10 +3827,10 @@ msgstr "プラットフォーム" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3831,7 +3857,7 @@ msgstr "プラットフォーム" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3841,23 +3867,28 @@ msgstr "プラットフォーム" msgid "Device" msgstr "デバイス" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "設定" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "仮想化" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "モジュールタイプ" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3875,109 +3906,109 @@ msgstr "モジュールタイプ" msgid "Label" msgstr "ラベル" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "長さ" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "長さの単位" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "ドメイン" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "電源盤" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "供給電源" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "電力相" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "電圧" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "アンペア数" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "最大使用率" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "最大消費電力" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "最大消費電力 (ワット)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "割当電力" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "割当消費電力 (ワット)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "電源ポート" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "供給端子" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "管理のみ" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "PoE モード" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "PoE タイプ" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "無線ロール" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -3991,17 +4022,17 @@ msgstr "無線ロール" msgid "Module" msgstr "モジュール" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "LAG" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "仮想デバイスコンテキスト" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4010,7 +4041,7 @@ msgstr "仮想デバイスコンテキスト" msgid "Speed" msgstr "速度" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4024,76 +4055,88 @@ msgstr "速度" msgid "Mode" msgstr "モード" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "VLAN グループ" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "タグなし VLAN" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "タグ付き VLAN" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "タグ付 VLAN の追加" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "タグ付 VLAN の削除" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "無線 LAN グループ" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "無線 LAN" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "アドレス" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "オペレーション" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "関連インタフェース" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "802.1Q スイッチング" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "追加/削除" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "VLAN を割り当てるには、インタフェースモードを指定する必要があります" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "アクセスインタフェースにはタグ付き VLAN を割り当てることはできません。" @@ -4119,9 +4162,9 @@ msgstr "割当グループ" msgid "available options" msgstr "使用可能なオプション" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4143,15 +4186,15 @@ msgstr "このラックタイプのメーカ" msgid "The lowest-numbered position in the rack" msgstr "ラック内の一番小さい番号の位置" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "レール間の幅 (インチ)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "外形寸法の単位" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "重量の単位" @@ -4163,240 +4206,230 @@ msgstr "割当テナント名" msgid "Name of assigned role" msgstr "割当ロール名" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "ラックタイプモデル" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "エアフロー" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "ラックタイプを指定しない場合は、幅を設定する必要があります。" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "ラックタイプを指定しない場合は U 高さを設定する必要があります。" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "親サイト" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "ラックのロケーション (存在する場合)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "単位" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "カンマ区切りのユニット番号" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "製造メーカ" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "デフォルトのプラットフォーム (オプション)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "デバイス重量" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "デバイス重量の単位" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "モジュール重量" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "モジュール重量の単位" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "プラットフォーム割り当てをこのメーカに限定する" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "割当ロール" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "デバイスタイプメーカ" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "デバイスタイプモデル" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "割当プラットフォーム" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "バーチャルシャーシ" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "クラスタ" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "仮想化クラスタ" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "割当ロケーション (存在する場合)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "割当ラック (存在する場合)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "面" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "ラック取付面" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "親デバイス (子デバイス用)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "デバイスベイ" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "取付られているデバイスベイ (子デバイス用)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "取付られているデバイス" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "モジュールベイ" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "取付られているモジュールベイ" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "モジュールタイプ" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "構成要素を複製" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" msgstr "関連する構成要素を自動的に登録 (デフォルト)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "既存の構成要素を採用" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "既存の構成要素を採用" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "ポートタイプ" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "ポート速度 (bps)" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "コンセントタイプ" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "このコンセントに給電する電源ポート" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "電気位相 (三相回路用)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "親インタフェース" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "ブリッジインタフェース" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Lag" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "親 LAG インタフェース" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "VDC" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "VDC 名をコンマで区切り、二重引用符で囲みます。例:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "物理媒体" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "デュプレックス" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "PoEモード" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "PoEタイプ" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "IEEE 802.1Q モード(L2 インタフェース用)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4404,172 +4437,172 @@ msgstr "IEEE 802.1Q モード(L2 インタフェース用)" msgid "Assigned VRF" msgstr "割当 VRF" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "RF ロール" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "無線ロール (AP/ステーション)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} デバイスには割り当てられていません {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "背面ポート" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "対応する背面ポート" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "物理媒体の分類" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "取付済みデバイス" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "このベイ内に取付された子デバイス" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "子デバイスが見つかりません。" -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "親在庫品目" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "構成要素タイプ" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "構成要素タイプ" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "コンポーネント名" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "構成要素名" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "コンポーネントが見つかりません: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "サイド A デバイス" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "デバイス名" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "サイド A タイプ" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "終了タイプ" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "サイド A 名" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "終端名" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "サイド B デバイス" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "サイド B タイプ" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "サイド B 名" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "接続ステータス" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "サイド {side_upper}: {device} {termination_object} は既に接続されています" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} サイドターミネーションが見つかりません: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "マスター" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "マスターデバイス" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "親サイトの名前" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "上流電源盤" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "プライマリまたは冗長" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "電源タイプ (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "単相または三相" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "プライマリ IPv4" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "マスク付きの IPv4 アドレス (例:1.2.3.4/24)" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "プライマリ IPv6" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "プレフィックス長のある IPv6 アドレス、例:2001: db8:: 1/64" @@ -4652,10 +4685,6 @@ msgstr "親グループ" msgid "Facility" msgstr "ファシリティ" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "ラックタイプ" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "機能" @@ -4692,7 +4721,7 @@ msgid "Has virtual device contexts" msgstr "仮想デバイスコンテキストがある" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "クラスタグループ" @@ -4731,7 +4760,7 @@ msgstr "種類" msgid "Mgmt only" msgstr "管理のみ" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4831,36 +4860,49 @@ msgstr "このモジュールタイプに関連する構成要素を自動的に msgid "Characteristics" msgstr "特性" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" +"英数字の範囲は一括作成に対応しています。1 つの範囲内で大文字と小文字や文字種の混在は対応していません (例: " +"1[ge,xe]-0/0/[0-9]1)。トークン " +"{module}が存在する場合、新しいモジュールを作成する際に、自動的に位置の値に置き換えられます。" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "コンソールポートテンプレート" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "コンソールサーバポートテンプレート" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "全面ポートテンプレート" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "インタフェーステンプレート" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "電源コンセントテンプレート" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "電源ポートテンプレート" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "背面ポートテンプレート" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4884,7 +4926,7 @@ msgstr "背面ポートテンプレート" msgid "Interface" msgstr "インタフェース" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4892,14 +4934,14 @@ msgstr "インタフェース" msgid "Console Port" msgstr "コンソールポート" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "コンソールサーバポート" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4910,7 +4952,7 @@ msgstr "コンソールサーバポート" msgid "Front Port" msgstr "前面ポート" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4923,74 +4965,74 @@ msgstr "前面ポート" msgid "Rear Port" msgstr "背面ポート" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "電源ポート" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "電源コンセント" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "構成要素割り当て" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "在庫品目は1つの構成要素にのみ割り当てることができます。" -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "LAG インタフェース" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "割り当て可能な VLAN をグループ別にフィルタリングします。" -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "子デバイス" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." msgstr "まず子デバイスを作成し、親デバイスのサイトとラックに割り当てる必要があります。" -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "コンソールポート" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "コンソールサーバポート" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "前面ポート" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "電源コンセント" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "在庫品目" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "在庫品目ロール" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5004,12 +5046,12 @@ msgid "" msgstr "パターンは {value_count} 個の値を示す範囲を指定しますが、 {pattern_count} 個の値が必要です。" #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "背面ポート" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "前面ポートごとに背面ポート 1 つ割り当てます。" @@ -5022,14 +5064,7 @@ msgstr "" "前面ポートテンプレートの数 ({frontport_count}) " "は選択した背面ポートの数({rearport_count})と一致する必要があります。" -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "文字列 {module} は(存在する場合)割当モジュールの位置に置き換えられます。" - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5037,24 +5072,24 @@ msgid "" msgstr "" "前面ポートの数 ({frontport_count}) は選択した背面ポートの数 ({rearport_count}) と一致する必要があります。" -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "メンバー" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "初期ポジション" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." msgstr "最初のメンバーのポジション。メンバーが増えるごとに 1 ずつ増えます。" -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "最初の VC メンバーのポジションを指定する必要があります。" @@ -5941,12 +5976,12 @@ msgstr "ポジション (U)" msgid "rack face" msgstr "ラックフェイス" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "プライマリ IPv4" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "プライマリ IPv6" @@ -6109,55 +6144,55 @@ msgid "" "device ({device})." msgstr "モジュールは、割当デバイスに属するモジュールベイ内に取り付ける必要があります ({device})。" -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "ドメイン" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "バーチャルシャーシ" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "選択したマスター ({master}) はこの仮想シャーシに割り当てられていません。" -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " "form a cross-chassis LAG interfaces." msgstr "バーチャルシャーシ{self}を削除できません 。クロスシャーシ LAG インタフェースを形成するメンバーインタフェースがあります。" -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "識別子" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "親デバイスに固有の数値識別子" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "コメント" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "仮想デバイスコンテキスト" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "仮想デバイスコンテキスト" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip}は IPv{family}アドレスではありません。" -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "プライマリ IP アドレスは、割当デバイスのインタフェースに属している必要があります。" @@ -6341,7 +6376,7 @@ msgstr "ローカル識別子" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "機能的ロール" @@ -6546,7 +6581,7 @@ msgstr "到達可能" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "デバイス" @@ -6575,8 +6610,8 @@ msgid "Site Group" msgstr "サイトグループ" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6627,20 +6662,20 @@ msgid "Power outlets" msgstr "電源コンセント" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "インタフェース" @@ -6666,8 +6701,8 @@ msgid "Module Bay" msgstr "モジュールベイ" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6696,7 +6731,7 @@ msgstr "最大電力 (W)" msgid "Allocated draw (W)" msgstr "割当電力 (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6792,87 +6827,87 @@ msgstr "U 高さ" msgid "Instances" msgstr "インスタンス" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "コンソールポート" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "コンソールサーバポート" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "電源ポート" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "電源コンセント" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "前面ポート" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "背面ポート" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "デバイスベイ" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "モジュールベイ" @@ -6921,7 +6956,7 @@ msgstr "スペース" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -6931,28 +6966,28 @@ msgstr "サイト" msgid "Test case must set peer_termination_type" msgstr "テストケースは peer_termination_type を設定する必要があります" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "切断されました {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "予約" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "ラック搭載でないデバイス" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "コンフィグコンテキスト" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "レンダーコンフィグ" @@ -6963,35 +6998,35 @@ msgstr "テンプレートをレンダリング中にエラーが発生しまし #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "仮想マシン" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "インストール済みデバイス {device} イン・ベイ {device_bay}。" -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "削除されたデバイス {device} ベイから {device_bay}。" -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "子ども" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "メンバー追加 {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "マスターデバイスを削除できません {device} バーチャルシャーシから。" -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "削除済み {device} バーチャルシャーシから {chassis}" @@ -7174,7 +7209,6 @@ msgstr "更新" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -7982,19 +8016,19 @@ msgstr "スクリプトの実行をスケジュールする" msgid "Interval at which this script is re-run (in minutes)" msgstr "実行される間隔 (分単位)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "データベースの変更は自動的に元に戻されました。" -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "スクリプトがエラーで中止されました: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "例外が発生しました: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "エラーにより、データベースの変更が元に戻されました。" @@ -8984,7 +9018,7 @@ msgstr "削除したウィジェット: " msgid "Error deleting widget: " msgstr "ウィジェットの削除中にエラーが発生しました: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "スクリプトを実行できません:RQ ワーカープロセスが実行されていません。" @@ -9100,129 +9134,129 @@ msgstr "L2VPN のエクスポート" msgid "Exporting L2VPN (identifier)" msgstr "L2VPN (識別子) のエクスポート" -#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:281 +#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:283 #: netbox/ipam/forms/model_forms.py:229 netbox/ipam/tables/ip.py:212 #: netbox/templates/ipam/prefix.html:12 msgid "Prefix" msgstr "プレフィックス" #: netbox/ipam/filtersets.py:159 netbox/ipam/filtersets.py:198 -#: netbox/ipam/filtersets.py:221 +#: netbox/ipam/filtersets.py:223 msgid "RIR (ID)" msgstr "RIR (ID)" #: netbox/ipam/filtersets.py:165 netbox/ipam/filtersets.py:204 -#: netbox/ipam/filtersets.py:227 +#: netbox/ipam/filtersets.py:229 msgid "RIR (slug)" msgstr "RIR (slug)" -#: netbox/ipam/filtersets.py:285 +#: netbox/ipam/filtersets.py:287 msgid "Within prefix" msgstr "プレフィックス内" -#: netbox/ipam/filtersets.py:289 +#: netbox/ipam/filtersets.py:291 msgid "Within and including prefix" msgstr "プレフィックス内およびプレフィックスを含む" -#: netbox/ipam/filtersets.py:293 +#: netbox/ipam/filtersets.py:295 msgid "Prefixes which contain this prefix or IP" msgstr "このプレフィックス / IP を含むプレフィックス" -#: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/filtersets.py:306 netbox/ipam/filtersets.py:574 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "マスクの長さ" -#: netbox/ipam/filtersets.py:373 netbox/vpn/filtersets.py:427 +#: netbox/ipam/filtersets.py:375 netbox/vpn/filtersets.py:427 msgid "VLAN (ID)" msgstr "VLAN (ID)" -#: netbox/ipam/filtersets.py:377 netbox/vpn/filtersets.py:422 +#: netbox/ipam/filtersets.py:379 netbox/vpn/filtersets.py:422 msgid "VLAN number (1-4094)" msgstr "VLAN 番号 (1-4094)" -#: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:473 netbox/ipam/filtersets.py:477 +#: netbox/ipam/filtersets.py:569 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" msgstr "アドレス" -#: netbox/ipam/filtersets.py:479 +#: netbox/ipam/filtersets.py:481 msgid "Ranges which contain this prefix or IP" msgstr "このプレフィックス / IP を含む範囲" -#: netbox/ipam/filtersets.py:507 netbox/ipam/filtersets.py:563 +#: netbox/ipam/filtersets.py:509 netbox/ipam/filtersets.py:565 msgid "Parent prefix" msgstr "親プレフィックス" -#: netbox/ipam/filtersets.py:616 netbox/ipam/filtersets.py:856 -#: netbox/ipam/filtersets.py:1131 netbox/vpn/filtersets.py:385 +#: netbox/ipam/filtersets.py:618 netbox/ipam/filtersets.py:858 +#: netbox/ipam/filtersets.py:1133 netbox/vpn/filtersets.py:385 msgid "Virtual machine (name)" msgstr "仮想マシン (名前)" -#: netbox/ipam/filtersets.py:621 netbox/ipam/filtersets.py:861 -#: netbox/ipam/filtersets.py:1125 netbox/virtualization/filtersets.py:282 +#: netbox/ipam/filtersets.py:623 netbox/ipam/filtersets.py:863 +#: netbox/ipam/filtersets.py:1127 netbox/virtualization/filtersets.py:282 #: netbox/virtualization/filtersets.py:321 netbox/vpn/filtersets.py:390 msgid "Virtual machine (ID)" msgstr "仮想マシン (ID)" -#: netbox/ipam/filtersets.py:627 netbox/vpn/filtersets.py:97 +#: netbox/ipam/filtersets.py:629 netbox/vpn/filtersets.py:97 #: netbox/vpn/filtersets.py:396 msgid "Interface (name)" msgstr "インタフェース (名前)" -#: netbox/ipam/filtersets.py:638 netbox/vpn/filtersets.py:108 +#: netbox/ipam/filtersets.py:640 netbox/vpn/filtersets.py:108 #: netbox/vpn/filtersets.py:407 msgid "VM interface (name)" msgstr "VM インタフェース (名前)" -#: netbox/ipam/filtersets.py:643 netbox/vpn/filtersets.py:113 +#: netbox/ipam/filtersets.py:645 netbox/vpn/filtersets.py:113 msgid "VM interface (ID)" msgstr "VM インタフェース (ID)" -#: netbox/ipam/filtersets.py:648 +#: netbox/ipam/filtersets.py:650 msgid "FHRP group (ID)" msgstr "FHRP グループ (ID)" -#: netbox/ipam/filtersets.py:652 +#: netbox/ipam/filtersets.py:654 msgid "Is assigned to an interface" msgstr "インタフェースに割り当てられているか" -#: netbox/ipam/filtersets.py:656 +#: netbox/ipam/filtersets.py:658 msgid "Is assigned" msgstr "割当済みか" -#: netbox/ipam/filtersets.py:668 +#: netbox/ipam/filtersets.py:670 msgid "Service (ID)" msgstr "サービス (ID)" -#: netbox/ipam/filtersets.py:673 +#: netbox/ipam/filtersets.py:675 msgid "NAT inside IP address (ID)" msgstr "NAT 内部の IP アドレス (ID)" -#: netbox/ipam/filtersets.py:1041 netbox/ipam/forms/bulk_import.py:322 +#: netbox/ipam/filtersets.py:1043 netbox/ipam/forms/bulk_import.py:322 msgid "Assigned interface" msgstr "割当インタフェース" -#: netbox/ipam/filtersets.py:1046 +#: netbox/ipam/filtersets.py:1048 msgid "Assigned VM interface" msgstr "割り当てられた VM インターフェイス" -#: netbox/ipam/filtersets.py:1136 +#: netbox/ipam/filtersets.py:1138 msgid "IP address (ID)" msgstr "IP アドレス (ID)" -#: netbox/ipam/filtersets.py:1142 netbox/ipam/models/ip.py:788 +#: netbox/ipam/filtersets.py:1144 netbox/ipam/models/ip.py:788 msgid "IP address" msgstr "IP アドレス" -#: netbox/ipam/filtersets.py:1167 +#: netbox/ipam/filtersets.py:1169 msgid "Primary IPv4 (ID)" msgstr "プライマリ IPv4 (ID)" -#: netbox/ipam/filtersets.py:1172 +#: netbox/ipam/filtersets.py:1174 msgid "Primary IPv6 (ID)" msgstr "プライマリ IPv6 (ID)" @@ -9255,16 +9289,16 @@ msgstr "CIDR マスク (例:/24) が必要です。" msgid "Address pattern" msgstr "アドレスパターン" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "重複を禁止する" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "非公開です" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9278,20 +9312,20 @@ msgstr "非公開です" msgid "RIR" msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "追加日" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "VLAN グループ" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9304,32 +9338,32 @@ msgstr "VLAN グループ" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "プレフィックス長" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "プールです" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "すべて使用済として扱う" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "VLAN アサイメント" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "DNS ネーム" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9337,12 +9371,12 @@ msgstr "DNS ネーム" msgid "Protocol" msgstr "プロトコル" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "グループ ID" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9354,12 +9388,12 @@ msgstr "グループ ID" msgid "Authentication type" msgstr "認証タイプ" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "認証キー" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9371,26 +9405,26 @@ msgstr "認証キー" msgid "Authentication" msgstr "認証" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "スコープタイプ" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "VLAN ID の範囲" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "スコープ" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "VLAN ID の範囲" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "サイトとグループ" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9417,8 +9451,8 @@ msgstr "VLAN のグループ (存在する場合)" msgid "Parent device of assigned interface (if any)" msgstr "割当インタフェースの親デバイス (存在する場合)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9444,39 +9478,59 @@ msgstr "プライマリか" msgid "Make this the primary IP for the assigned device" msgstr "割当デバイスのプライマリ IP アドレスにする" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "帯域外" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "これを、割当デバイスの帯域外 IP アドレスとして指定します。" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "デバイスまたは仮想マシンが指定されていないため、プライマリ IP として設定できません" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "デバイスが指定されていないため、帯域外IP として設定できません" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "仮想マシンには帯域外 IP を設定できません" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "インタフェースが指定されていないため、プライマリ IP として設定できません" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "インターフェイスが指定されていないため、帯域外IP として設定できません" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "認証タイプ" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "スコープの種類 (アプリとモデル)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "割当 VLAN グループ" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "IP プロトコル" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "VM に割り当てられていない場合は必須" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "デバイスに割り当てられていない場合は必須" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} はこのデバイス/VM には割り当てられていません。" @@ -9558,7 +9612,7 @@ msgstr "インタフェースに割当済" msgid "DNS Name" msgstr "DNS名" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9569,13 +9623,13 @@ msgstr "VLAN" msgid "Contains VLAN ID" msgstr "VLAN ID が含まれています" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "VLAN ID" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9586,7 +9640,7 @@ msgstr "VLAN ID" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9615,8 +9669,8 @@ msgstr "サイト/VLAN 割り当て" msgid "IP Range" msgstr "IP アドレス範囲" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "FHRP グループ" @@ -9625,75 +9679,87 @@ msgstr "FHRP グループ" msgid "Make this the primary IP for the device/VM" msgstr "デバイス/VMのプライマリIPにする" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "これをデバイスの帯域外IPにする" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "NAT IP (インサイド)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "IP アドレスは 1 つのオブジェクトにのみ割り当てることができます。" -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" -msgstr "親オブジェクトのプライマリ IP として指定されている間は IP アドレスを再割り当てできません" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" +msgstr "親デバイス/VMのプライマリ IP アドレスを再割り当てできません" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "親デバイスに帯域外IP アドレスを再割り当てできません" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "プライマリ IP として指定できるのは、インタフェースに割り当てられた IP アドレスのみです。" -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "デバイスの帯域外 IP として指定できるのは、デバイスインタフェイスに割り当てられた IP アドレスのみです。" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "仮想 IP アドレス" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "既に割り当てられています" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "VLAN ID" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "子 VLAN" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." msgstr "カンマ区切りのポート番号のリスト。範囲はハイフンを使用して指定できます。" -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "サービステンプレート" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "ポート (s)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "サービス" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "サービステンプレート" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "テンプレートから" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "カスタム" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "サービステンプレートを使用しない場合は、名前、プロトコル、およびポートを指定する必要があります。" @@ -9965,6 +10031,12 @@ msgstr "{ip} はブロードキャストアドレスのため、インタフェ msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "重複した IP アドレスが見つかりました {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "親オブジェクトのプライマリ IP として指定されている間は IP アドレスを再割り当てできません" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "SLAAC ステータスを割り当てることができるのは IPv6 アドレスのみです" @@ -10015,45 +10087,55 @@ msgstr "scope_id なしでscope_typeを設定することはできません。" msgid "Cannot set scope_id without scope_type." msgstr "scope_typeなしでscope_idを設定することはできません。" -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "範囲の開始 VLAN ID ({value}) は{minimum}以下であってはなりません " + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "範囲の終了 VLAN ID ({value}) は{maximum}を超えることはできません " + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "範囲の終了 VLAN ID は、開始 VLAN ID ({range})以上である必要があります" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "範囲は重複できません。" -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "子供 VID の最大数は、子供 VID の最小値以上でなければなりません ({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "この VLAN が割り当てられているサイト (存在する場合)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "VLAN グループ (オプション)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "数値によるVLAN ID (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "この VLAN の動作ステータス" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "この VLAN の主な機能" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " "site {site}." msgstr "VLANはグループ{group}に割り当てられています (スコープ: {scope}) サイト{site}への割り当てはできません 。" -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "VID は範囲内にある必要があります {ranges} グループ内の VLAN 用 {group}" @@ -10806,17 +10888,12 @@ msgstr "IPsec ポリシ" msgid "IPSec Profiles" msgstr "IPsec プロファイル" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "仮想化" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "仮想ディスク" @@ -10978,7 +11055,7 @@ msgstr "システム" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11220,19 +11297,19 @@ msgstr "選択したエクスポートテンプレートをレンダリング中 msgid "Row {i}: Object with ID {id} does not exist" msgstr "行 {i}: ID {id}のオブジェクトは存在しません" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "いいえ {object_type} が選ばれました。" -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "名前が変更されました {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "削除済み {count} {object_type}" @@ -11264,7 +11341,7 @@ msgstr "同期済み {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} はget_children () を実装する必要があります" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11606,9 +11683,7 @@ msgid "Circuit Type" msgstr "回線タイプ" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11619,7 +11694,6 @@ msgstr "追加" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -11907,35 +11981,35 @@ msgstr "日々" msgid "Indefinite" msgstr "無期限" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "未インストール" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "概要" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "インストール" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "プラグイン詳細" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "サマリー" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "ライセンス" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "バージョン履歴" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "ローカルインストール手順" @@ -12276,8 +12350,8 @@ msgstr "サービスを追加" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12350,20 +12424,24 @@ msgstr "コンフィグ" msgid "Context Data" msgstr "コンテキストデータ" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "レンダリング設定" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "ダウンロード" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "設定テンプレートが見つかりません" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "エラーレンダリングテンプレート" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "このデバイスには設定テンプレートが割り当てられていません。" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12385,7 +12463,6 @@ msgid "Local Config Context Data" msgstr "ローカル設定コンテキストデータ" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12432,12 +12509,12 @@ msgid "VM Role" msgstr "VMのロール" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "モデル名" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "パーツ番号" @@ -12576,7 +12653,7 @@ msgstr "MAC アドレス" msgid "Wireless Link" msgstr "無線リンク" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "ピア" @@ -13181,7 +13258,7 @@ msgstr "スクリプトを実行する権限がありません" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "スクリプトを実行" @@ -13194,27 +13271,32 @@ msgstr "スクリプトのロード中にエラーが発生しました" msgid "Script no longer exists in the source file." msgstr "スクリプトはソースファイルに存在しなくなりました。" -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "ラストラン" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "スクリプトはソースファイルに存在しなくなりました" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "決して" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "もう一度実行" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "モジュール%(module)sからスクリプトを読み込めませんでした " + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "スクリプトが見つかりません" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13531,7 +13613,7 @@ msgstr "すべての通知" msgid "Select" msgstr "選択" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "リセット" @@ -14010,6 +14092,10 @@ msgstr "リソース" msgid "Add Virtual Disk" msgstr "仮想ディスクを追加" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "このVMには構成テンプレートが割り当てられていません。" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15037,13 +15123,13 @@ msgid "Memory (MB)" msgstr "メモリ (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "ディスク (GB)" +msgid "Disk (MB)" +msgstr "ディスク (MB)" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "サイズ (GB)" +msgid "Size (MB)" +msgstr "サイズ (MB)" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15107,7 +15193,7 @@ msgstr "クラスタグループ" #: netbox/virtualization/models/clusters.py:121 msgid "cluster" -msgstr "集まる" +msgstr "クラスタ" #: netbox/virtualization/models/clusters.py:122 msgid "clusters" @@ -15212,68 +15298,80 @@ msgstr "仮想ディスク" msgid "virtual disks" msgstr "仮想ディスク" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "追加しました {count} デバイスをクラスタに {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "削除済み {count} クラスターのデバイス {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPsec-トランスポート" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec-トンネル" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP-in-IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GRE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "WireGuard" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "OpenVPN" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "L2TP" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "PPTP" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "ハブ" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "スポーク" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "アグレッシブ" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "メイン" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "事前共有キー" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "証明書" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "RSA シグネチャ" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "DSA シグネチャ" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15282,23 +15380,27 @@ msgstr "DSA シグネチャ" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "グループ {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "イーサネットプライベート LAN" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "イーサネット仮想プライベート LAN" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "イーサネットプライベートツリー" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "イーサネット仮想プライベートツリー" diff --git a/netbox/translations/nl/LC_MESSAGES/django.mo b/netbox/translations/nl/LC_MESSAGES/django.mo index ca93c83dc..1af769697 100644 Binary files a/netbox/translations/nl/LC_MESSAGES/django.mo and b/netbox/translations/nl/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/nl/LC_MESSAGES/django.po b/netbox/translations/nl/LC_MESSAGES/django.po index 9a9392642..8a26ba015 100644 --- a/netbox/translations/nl/LC_MESSAGES/django.po +++ b/netbox/translations/nl/LC_MESSAGES/django.po @@ -8,6 +8,7 @@ # deku_m, 2024 # Peter Mulder , 2024 # Jeremy Stretch, 2024 +# Jorg de Jong, 2024 # Sebastian Berm, 2024 # #, fuzzy @@ -15,7 +16,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" "Last-Translator: Sebastian Berm, 2024\n" "Language-Team: Dutch (https://app.transifex.com/netbox-community/teams/178115/nl/)\n" @@ -92,8 +93,8 @@ msgstr "Je wachtwoord is succesvol gewijzigd." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -106,7 +107,7 @@ msgstr "Provisioning" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -117,8 +118,8 @@ msgid "Active" msgstr "Actief" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Offline" @@ -131,7 +132,7 @@ msgstr "Deprovisioning" msgid "Decommissioned" msgstr "Buiten gebruik" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Primair" @@ -204,12 +205,12 @@ msgstr "Sitegroep (slug)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -218,18 +219,17 @@ msgstr "Sitegroep (slug)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -337,10 +337,10 @@ msgstr "Eindpunt A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -392,7 +392,7 @@ msgstr "Circuitgroep (slug)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -407,33 +407,33 @@ msgstr "ASN's" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -442,7 +442,7 @@ msgstr "ASN's" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -457,7 +457,7 @@ msgstr "ASN's" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -477,7 +477,7 @@ msgstr "ASN's" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -570,10 +570,10 @@ msgid "Service ID" msgstr "Service-ID" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -594,16 +594,16 @@ msgstr "Kleur" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -658,14 +658,14 @@ msgstr "Provideraccount" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -674,13 +674,13 @@ msgstr "Provideraccount" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -691,7 +691,7 @@ msgstr "Provideraccount" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -727,30 +727,30 @@ msgstr "Status" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -820,11 +820,11 @@ msgstr "Serviceparameters" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -856,11 +856,11 @@ msgstr "Poortsnelheid (Kbps)" msgid "Upstream speed (Kbps)" msgstr "Upstreamsnelheid (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Markeren als verbonden" @@ -907,10 +907,10 @@ msgstr "Soort circuit" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -920,13 +920,13 @@ msgstr "Operationele status" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -951,12 +951,12 @@ msgstr "Netwerkprovider" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -973,9 +973,9 @@ msgstr "Netwerkprovider" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1004,8 +1004,8 @@ msgid "Contacts" msgstr "Contacten" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1013,13 +1013,12 @@ msgstr "Contacten" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1032,16 +1031,16 @@ msgid "Region" msgstr "Regio" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1053,7 +1052,7 @@ msgstr "Sitegroep" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1092,9 +1091,9 @@ msgstr "Account" msgid "Term Side" msgstr "Termzijde" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1104,11 +1103,11 @@ msgstr "Opdracht" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1180,20 +1179,20 @@ msgid "Unique circuit ID" msgstr "Uniek circuit-ID" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "-status" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "geïnstalleerd" @@ -1315,11 +1314,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1330,7 +1329,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1418,7 +1417,7 @@ msgstr "providernetwerken" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1429,7 +1428,7 @@ msgstr "providernetwerken" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1460,7 +1459,7 @@ msgstr "providernetwerken" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1626,7 +1625,7 @@ msgstr "Voltooid" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Mislukt" @@ -1693,7 +1692,7 @@ msgid "Cancelled" msgstr "Geannuleerd" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Lokaal" @@ -1780,8 +1779,8 @@ msgid "User name" msgstr "Gebruikersnaam" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1885,7 +1884,7 @@ msgid "Completed before" msgstr "Eerder voltooid" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1953,9 +1952,9 @@ msgstr "" msgid "Rack Elevations" msgstr "Rackverhogingen" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Stroom" @@ -2057,7 +2056,7 @@ msgstr "" "objecttype ({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2117,7 +2116,7 @@ msgstr "type" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2237,60 +2236,60 @@ msgstr "beheerd bestand" msgid "managed files" msgstr "beheerde bestanden" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "gepland" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "interval" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Herhalingsinterval (in minuten)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "gestart" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "voltooid" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "gegevens" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "fout" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "taak-ID" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "taak" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "taken" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "Taken kunnen niet worden toegewezen aan dit objecttype ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "" "Ongeldige status voor beëindiging van het dienstverband. De keuzes zijn: " "{choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" @@ -2375,7 +2374,7 @@ msgstr "Maximale NetBox-versie" msgid "No plugin data found" msgstr "Geen plugin-gegevens gevonden" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Auteur" @@ -2383,7 +2382,7 @@ msgstr "Auteur" msgid "Installed" msgstr "Geïnstalleerd" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Gecertificeerd" @@ -2509,11 +2508,11 @@ msgstr "Baan {id} is gestopt." msgid "Failed to stop job {id}" msgstr "Kon de taak niet stoppen {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "De catalogus met plug-ins kon niet worden geladen" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Plug-in {name} niet gevonden" @@ -2533,7 +2532,7 @@ msgid "Staging" msgstr "Klaarzetten" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Ontmanteling" @@ -2597,7 +2596,7 @@ msgstr "Verouderd" msgid "Millimeters" msgstr "Millimeters" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "Inches" @@ -2611,15 +2610,15 @@ msgstr "Van voor naar achter" msgid "Rear to front" msgstr "Van achter naar voren" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2699,7 +2698,7 @@ msgid "Top to bottom" msgstr "Van boven naar beneden" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Passief" @@ -2728,8 +2727,8 @@ msgid "Proprietary" msgstr "Gepatenteerd" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Andere" @@ -2742,24 +2741,24 @@ msgstr "ITA/internationaal" msgid "Physical" msgstr "Fysiek" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Virtueel" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Draadloos" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Virtuele interfaces" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2768,27 +2767,27 @@ msgstr "Virtuele interfaces" msgid "Bridge" msgstr "Bridge" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Linkaggregatiegroep (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (vast)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (modulair)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (backplane)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Mobiel" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2796,130 +2795,130 @@ msgstr "Mobiel" msgid "Serial" msgstr "Serienummer" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Coaxiaal" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "Stapelen" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Half" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Volledig" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Auto" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Toegang" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Getagd" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Getagd (Alles)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "IEEE-standaard" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "Passief 24V (2 paren)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "Passief 24V (4 paren)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "Passief 48V (2 paren)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "Passief 48V (4 paren)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Koper" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Glasvezel" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Vezel" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Verbonden" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Kilometers" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Meters" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Centimeters" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Mijlen" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Feet" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Kilogrammen" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Gram" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "Ponden" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Ons" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Redundant" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Een fase" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Drie fase" @@ -3165,7 +3164,7 @@ msgstr "Clustergroep (ID)" msgid "Device model (slug)" msgstr "Apparaatmodel (slug)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "Is volledige diepte" @@ -3287,21 +3286,21 @@ msgstr "Toegewezen VLAN" msgid "Assigned VID" msgstr "Toegewezen VID" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3368,7 +3367,7 @@ msgid "LAG interface (ID)" msgstr "LAG-interface (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Context van het virtuele apparaat" @@ -3442,7 +3441,7 @@ msgstr "Labels" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3459,38 +3458,38 @@ msgstr "" "Alfanumerieke reeksen worden ondersteund. (Moet overeenkomen met het aantal " "namen dat wordt aangemaakt.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Naam van de contactpersoon" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Telefoonnummer contacteren" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "E-mailadres voor contact" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Tijdzone" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3500,58 +3499,59 @@ msgstr "Tijdzone" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Fabrikant" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Vormfactor" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Breedte" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Hoogte (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Aflopende eenheden" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Buitenbreedte" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Buitendiepte" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Buitenste eenheid" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Inbouwdiepte" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3562,10 +3562,10 @@ msgstr "Inbouwdiepte" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3574,61 +3574,61 @@ msgstr "Inbouwdiepte" msgid "Weight" msgstr "Gewicht" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Maximaal gewicht" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Gewichtseenheid" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Racktype" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Buitenafmetingen" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Dimensies" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Nummering" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3656,45 +3656,50 @@ msgstr "Nummering" msgid "Role" msgstr "Rol" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Racktype" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Serienummer" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Tag voor bedrijfsmiddelen" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Luchtstroom" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3704,64 +3709,64 @@ msgstr "Luchtstroom" msgid "Rack" msgstr "Rek" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Hardware" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Standaardplatform" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Onderdeelnummer" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "U-hoogte" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Uitsluiten van gebruik" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Soort apparaat" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Moduletype" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Chassis" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "VM-rol" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3772,19 +3777,19 @@ msgstr "VM-rol" msgid "Config template" msgstr "Configuratiesjabloon" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Soort apparaat" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Rol van het apparaat" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3798,14 +3803,36 @@ msgstr "Rol van het apparaat" msgid "Platform" msgstr "Platform" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Cluster" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3815,9 +3842,9 @@ msgstr "Platform" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3826,10 +3853,10 @@ msgstr "Platform" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3856,7 +3883,7 @@ msgstr "Platform" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3866,23 +3893,28 @@ msgstr "Platform" msgid "Device" msgstr "Apparaat" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Configuratie" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Virtualisatie" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Moduletype" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3900,109 +3932,109 @@ msgstr "Moduletype" msgid "Label" msgstr "Label" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Lengte" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Lengte-eenheid" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Domein" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "Voedingspaneel" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Levering" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Fase" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Spanning" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Stroomsterkte" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Maximaal gebruik" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Maximale trekking" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Maximaal stroomverbruik (watt)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Toegewezen loting" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Toegewezen stroomverbruik (watt)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Voedingspoort" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Voer de poot in" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Alleen voor beheer" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "PoE-modus" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "PoE-type" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Draadloze rol" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4016,17 +4048,17 @@ msgstr "Draadloze rol" msgid "Module" msgstr "Module" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "LAG" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Contexten van virtuele apparaten" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4035,7 +4067,7 @@ msgstr "Contexten van virtuele apparaten" msgid "Speed" msgstr "Snelheid" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4049,76 +4081,88 @@ msgstr "Snelheid" msgid "Mode" msgstr "Modus" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "VLAN-groep" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "VLAN zonder label" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "Getagde VLAN's" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Draadloze LAN-groep" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "Draadloze LAN's" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Addressing" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Operatie" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Gerelateerde interfaces" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "802.1Q-omschakeling" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "De interfacemodus moet worden gespecificeerd om VLAN's toe te wijzen" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "" "Aan een toegangsinterface kunnen geen gelabelde VLAN's worden toegewezen." @@ -4145,9 +4189,9 @@ msgstr "Toegewezen groep" msgid "available options" msgstr "beschikbare opties" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4169,15 +4213,15 @@ msgstr "De fabrikant van dit racktype" msgid "The lowest-numbered position in the rack" msgstr "De positie met het laagst genummerde nummer in het rack" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Breedte van rail tot rail (in inches)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Eenheid voor buitenafmetingen" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Eenheid voor rackgewichten" @@ -4189,158 +4233,148 @@ msgstr "Naam van de toegewezen tenant" msgid "Name of assigned role" msgstr "Naam van de toegewezen rol" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Richting van de luchtstroom" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Site voor ouders" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Locatie van het rek (indien aanwezig)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Eenheden" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Door komma's gescheiden lijst van individuele eenheidsnummers" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "De fabrikant die dit apparaattype produceert" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "Het standaardplatform voor apparaten van dit type (optioneel)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Gewicht van het apparaat" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Eenheid voor het gewicht van het apparaat" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Gewicht van de module" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Eenheid voor modulegewicht" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Beperk de platformtoewijzingen aan deze fabrikant" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Toegewezen rol" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Apparaattype fabrikant" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Apparaattype model" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Toegewezen platform" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Virtueel chassis" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Cluster" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Virtualisatiecluster" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Toegewezen locatie (indien aanwezig)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Toegewezen rek (indien aanwezig)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Gezicht" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Gemonteerd rackfront" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Ouderapparaat (voor apparaten voor kinderen)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Toestelvak" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" "Apparaatvak waarin dit apparaat is geïnstalleerd (voor onderliggende " "apparaten)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "Het apparaat waarop deze module is geïnstalleerd" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Modulevak" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "De moduleruimte waarin deze module is geïnstalleerd" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "Het type module" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Componenten repliceren" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4348,87 +4382,87 @@ msgstr "" "Componenten die aan dit moduletype zijn gekoppeld automatisch invullen " "(standaard ingeschakeld)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Componenten adopteren" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Reeds bestaande componenten adopteren" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Poorttype" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Poortsnelheid in bps" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Type stopcontact" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Lokale voedingspoort die dit stopcontact voedt" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Elektrische fase (voor driefasige circuits)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Interface voor ouders" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Overbrugde interface" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Lag" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "LAG-interface voor ouders" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "Vdcs" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" "VDC-namen gescheiden door komma's, tussen dubbele aanhalingstekens. " "Voorbeeld:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Fysiek medium" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Dubbelzijdig" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "Poe-modus" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Poe-type" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "IEEE 802.1Q operationele modus (voor L2-interfaces)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4436,172 +4470,172 @@ msgstr "IEEE 802.1Q operationele modus (voor L2-interfaces)" msgid "Assigned VRF" msgstr "Toegewezen VRF" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Rf-rol" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Draadloze rol (AP/station)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} is niet toegewezen aan het apparaat {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Poort aan de achterkant" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Bijbehorende poort aan de achterkant" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Classificatie van fysieke media" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Geïnstalleerd apparaat" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "Kinderapparaat dat in deze bay is geïnstalleerd" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Kinderapparaat niet gevonden." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Onderliggend inventarisitem" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Soort onderdeel" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Soort onderdeel" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Naam van het onderdeel" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Naam van de component" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Onderdeel niet gevonden: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Side A-apparaat" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Naam van het apparaat" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Type kant A" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Soort beëindiging" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Naam van kant A" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Naam van beëindiging" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Side B-apparaat" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Type kant B" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Naam van kant B" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Status van de verbinding" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "Kant {side_upper}: {device} {termination_object} is al verbonden" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} nevenbeëindiging niet gevonden: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Meester" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Master-apparaat" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Naam van de moedersite" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "Stroomopwaarts stroompaneel" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Primair of redundant" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Soort voeding (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Enkel- of driefasig" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "Primaire IPv4" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "IPv4-adres met masker, bijvoorbeeld 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "Primaire IPv6" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "IPv6-adres met prefixlengte, bijvoorbeeld 2001:db8: :1/64" @@ -4689,10 +4723,6 @@ msgstr "Oudergroep" msgid "Facility" msgstr "Faciliteit" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Racktype" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Functie" @@ -4729,7 +4759,7 @@ msgid "Has virtual device contexts" msgstr "Heeft contexten voor virtuele apparaten" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Clustergroep" @@ -4768,7 +4798,7 @@ msgstr "Vriendelijk" msgid "Mgmt only" msgstr "Alleen voor beheer" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4876,36 +4906,46 @@ msgstr "" msgid "Characteristics" msgstr "Kenmerken" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Sjabloon voor consolepoort" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Poortsjabloon voor consoleserver" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Sjabloon voor de voorpoort" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Interfacesjabloon" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Sjabloon voor stopcontact" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Sjabloon voor voedingspoort" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Sjabloon voor achterpoort" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4929,7 +4969,7 @@ msgstr "Sjabloon voor achterpoort" msgid "Interface" msgstr "Interface" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4937,14 +4977,14 @@ msgstr "Interface" msgid "Console Port" msgstr "Consolepoort" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Console Server-poort" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4955,7 +4995,7 @@ msgstr "Console Server-poort" msgid "Front Port" msgstr "Poort Voor" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4968,40 +5008,40 @@ msgstr "Poort Voor" msgid "Rear Port" msgstr "Poort achter" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Voedingspoort" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Stopcontact" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Toewijzing van componenten" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "Een InventoryItem kan slechts aan één component worden toegewezen." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "LAG-interface" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Filter-VLAN's die beschikbaar zijn voor toewijzing per groep." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Apparaat voor kinderen" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -5009,35 +5049,35 @@ msgstr "" "Kindapparaten moeten eerst worden aangemaakt en toegewezen aan de site en " "het rack van het ouderapparaat." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Consolepoort" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Console-serverpoort" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Poort voor" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "Stopcontact" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Inventarisitem" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Rol van het inventarisitem" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5055,12 +5095,12 @@ msgstr "" "{pattern_count} worden verwacht." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Poorten achter" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" "Selecteer één toewijzing van de achterpoort voor elke poort aan de voorkant " @@ -5076,16 +5116,7 @@ msgstr "" "moet overeenkomen met het geselecteerde aantal posities aan de achterkant " "van de poort ({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"Het touwtje {module} wordt vervangen door de positie van de " -"toegewezen module, indien aanwezig." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5095,18 +5126,18 @@ msgstr "" "overeenkomen met het geselecteerde aantal posities aan de achterkant van de " "poort ({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Leden" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Uitgangspositie" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." @@ -5114,7 +5145,7 @@ msgstr "" "Positie van het apparaat van het eerste lid. Verhoogt met één voor elk extra" " lid." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "Voor het eerste VC-lid moet een positie worden gespecificeerd." @@ -6065,12 +6096,12 @@ msgstr "positie (U)" msgid "rack face" msgstr "gezicht met een rekje" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "primaire IPv4" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "primaire IPv6" @@ -6248,15 +6279,15 @@ msgstr "" "De module moet worden geïnstalleerd in een modulecompartiment dat bij het " "toegewezen apparaat hoort ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "domein" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "virtueel chassis" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." @@ -6264,7 +6295,7 @@ msgstr "" "De geselecteerde master ({master}) is niet toegewezen aan dit virtuele " "chassis." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6273,34 +6304,34 @@ msgstr "" "Kan het virtuele chassis niet verwijderen {self}. Er zijn lidinterfaces die " "een LAG-interface tussen chassis vormen." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "-identificatiecode" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Numerieke identificatie die uniek is voor het ouderapparaat" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "reacties" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "context van het virtuele apparaat" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "contexten van virtuele apparaten" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} is geen IPv{family} adres." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" "Het primaire IP-adres moet bij een interface op het toegewezen apparaat " @@ -6493,7 +6524,7 @@ msgstr "Lokaal toegewezen identificatiecode" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Functionele rol" @@ -6703,7 +6734,7 @@ msgstr "Bereikbaar" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Apparaten" @@ -6732,8 +6763,8 @@ msgid "Site Group" msgstr "Sitegroep" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6784,20 +6815,20 @@ msgid "Power outlets" msgstr "Stopcontacten" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Interfaces" @@ -6823,8 +6854,8 @@ msgid "Module Bay" msgstr "Modulebaai" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6853,7 +6884,7 @@ msgstr "Maximale trekkracht (W)" msgid "Allocated draw (W)" msgstr "Toegewezen trekking (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6949,87 +6980,87 @@ msgstr "U-hoogte" msgid "Instances" msgstr "Instanties" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Consolepoorten" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Serverpoorten voor de console" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Voedingspoorten" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Stopcontacten" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Ports aan de voorkant" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Poorten achteraan" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Apparaatvakken" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Modulebays" @@ -7078,7 +7109,7 @@ msgstr "Ruimte" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7088,28 +7119,28 @@ msgstr "Sites" msgid "Test case must set peer_termination_type" msgstr "De testcase moet peer_termination_type instellen" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Verbinding verbroken {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Reserveringen" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Apparaten zonder rack" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Context van de configuratie" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Render-configuratie" @@ -7121,36 +7152,36 @@ msgstr "" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Virtuele machines" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Geïnstalleerd apparaat {device} in de baai {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Apparaat verwijderd {device} van bay {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Kinderen" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Lid toegevoegd {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "" "Kan het masterapparaat niet verwijderen {device} vanaf het virtuele chassis." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "Verwijderd {device} vanaf een virtueel chassis {chassis}" @@ -7333,7 +7364,6 @@ msgstr "Bijwerken" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -8173,19 +8203,19 @@ msgstr "Plan de uitvoering van het script op een bepaald tijdstip" msgid "Interval at which this script is re-run (in minutes)" msgstr "Interval waarmee dit script opnieuw wordt uitgevoerd (in minuten)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "Wijzigingen in de database zijn automatisch teruggedraaid." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Script is met een fout afgebroken: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Er deed zich een uitzondering voor: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "Wijzigingen in de database zijn teruggedraaid vanwege een fout." @@ -9227,7 +9257,7 @@ msgstr "Widget verwijderd: " msgid "Error deleting widget: " msgstr "Fout bij het verwijderen van de widget: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "Kan script niet uitvoeren: het RQ-werkproces wordt niet uitgevoerd." @@ -9374,7 +9404,7 @@ msgid "Prefixes which contain this prefix or IP" msgstr "Prefixen die dit voorvoegsel of IP-adres bevatten" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Lengte van het masker" @@ -9388,7 +9418,7 @@ msgid "VLAN number (1-4094)" msgstr "VLAN-nummer (1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9500,16 +9530,16 @@ msgstr "Een CIDR-masker (bijv /24) is vereist." msgid "Address pattern" msgstr "Adrespatroon" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Zorg voor unieke ruimte" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "Is privé" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9523,20 +9553,20 @@ msgstr "Is privé" msgid "RIR" msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Datum toegevoegd" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "VLAN-groep" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9549,32 +9579,32 @@ msgstr "VLAN-groep" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Lengte van het voorvoegsel" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" -msgstr "Is een zwembad" +msgstr "Is een pool" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Behandel als volledig gebruikt" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "VLAN-toewijzing" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "DNS-naam" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9582,12 +9612,12 @@ msgstr "DNS-naam" msgid "Protocol" msgstr "Protocol" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "Groeps-ID" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9599,12 +9629,12 @@ msgstr "Groeps-ID" msgid "Authentication type" msgstr "Authenticatietype" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Verificatiesleutel" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9616,26 +9646,26 @@ msgstr "Verificatiesleutel" msgid "Authentication" msgstr "Authentificatie" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Soort bereik" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "VLAN-ID-bereiken" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Toepassingsgebied" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "VLAN-ID-bereiken" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Site en groep" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9662,8 +9692,8 @@ msgstr "VLAN-groep (indien aanwezig)" msgid "Parent device of assigned interface (if any)" msgstr "Ouderapparaat met toegewezen interface (indien aanwezig)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9689,43 +9719,63 @@ msgstr "Is primair" msgid "Make this the primary IP for the assigned device" msgstr "Maak dit het primaire IP-adres voor het toegewezen apparaat" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "Geen apparaat of virtuele machine gespecificeerd; kan niet worden ingesteld " "als primair IP-adres" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "" "Geen interface gespecificeerd; kan niet worden ingesteld als primair IP-" "adres" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Authenticatietype" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Soort bereik (app en model)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Toegewezen VLAN-groep" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "IP-protocol" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Vereist indien niet toegewezen aan een VM" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Vereist indien niet toegewezen aan een apparaat" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} is niet toegewezen aan dit apparaat/VM." @@ -9807,7 +9857,7 @@ msgstr "Toegewezen aan een interface" msgid "DNS Name" msgstr "DNS-naam" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9818,13 +9868,13 @@ msgstr "VLAN's" msgid "Contains VLAN ID" msgstr "Bevat VLAN-ID" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "VLAN-ID" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9835,7 +9885,7 @@ msgstr "VLAN-ID" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9864,8 +9914,8 @@ msgstr "Site/VLAN-toewijzing" msgid "IP Range" msgstr "IP-bereik" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "FHRP-groep" @@ -9874,47 +9924,57 @@ msgstr "FHRP-groep" msgid "Make this the primary IP for the device/VM" msgstr "Maak dit het primaire IP-adres voor het apparaat/VM" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "NAT IP (binnenin)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "Een IP-adres kan slechts aan één object worden toegewezen." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Kan het IP-adres niet opnieuw toewijzen terwijl dit is aangewezen als het " -"primaire IP-adres voor het bovenliggende object" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "Alleen IP-adressen die aan een interface zijn toegewezen, kunnen als " "primaire IP-adressen worden aangeduid." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Virtueel IP-adres" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "De opdracht bestaat al" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "VLAN-ID's" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "Kind-VLAN's" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9922,33 +9982,33 @@ msgstr "" "Door komma's gescheiden lijst van een of meer poortnummers. Een bereik kan " "worden gespecificeerd met een koppelteken." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Servicesjabloon" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Poort (en)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Service" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Servicesjabloon" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "Van sjabloon" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Op maat" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10236,6 +10296,14 @@ msgstr "" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Duplicaat IP-adres gevonden in {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Kan het IP-adres niet opnieuw toewijzen terwijl dit is aangewezen als het " +"primaire IP-adres voor het bovenliggende object" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Alleen IPv6-adressen kunnen een SLAAC-status krijgen" @@ -10291,40 +10359,48 @@ msgstr "Kan scope_type niet instellen zonder scope_id." msgid "Cannot set scope_id without scope_type." msgstr "Kan scope_id niet instellen zonder scope_type." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Bereiken kunnen elkaar niet overlappen." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"De maximale VID voor kinderen moet groter zijn dan of gelijk zijn aan de " -"minimale VID voor kinderen ({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "De specifieke site waaraan dit VLAN is toegewezen (indien aanwezig)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "VLAN-groep (optioneel)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "Numerieke VLAN-id (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Operationele status van dit VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "De primaire functie van dit VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10333,7 +10409,7 @@ msgstr "" "VLAN is toegewezen aan de groep {group} (toepassingsgebied: {scope}); kan " "niet ook aan de site worden toegewezen {site}." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "VID moet binnen bereik zijn {ranges} voor VLAN's in groep {group}" @@ -11107,17 +11183,12 @@ msgstr "IPsec-beleid" msgid "IPSec Profiles" msgstr "IPsec-profielen" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Virtualisatie" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Virtuele schijven" @@ -11279,7 +11350,7 @@ msgstr "Systeem" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11529,19 +11600,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Rij {i}: Object met ID {id} bestaat niet" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "Nee {object_type} zijn geselecteerd." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Hernoemd {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Verwijderd {count} {object_type}" @@ -11574,7 +11645,7 @@ msgstr "Gesynchroniseerd {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} moet get_children () implementeren" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11919,9 +11990,7 @@ msgid "Circuit Type" msgstr "Circuittype" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11932,7 +12001,6 @@ msgstr "Toevoegen" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12222,35 +12290,35 @@ msgstr "dagen" msgid "Indefinite" msgstr "Onbepaald" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Niet geïnstalleerd" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Overzicht" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Installeren" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Details van de plug-in" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Samenvatting" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Licentie" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Versiegeschiedenis" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Lokale installatie-instructies" @@ -12596,8 +12664,8 @@ msgstr "Een service toevoegen" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12670,20 +12738,24 @@ msgstr "Configuratie" msgid "Context Data" msgstr "Contextgegevens" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Gerenderde configuratie" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Downloaden" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Geen configuratiesjabloon gevonden" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12705,7 +12777,6 @@ msgid "Local Config Context Data" msgstr "Contextgegevens voor lokale configuratie" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12752,12 +12823,12 @@ msgid "VM Role" msgstr "VM-rol" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Naam van het model" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Onderdeelnummer" @@ -12896,7 +12967,7 @@ msgstr "MAC-adres" msgid "Wireless Link" msgstr "Draadloze link" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Peer" @@ -13521,7 +13592,7 @@ msgstr "Je hebt geen toestemming om scripts uit te voeren" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Script uitvoeren" @@ -13534,27 +13605,32 @@ msgstr "Fout bij laden van script" msgid "Script no longer exists in the source file." msgstr "Het script bestaat niet meer in het bronbestand." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Laatste run" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "Het script is niet langer aanwezig in het bronbestand" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Nooit" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Draai opnieuw" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "Kon de scripts van niet laden van module %(module)s" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Geen scripts gevonden" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13878,7 +13954,7 @@ msgstr "Alle meldingen" msgid "Select" msgstr "Selecteer" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Resetten" @@ -14363,6 +14439,10 @@ msgstr "Hulpbronnen" msgid "Add Virtual Disk" msgstr "Virtuele schijf toevoegen" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15442,13 +15522,13 @@ msgid "Memory (MB)" msgstr "Geheugen (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Schijf (GB)" +msgid "Disk (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Grootte (GB)" +msgid "Size (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15635,68 +15715,80 @@ msgstr "virtuele schijf" msgid "virtual disks" msgstr "virtuele schijven" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Toegevoegd {count} apparaten om te clusteren {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Verwijderd {count} apparaten uit het cluster {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPsec - Vervoer" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec - Tunnel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP-in-IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GRE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Hub" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "Spoke" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Agressive" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Main" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Vooraf gedeelde sleutels" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Certificaten" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "RSA-handtekeningen" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "DSA-handtekeningen" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15705,23 +15797,27 @@ msgstr "DSA-handtekeningen" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "groep {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Ethernet, privé-LAN" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Virtueel privé-LAN via Ethernet" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Ethernet Private Tree" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Virtuele privéstructuur van Ethernet" diff --git a/netbox/translations/pl/LC_MESSAGES/django.mo b/netbox/translations/pl/LC_MESSAGES/django.mo index 8d6777d9f..e0e9273fa 100644 Binary files a/netbox/translations/pl/LC_MESSAGES/django.mo and b/netbox/translations/pl/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/pl/LC_MESSAGES/django.po b/netbox/translations/pl/LC_MESSAGES/django.po index c8ede3aca..92dde3ca4 100644 --- a/netbox/translations/pl/LC_MESSAGES/django.po +++ b/netbox/translations/pl/LC_MESSAGES/django.po @@ -6,17 +6,17 @@ # Translators: # Jeff Gehlbach, 2024 # Simplicity sp. z o.o., 2024 -# Grzegorz Szymaszek, 2024 # Jeremy Stretch, 2024 +# Grzegorz Szymaszek, 2024 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" -"Last-Translator: Jeremy Stretch, 2024\n" +"Last-Translator: Grzegorz Szymaszek, 2024\n" "Language-Team: Polish (https://app.transifex.com/netbox-community/teams/178115/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -91,8 +91,8 @@ msgstr "Twoje hasło zostało pomyślnie zmienione." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -105,7 +105,7 @@ msgstr "Zaopatrzenie" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -116,8 +116,8 @@ msgid "Active" msgstr "Aktywny" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Nieaktywne" @@ -130,19 +130,19 @@ msgstr "Odstąpienie od zaopatrzenia" msgid "Decommissioned" msgstr "Wycofane ze służby" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" -msgstr "Podstawowy" +msgstr "Pierwszorzędny" #: netbox/circuits/choices.py:91 netbox/ipam/choices.py:90 #: netbox/tenancy/choices.py:18 msgid "Secondary" -msgstr "Wtórny" +msgstr "Drugorzędny" #: netbox/circuits/choices.py:92 netbox/tenancy/choices.py:19 msgid "Tertiary" -msgstr "Trzeciorzędowy" +msgstr "Trzeciorzędny" #: netbox/circuits/choices.py:93 netbox/tenancy/choices.py:20 msgid "Inactive" @@ -203,12 +203,12 @@ msgstr "Grupa terenów (identyfikator)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -217,18 +217,17 @@ msgstr "Grupa terenów (identyfikator)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -336,10 +335,10 @@ msgstr "Wypowiedzenie A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -391,7 +390,7 @@ msgstr "Grupa obwodów (identyfikator)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -406,33 +405,33 @@ msgstr "ASN" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -441,7 +440,7 @@ msgstr "ASN" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -456,7 +455,7 @@ msgstr "ASN" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -476,7 +475,7 @@ msgstr "ASN" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -569,10 +568,10 @@ msgid "Service ID" msgstr "Identyfikator usługi" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -593,16 +592,16 @@ msgstr "Kolor" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -657,14 +656,14 @@ msgstr "Konto dostawcy" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -673,13 +672,13 @@ msgstr "Konto dostawcy" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -690,7 +689,7 @@ msgstr "Konto dostawcy" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -726,30 +725,30 @@ msgstr "Status" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -819,11 +818,11 @@ msgstr "Parametry serwisowe" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -855,11 +854,11 @@ msgstr "Prędkość portu (Kbps)" msgid "Upstream speed (Kbps)" msgstr "Prędkość od klienta do serwera (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Oznacz podłączony" @@ -906,10 +905,10 @@ msgstr "Rodzaj obwodu" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -919,13 +918,13 @@ msgstr "Status operacyjny" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -950,12 +949,12 @@ msgstr "Sieć dostawców" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -972,9 +971,9 @@ msgstr "Sieć dostawców" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1003,8 +1002,8 @@ msgid "Contacts" msgstr "Łączność" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1012,13 +1011,12 @@ msgstr "Łączność" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1031,16 +1029,16 @@ msgid "Region" msgstr "Region" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1052,7 +1050,7 @@ msgstr "Grupa terenów" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1091,9 +1089,9 @@ msgstr "Konto" msgid "Term Side" msgstr "Strona terminowa" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1103,11 +1101,11 @@ msgstr "Zlecenie" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1179,20 +1177,20 @@ msgid "Unique circuit ID" msgstr "Unikalny identyfikator obwodu" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "status" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "zainstalowany" @@ -1312,11 +1310,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1327,7 +1325,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1415,7 +1413,7 @@ msgstr "sieci dostawców" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1426,7 +1424,7 @@ msgstr "sieci dostawców" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1457,7 +1455,7 @@ msgstr "sieci dostawców" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1621,7 +1619,7 @@ msgstr "Zakończone" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Nie powiodło się" @@ -1688,7 +1686,7 @@ msgid "Cancelled" msgstr "Anulowane" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Lokalne" @@ -1775,8 +1773,8 @@ msgid "User name" msgstr "Nazwa użytkownika" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1880,7 +1878,7 @@ msgid "Completed before" msgstr "Zakończone przed" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1945,9 +1943,9 @@ msgstr "Musisz przesłać plik lub wybrać plik danych do synchronizacji" msgid "Rack Elevations" msgstr "Elewacje szaf" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Moc" @@ -2049,7 +2047,7 @@ msgstr "" "Rejestracja zmian nie jest obsługiwana dla tego typu obiektu ({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2109,7 +2107,7 @@ msgstr "typ" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2228,58 +2226,58 @@ msgstr "plik zarządzany" msgid "managed files" msgstr "zarządzane pliki" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "planowy" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "interwał" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Odstęp nawrotów (w minutach)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "rozpoczął się" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "ukończony" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "dane" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "błąd" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "ID pracy" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "pracy" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "prace" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "Zadania nie mogą być przypisane do tego typu obiektu ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "Nieprawidłowy status zakończenia pracy. Wybory to: {choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" @@ -2364,7 +2362,7 @@ msgstr "Maksymalna wersja NetBox" msgid "No plugin data found" msgstr "Nie znaleziono danych wtyczki" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Autor" @@ -2372,7 +2370,7 @@ msgstr "Autor" msgid "Installed" msgstr "Zainstalowany" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Certyfikowany" @@ -2498,11 +2496,11 @@ msgstr "Praca {id} został zatrzymany." msgid "Failed to stop job {id}" msgstr "Nie udało się zatrzymać zadania {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "Nie można załadować katalogu wtyczek" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Wtyczka {name} nie znaleziono" @@ -2522,7 +2520,7 @@ msgid "Staging" msgstr "Inscenizacja" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Wycofanie z eksploatacji" @@ -2586,7 +2584,7 @@ msgstr "Przestarzałe" msgid "Millimeters" msgstr "Milimetrów" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "Cale" @@ -2600,15 +2598,15 @@ msgstr "Przód do tyłu" msgid "Rear to front" msgstr "Tył do przodu" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2688,7 +2686,7 @@ msgid "Top to bottom" msgstr "Od góry do dołu" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Pasywny" @@ -2714,11 +2712,11 @@ msgstr "Międzynarodowy/ITA" #: netbox/dcim/choices.py:573 netbox/dcim/choices.py:814 msgid "Proprietary" -msgstr "Zastrzeżone" +msgstr "Własnościowy" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Pozostałe" @@ -2731,24 +2729,24 @@ msgstr "ITA/Międzynarodowy" msgid "Physical" msgstr "Fizyczne" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Wirtualny" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Bezprzewodowy" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Interfejsy wirtualne" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2757,27 +2755,27 @@ msgstr "Interfejsy wirtualne" msgid "Bridge" msgstr "Most" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Grupa agregacji linków (LGD)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (stały)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (modułowy)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (płaszczyzna tylna)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Komórkowy" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2785,130 +2783,130 @@ msgstr "Komórkowy" msgid "Serial" msgstr "Seryjny" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "koncentryczny" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "Układanie" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Połowa" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Pełny" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Automatyczny" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Dostęp" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Oznaczone" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Oznaczone (Wszystkie)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "Standard IEEE" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "Pasywny 24V (2 pary)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "Pasywny 24V (4-parowy)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "Pasywny 48V (2 pary)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "Pasywny 48V (4 pary)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Miedź" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Światłowód" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Włókno" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Połączony" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Kilometry" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Mierniki" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Centymetry" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Mile" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Stopy" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Kilogramy" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Gramy" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "funty" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Uncja" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Nadmiarowy" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Jednofazowy" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Trójfazowy" @@ -3154,7 +3152,7 @@ msgstr "Grupa klastra (ID)" msgid "Device model (slug)" msgstr "Model urządzenia (identyfikator)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "Jest pełna głębokość" @@ -3276,21 +3274,21 @@ msgstr "Przypisana sieć VLAN" msgid "Assigned VID" msgstr "Przypisany VID" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3357,7 +3355,7 @@ msgid "LAG interface (ID)" msgstr "Interfejs LAG (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Kontekst urządzenia wirtualnego" @@ -3431,7 +3429,7 @@ msgstr "Tagi" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3448,38 +3446,38 @@ msgstr "" "Obsługiwane są zakresy alfanumeryczne. (Musi odpowiadać liczbie tworzonych " "nazw.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Nazwa kontaktu" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Telefon kontaktowy" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "Kontakt E-mail" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Strefa czasowa" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3489,58 +3487,59 @@ msgstr "Strefa czasowa" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Producent" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Współczynnik kształtu" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Szerokość" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Wysokość (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Jednostki malejące" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Szerokość zewnętrzna" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Głębokość zewnętrzna" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Jednostka zewnętrzna" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Głębokość montażu" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3551,10 +3550,10 @@ msgstr "Głębokość montażu" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3563,61 +3562,61 @@ msgstr "Głębokość montażu" msgid "Weight" msgstr "Waga" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Maksymalna waga" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Jednostka wagowa" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Typ szafy" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Wymiary zewnętrzne" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Wymiary" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Numeracja" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3645,45 +3644,50 @@ msgstr "Numeracja" msgid "Role" msgstr "Rola" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Typ szafy" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Numer seryjny" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Etykieta zasobu" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Przepływ powietrza" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3693,64 +3697,64 @@ msgstr "Przepływ powietrza" msgid "Rack" msgstr "Szafa" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Sprzęt" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Domyślna platforma" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Numer części" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "Wysokość U" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Wyklucz z wykorzystania" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Typ urządzenia" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Typ modułu" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Podwozie" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "Rola maszyny wirtualnej" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3761,19 +3765,19 @@ msgstr "Rola maszyny wirtualnej" msgid "Config template" msgstr "Szablon konfiguracji" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Typ urządzenia" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Rola urządzenia" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3787,14 +3791,36 @@ msgstr "Rola urządzenia" msgid "Platform" msgstr "Platforma" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Klaster" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3804,9 +3830,9 @@ msgstr "Platforma" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3815,10 +3841,10 @@ msgstr "Platforma" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3845,7 +3871,7 @@ msgstr "Platforma" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3855,23 +3881,28 @@ msgstr "Platforma" msgid "Device" msgstr "Urządzenie" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Konfiguracja" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Wirtualizacja" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Rodzaj modułu" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3889,109 +3920,109 @@ msgstr "Rodzaj modułu" msgid "Label" msgstr "Etykieta" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Długość" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Jednostka długości" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Domena" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "Panel zasilania" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Dostawa" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Faza" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Napięcie" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Natężenie prądu" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Maksymalne wykorzystanie" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Maksymalne losowanie" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Maksymalny pobór mocy (waty)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Przydzielone losowanie" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Przydzielony pobór mocy (waty)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Port zasilania" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Noga do karmienia" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Tylko zarządzanie" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "Tryb PoE" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "Typ PoE" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Rola sieci bezprzewodowej" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4005,17 +4036,17 @@ msgstr "Rola sieci bezprzewodowej" msgid "Module" msgstr "Moduł" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "OPÓŹNIENIE" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Konteksty urządzeń wirtualnych" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4024,7 +4055,7 @@ msgstr "Konteksty urządzeń wirtualnych" msgid "Speed" msgstr "Prędkość" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4038,76 +4069,88 @@ msgstr "Prędkość" msgid "Mode" msgstr "Tryb" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "Grupa VLAN" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "Nieoznaczone sieci VLAN" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "Oznaczone sieci VLAN" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Grupa sieci bezprzewodowej sieci LAN" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "Bezprzewodowe sieci LAN" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Adresowanie" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Operacja" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Powiązane interfejsy" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "Przełączanie 802.1Q" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "Tryb interfejsu musi być określony, aby przypisać sieci VLAN" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "Interfejs dostępu nie może mieć przypisanych oznakowanych sieci VLAN." @@ -4133,9 +4176,9 @@ msgstr "Przydzielona grupa" msgid "available options" msgstr "dostępne opcje" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4157,15 +4200,15 @@ msgstr "Producent tego typu szaf" msgid "The lowest-numbered position in the rack" msgstr "Najniższy numer pozycji w szafie" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Szerokość szyny do szyny (w calach)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Jednostka do wymiarów zewnętrznych" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Jednostka masy w szafach" @@ -4177,158 +4220,148 @@ msgstr "Nazwa przydzielonego najemcy" msgid "Name of assigned role" msgstr "Nazwa przypisanej roli" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Kierunek przepływu powietrza" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Witryna nadrzędna" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Lokalizacja szafy (jeśli określona)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Jednostki" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Lista poszczególnych numerów jednostek oddzielona przecinkami" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "Producent, który produkuje ten typ urządzenia" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "Domyślna platforma dla urządzeń tego typu (opcjonalnie)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Waga urządzenia" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Jednostka do wagi urządzenia" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Waga modułu" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Jednostka do ciężaru modułu" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Ogranicz przypisania platformy do tego producenta" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Przypisana rola" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Producent typu urządzenia" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Model typu urządzenia" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Przydzielona platforma" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Wirtualne podwozie" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Klaster" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Klaster wirtualizacji" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Przypisana lokalizacja (jeśli istnieje)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Przypisana szafa (jeśli określona)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Twarz" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Powierzchnia montażu w szafie" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Urządzenie nadrzędne (dla urządzeń podrzędnych)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Osłona urządzenia" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" "Osłona urządzenia, w której to urządzenie jest zainstalowane (dla urządzeń " "podrzędnych)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "Urządzenie, w którym zainstalowany jest ten moduł" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Wnęka modułu" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "Wnęka modułu, w której ten moduł jest zainstalowany" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "Rodzaj modułu" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Replikacja komponentów" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4336,87 +4369,87 @@ msgstr "" "Automatyczne wypełnianie komponentów powiązanych z tym typem modułu " "(domyślnie włączone)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Zastosuj komponenty" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Zastosuj już istniejące komponenty" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Typ portu" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Prędkość portu w bps" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Rodzaj wylotu" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Lokalny port zasilania zasilający to gniazdko" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Faza elektryczna (dla obwodów trójfazowych)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Interfejs nadrzędny" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Interfejs mostkowy" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Opóźnienie" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Nadrzędny interfejs LAG" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "Vdc" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" "Nazwy VDC oddzielone przecinkami, otoczone podwójnymi cudzysłowami. " "Przykład:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Medium fizyczne" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Dwupoziomowy" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "Tryb PoE" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Typ PoE" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "Tryb pracy IEEE 802.1Q (dla interfejsów L2)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4424,174 +4457,174 @@ msgstr "Tryb pracy IEEE 802.1Q (dla interfejsów L2)" msgid "Assigned VRF" msgstr "Przypisany VRF" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Rola Rf" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Rola bezprzewodowa (AP/stacja)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} nie jest przypisany do urządzenia {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Tylny port" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Odpowiedni tylny port" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Klasyfikacja medium fizycznego" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Zainstalowane urządzenie" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "Urządzenie dziecięce zainstalowane w tej wnęce" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Nie znaleziono urządzenia dziecięcego." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Nadrzędny element zapasów" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Typ komponentu" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Typ komponentu" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Nazwa firmy" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Nazwa komponentu" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Nie znaleziono komponentu: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Urządzenie boczne A" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Nazwa urządzenia" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Typ strony A" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Typ zakończenia" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Nazwa strony A" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Nazwa zakończenia" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Urządzenie boczne B" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Strona typu B" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Nazwa strony B" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Status połączenia" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "Bok {side_upper}: {device} {termination_object} jest już połączony" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} Nie znaleziono zakończenia bocznego: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Mistrzu" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Urządzenie główne" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Nazwa witryny nadrzędnej" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "Panel zasilania przed strumieniem" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Podstawowy lub nadmiarowy" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Rodzaj zasilania (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Pojedynczy lub trójfazowy" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "Podstawowy IPv4" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "Adres IPv4 z maską, np. 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "Podstawowy IPv6" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" -msgstr "Adres IPv6 z przedrostkiem, np. 2001:db8: :1/64" +msgstr "Adres IPv6 z prefiksem, np. 2001:db8::1/64" #: netbox/dcim/forms/common.py:24 netbox/dcim/models/device_components.py:527 #: netbox/templates/dcim/interface.html:57 @@ -4676,10 +4709,6 @@ msgstr "Grupa nadrzędna" msgid "Facility" msgstr "Obiekty" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Typ szafy" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Funkcja" @@ -4716,7 +4745,7 @@ msgid "Has virtual device contexts" msgstr "Posiada konteksty urządzeń wirtualnych" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Grupa klastra" @@ -4755,7 +4784,7 @@ msgstr "Uprzejmy" msgid "Mgmt only" msgstr "Tylko MGMT" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4859,36 +4888,46 @@ msgstr "Automatyczne wypełnianie komponentów powiązanych z tym typem modułu" msgid "Characteristics" msgstr "Charakterystyka" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Szablon portu konsoli" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Szablon portu serwera konsoli" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Szablon portu przedniego" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Szablon interfejsu" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Szablon gniazdka elektrycznego" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Szablon portu zasilania" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Szablon tylnego portu" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4912,7 +4951,7 @@ msgstr "Szablon tylnego portu" msgid "Interface" msgstr "Interfejs" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4920,14 +4959,14 @@ msgstr "Interfejs" msgid "Console Port" msgstr "Port konsoli" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Port serwera konsoli" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4938,7 +4977,7 @@ msgstr "Port serwera konsoli" msgid "Front Port" msgstr "Port przedni" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4951,40 +4990,40 @@ msgstr "Port przedni" msgid "Rear Port" msgstr "Tylny port" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Port zasilania" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Gniazdo zasilania" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Przypisywanie komponentów" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "InventoryItem można przypisać tylko do pojedynczego komponentu." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "Interfejs LAG" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Filtruj sieci VLAN dostępne do przypisania według grup." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Urządzenie dziecięce" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -4992,35 +5031,35 @@ msgstr "" "Urządzenia podrzędne muszą być najpierw utworzone i przypisane do terenu " "i szafy urządzenia nadrzędnego." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Port konsoli" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Port serwera konsoli" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Port przedni" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "Gniazdo zasilania" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Przedmiot zapasów" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Rola pozycji zapasów" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5038,12 +5077,12 @@ msgstr "" "oczekiwane." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Tylne porty" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" "Wybierz jedno przypisanie portu tylnego dla każdego tworzonego portu " @@ -5058,16 +5097,7 @@ msgstr "" "Liczba szablonów portów przednich do utworzenia ({frontport_count}) musi " "odpowiadać wybranej liczbie pozycji tylnych portów ({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"Sznurek {module} zostanie zastąpiony pozycją przypisanego " -"modułu, jeśli istnieje." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5076,18 +5106,18 @@ msgstr "" "Liczba portów przednich do utworzenia ({frontport_count}) musi odpowiadać " "wybranej liczbie pozycji tylnych portów ({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Członkowie" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Pozycja początkowa" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." @@ -5095,7 +5125,7 @@ msgstr "" "Położenie pierwszego urządzenia członkowskiego. Zwiększa się o jeden dla " "każdego dodatkowego członka." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "Pozycja musi być określona dla pierwszego członka VC." @@ -6032,12 +6062,12 @@ msgstr "pozycja (U)" msgid "rack face" msgstr "powierzchnia szafy" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "podstawowy IPv4" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "podstawowy IPv6" @@ -6212,22 +6242,22 @@ msgstr "" "Moduł musi być zainstalowany w wnęce modułowej należącej do przypisanego " "urządzenia ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "domena" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "wirtualne podwozie" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "" "Wybrany mistrz ({master}) nie jest przypisany do tej wirtualnej obudowy." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6236,34 +6266,34 @@ msgstr "" "Nie można usunąć wirtualnej obudowy {self}. Istnieją interfejsy członów, " "które tworzą interfejsy LAG między podwoziami." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "identyfikator" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Identyfikator numeryczny unikalny dla urządzenia nadrzędnego" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "komentarzy" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "kontekst urządzenia wirtualnego" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "konteksty urządzeń wirtualnych" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} nie jest IPV{family} adres." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" "Podstawowy adres IP musi należeć do interfejsu na przypisanym urządzeniu." @@ -6455,7 +6485,7 @@ msgstr "Lokalnie przypisany identyfikator" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Funkcjonalna rola" @@ -6666,7 +6696,7 @@ msgstr "Osiągnięty" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Urządzenia" @@ -6695,8 +6725,8 @@ msgid "Site Group" msgstr "Grupa witryn" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6747,20 +6777,20 @@ msgid "Power outlets" msgstr "Gniazdka elektryczne" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Interfejsy" @@ -6786,8 +6816,8 @@ msgid "Module Bay" msgstr "Moduł Bay" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6816,7 +6846,7 @@ msgstr "Maksymalne wyciąganie (W)" msgid "Allocated draw (W)" msgstr "Przydzielone losowanie (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6912,87 +6942,87 @@ msgstr "Wysokość U" msgid "Instances" msgstr "Instancje" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Porty konsoli" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Porty serwera konsoli" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Porty zasilania" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Gniazdka elektryczne" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Porty przednie" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Tylne porty" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Wnęsy na urządzenia" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Wnęsy modułowe" @@ -7041,7 +7071,7 @@ msgstr "Przestrzeń" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7051,28 +7081,28 @@ msgstr "Witryny" msgid "Test case must set peer_termination_type" msgstr "Przypadek testowy musi ustawić peer_termination_type" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Odłączony {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Rezerwacje" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Urządzenia poza szafami" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Kontekst konfiguracji" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Konfiguracja renderowania" @@ -7083,35 +7113,35 @@ msgstr "Wystąpił błąd podczas renderowania szablonu: {error}" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Maszyny wirtualne" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Zainstalowane urządzenie {device} w zatoce {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Usunięte urządzenie {device} z zatoki {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Dzieci" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Dodano członka {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "Nie można usunąć urządzenia głównego {device} z wirtualnego podwozia." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "Usunięto {device} z wirtualnego podwozia {chassis}" @@ -7294,7 +7324,6 @@ msgstr "Aktualizacja" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -7404,7 +7433,7 @@ msgstr "Nieprawidłowy typ {op} operacja: {value}" #: netbox/extras/conditions.py:137 #, python-brace-format msgid "Ruleset must be a dictionary, not {ruleset}." -msgstr "Zestaw reguł musi być słownikiem, a nie {ruleset}." +msgstr "Zestaw reguł musi być słownikiem, a nie {ruleset}." #: netbox/extras/conditions.py:142 msgid "Invalid logic type: must be 'AND' or 'OR'. Please check documentation." @@ -8122,19 +8151,19 @@ msgstr "Zaplanuj wykonanie skryptu na określony czas" msgid "Interval at which this script is re-run (in minutes)" msgstr "Interwał, w którym ten skrypt jest ponownie uruchamiany (w minutach)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "Zmiany w bazie danych zostały wycofane automatycznie." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Skrypt przerwany z błędem: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Wystąpił wyjątek: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "Zmiany bazy danych zostały cofnięte z powodu błędu." @@ -9162,7 +9191,7 @@ msgstr "Usunięty widget: " msgid "Error deleting widget: " msgstr "Błąd usuwania widżetu: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "Nie można uruchomić skryptu: proces roboczy RQ nie działa." @@ -9177,7 +9206,7 @@ msgstr "Nieprawidłowy format adresu IP: {data}" #: netbox/ipam/api/field_serializers.py:37 msgid "Enter a valid IPv4 or IPv6 prefix and mask in CIDR notation." -msgstr "Wprowadź prawidłowy prefiks IPv4 lub IPv6 i maskę w notacji CIDR." +msgstr "Wprowadź prawidłowy prefiks IPv4 lub IPv6 i maskę w notacji CIDR." #: netbox/ipam/api/field_serializers.py:44 #, python-brace-format @@ -9188,8 +9217,8 @@ msgstr "Nieprawidłowy format prefiksu IP: {data}" msgid "" "Insufficient space is available to accommodate the requested prefix size(s)" msgstr "" -"Dostępna jest niewystarczająca ilość miejsca, aby pomieścić żądany rozmiar " -"(-y) prefiksu" +"Nie jest dostępna jest wystarczająca ilość miejsca, aby pomieścić żądany " +"rozmiar prefiksu (prefiksów)" #: netbox/ipam/choices.py:30 msgid "Container" @@ -9298,18 +9327,18 @@ msgstr "RIR (identyfikator)" #: netbox/ipam/filtersets.py:285 msgid "Within prefix" -msgstr "W przedrostku" +msgstr "W prefiksie" #: netbox/ipam/filtersets.py:289 msgid "Within and including prefix" -msgstr "Wewnątrz i włącznie z prefiksem" +msgstr "W i włącznie z prefiksem" #: netbox/ipam/filtersets.py:293 msgid "Prefixes which contain this prefix or IP" msgstr "Prefiksy zawierające ten prefiks lub adres IP" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Długość maski" @@ -9323,7 +9352,7 @@ msgid "VLAN number (1-4094)" msgstr "Numer VLAN (1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9404,7 +9433,7 @@ msgstr "Podstawowy IPv4 (ID)" #: netbox/ipam/filtersets.py:1172 msgid "Primary IPv6 (ID)" -msgstr "Podstawowy protokół IPv6 (ID)" +msgstr "Podstawowy IPv6 (ID)" #: netbox/ipam/formfields.py:14 msgid "Enter a valid IPv4 or IPv6 address (without a mask)." @@ -9435,16 +9464,16 @@ msgstr "Wymagana jest maska CIDR (np. /24)." msgid "Address pattern" msgstr "Wzór adresu" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Wymuszaj unikalną przestrzeń" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "Jest prywatny" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9458,20 +9487,20 @@ msgstr "Jest prywatny" msgid "RIR" msgstr "WRZUCIĆ" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Data dodania" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "Grupa VLAN" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9484,32 +9513,32 @@ msgstr "Grupa VLAN" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" -msgstr "Długość przedrostka" +msgstr "Długość prefiksu" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "Jest basenem" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Traktuj jako w pełni wykorzystany" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "Przypisanie sieci VLAN" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "Nazwa DNS" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9517,12 +9546,12 @@ msgstr "Nazwa DNS" msgid "Protocol" msgstr "Protokół" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "Identyfikator grupy" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9534,12 +9563,12 @@ msgstr "Identyfikator grupy" msgid "Authentication type" msgstr "Typ uwierzytelniania" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "klucz uwierzytelniania" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9551,26 +9580,26 @@ msgstr "klucz uwierzytelniania" msgid "Authentication" msgstr "Uwierzytelnienie" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Rodzaj zakresu" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "Zakresy identyfikatorów VLAN" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Zakres" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "Zakresy identyfikatorów VLAN" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Strona & Grupa" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9597,8 +9626,8 @@ msgstr "Grupa sieci VLAN (jeśli istnieje)" msgid "Parent device of assigned interface (if any)" msgstr "Urządzenie nadrzędne przypisanego interfejsu (jeśli istnieje)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9624,42 +9653,62 @@ msgstr "Jest podstawowy" msgid "Make this the primary IP for the assigned device" msgstr "Ustaw to podstawowy adres IP przypisanego urządzenia" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "Nie określono urządzenia ani maszyny wirtualnej; nie można ustawić jako " "podstawowego adresu IP" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "" "Nie określono interfejsu; nie można ustawić jako podstawowego adresu IP" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Rodzaj auth" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Typ zakresu (aplikacja i model)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Przypisana grupa VLAN" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "protokół IP" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Wymagane, jeśli nie jest przypisane do maszyny wirtualnej" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Wymagane, jeśli nie jest przypisane do urządzenia" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} nie jest przypisany do tego urządzenia/maszyny wirtualnej." @@ -9741,7 +9790,7 @@ msgstr "Przypisany do interfejsu" msgid "DNS Name" msgstr "Nazwa DNS" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9752,13 +9801,13 @@ msgstr "sieci VLAN" msgid "Contains VLAN ID" msgstr "Zawiera identyfikator VLAN" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "IDENTYFIKATOR VLAN" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9769,7 +9818,7 @@ msgstr "IDENTYFIKATOR VLAN" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9798,8 +9847,8 @@ msgstr "Przypisanie witryny/sieci VLAN" msgid "IP Range" msgstr "Zakres IP" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "Grupa FHRP" @@ -9808,47 +9857,57 @@ msgstr "Grupa FHRP" msgid "Make this the primary IP for the device/VM" msgstr "Ustaw to podstawowy adres IP urządzenia/maszyny wirtualnej" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "NAT IP (wewnątrz)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "Adres IP może być przypisany tylko do jednego obiektu." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Nie można ponownie przypisać adresu IP, gdy jest on wyznaczony jako główny " -"adres IP dla obiektu nadrzędnego" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "Tylko adresy IP przypisane do interfejsu mogą być oznaczone jako podstawowe " "adresy IP." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Wirtualny adres IP" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "Przydział już istnieje" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "Identyfikatory sieci VLAN" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "Dziecięce sieci VLAN" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9856,33 +9915,33 @@ msgstr "" "Oddzielona przecinkami lista jednego lub więcej numerów portów. Zakres można" " określić za pomocą myślnika." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Szablon usługi" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Port (y)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Serwis" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Szablon usługi" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "Z szablonu" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Niestandardowe" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10024,7 +10083,7 @@ msgstr "Status operacyjny tego prefiksu" #: netbox/ipam/models/ip.py:262 msgid "The primary function of this prefix" -msgstr "Podstawowa funkcja tego przedrostka" +msgstr "Podstawowa funkcja tego prefiksu" #: netbox/ipam/models/ip.py:265 msgid "is a pool" @@ -10032,7 +10091,7 @@ msgstr "jest basenem" #: netbox/ipam/models/ip.py:267 msgid "All IP addresses within this prefix are considered usable" -msgstr "Wszystkie adresy IP w tym prefiksie są uważane za użyteczne" +msgstr "Wszystkie adresy IP w tym prefiksie są uważane za użyteczne" #: netbox/ipam/models/ip.py:270 netbox/ipam/models/ip.py:537 msgid "mark utilized" @@ -10040,7 +10099,7 @@ msgstr "użyty znak" #: netbox/ipam/models/ip.py:294 msgid "prefixes" -msgstr "przedrostki" +msgstr "prefiksy" #: netbox/ipam/models/ip.py:317 msgid "Cannot create prefix with /0 mask." @@ -10058,7 +10117,7 @@ msgstr "tabela globalna" #: netbox/ipam/models/ip.py:326 #, python-brace-format msgid "Duplicate prefix found in {table}: {prefix}" -msgstr "Zduplikowany prefiks znaleziony w {table}: {prefix}" +msgstr "Zduplikowany prefiks znaleziony w {table}: {prefix}" #: netbox/ipam/models/ip.py:495 msgid "start address" @@ -10166,6 +10225,14 @@ msgstr "" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Zduplikowany adres IP znaleziony w {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Nie można ponownie przypisać adresu IP, gdy jest on wyznaczony jako główny " +"adres IP dla obiektu nadrzędnego" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Tylko adresy IPv6 mogą mieć przypisany status SLAAC" @@ -10219,41 +10286,49 @@ msgstr "Nie można ustawić typu skope_bez identyfikatora scope_id." msgid "Cannot set scope_id without scope_type." msgstr "Nie można ustawić scope_id bez scope_type." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Zakresy nie mogą się nakładać." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"Maksymalny VID dziecka musi być większy lub równy minimalnej wartości VID " -"dziecka ({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "" "Określona strona, do której przypisana jest ta sieć VLAN (jeśli istnieje)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "Grupa VLAN (opcjonalnie)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "Numeryczny identyfikator sieci VLAN (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Stan operacyjny tej sieci VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" -msgstr "Podstawowa funkcja tej sieci VLAN" +msgstr "Podstawowa funkcja tej VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10262,7 +10337,7 @@ msgstr "" "VLAN jest przypisana do grupy {group} (zakres: {scope}); nie można również " "przypisać do witryny {site}." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "VID musi być w zakresach {ranges} dla sieci VLAN w grupie {group}" @@ -10281,7 +10356,7 @@ msgstr "egzekwuj unikalną przestrzeń" #: netbox/ipam/models/vrfs.py:43 msgid "Prevent duplicate prefixes/IP addresses within this VRF" -msgstr "Zapobiegaj zduplikowaniu prefiks/adresów IP w tym VRF" +msgstr "Zapobiegaj duplikowaniu prefiksów / adresów IP w tym VRF" #: netbox/ipam/models/vrfs.py:63 netbox/netbox/navigation/menu.py:186 #: netbox/netbox/navigation/menu.py:188 @@ -10410,17 +10485,17 @@ msgstr "Cele eksportu" #, python-brace-format msgid "{prefix} is not a valid prefix. Did you mean {suggested}?" msgstr "" -"{prefix} nie jest prawidłowym prefiksem. Czy chodziło ci o to {suggested}?" +"{prefix} nie jest prawidłowym prefiksem. Czy chodziło Ci o {suggested}?" #: netbox/ipam/validators.py:16 #, python-format msgid "The prefix length must be less than or equal to %(limit_value)s." -msgstr "Długość przedrostka musi być mniejsza lub równa %(limit_value)s." +msgstr "Długość przedrostka musi być mniejsza niż lub równa %(limit_value)s." #: netbox/ipam/validators.py:24 #, python-format msgid "The prefix length must be greater than or equal to %(limit_value)s." -msgstr "Długość przedrostka musi być większa lub równa %(limit_value)s." +msgstr "Długość przedrostka musi być większa niż lub równa %(limit_value)s." #: netbox/ipam/validators.py:33 msgid "" @@ -10432,7 +10507,7 @@ msgstr "" #: netbox/ipam/views.py:533 msgid "Child Prefixes" -msgstr "Przedrostki dziecięce" +msgstr "Prefiksy podrzędne" #: netbox/ipam/views.py:569 msgid "Child Ranges" @@ -10958,7 +11033,7 @@ msgstr "Grupy sieci bezprzewodowej sieci LAN" #: netbox/netbox/navigation/menu.py:168 msgid "Prefix & VLAN Roles" -msgstr "Role prefiksów i sieci VLAN" +msgstr "Role prefiksów i VLAN" #: netbox/netbox/navigation/menu.py:174 msgid "ASN Ranges" @@ -11029,17 +11104,12 @@ msgstr "Zasady IPsec" msgid "IPSec Profiles" msgstr "Profile IPsec" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Wirtualizacja" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Wirtualne dyski" @@ -11201,7 +11271,7 @@ msgstr "System" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11450,19 +11520,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Wiersz {i}: Obiekt z identyfikatorem {id} nie istnieje" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "Nie {object_type} zostały wybrane." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Zmiana nazwy {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Usunięte {count} {object_type}" @@ -11494,7 +11564,7 @@ msgstr "Zsynchronizowane {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} musi zaimplementować get_children ()" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11838,9 +11908,7 @@ msgid "Circuit Type" msgstr "Typ obwodu" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11851,7 +11919,6 @@ msgstr "Dodaj" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12140,35 +12207,35 @@ msgstr "dni" msgid "Indefinite" msgstr "Nieokreślony" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Nie zainstalowany" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Przegląd" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Zainstaluj" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Szczegóły wtyczki" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Podsumowanie" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Licencja" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Historia wersji" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Lokalne instrukcje instalacji" @@ -12511,8 +12578,8 @@ msgstr "Dodawanie usługi" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12585,20 +12652,24 @@ msgstr "Konfiguracja" msgid "Context Data" msgstr "Dane kontekstowe" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Wyrenderowana konfiguracja" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Ściągnij" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Nie znaleziono szablonu konfiguracji" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12620,7 +12691,6 @@ msgid "Local Config Context Data" msgstr "Dane kontekstowe konfiguracji lokalnej" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12667,12 +12737,12 @@ msgid "VM Role" msgstr "Rola maszyny wirtualnej" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Nazwa modelu" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Numer części" @@ -12811,7 +12881,7 @@ msgstr "Adres MAC" msgid "Wireless Link" msgstr "Bezprzewodowe łącze" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Peer" @@ -13434,7 +13504,7 @@ msgstr "Nie masz uprawnień do uruchamiania skryptów" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Uruchom skrypt" @@ -13447,27 +13517,32 @@ msgstr "Błąd ładowania skryptu" msgid "Script no longer exists in the source file." msgstr "Skrypt nie istnieje już w pliku źródłowym." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Ostatni bieg" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "Skrypt nie jest już obecny w pliku źródłowym" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Nigdy" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Uruchom ponownie" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Nie znaleziono skryptów" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13789,7 +13864,7 @@ msgstr "Wszystkie powiadomienia" msgid "Select" msgstr "Wybierz" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Resetuj" @@ -13987,7 +14062,7 @@ msgstr "Pierwszy dostępny adres IP" #: netbox/templates/ipam/prefix.html:179 msgid "Prefix Details" -msgstr "Szczegóły przedrostka" +msgstr "Szczegóły prefiksu" #: netbox/templates/ipam/prefix.html:185 msgid "Network Address" @@ -14043,7 +14118,7 @@ msgstr "Eksportowanie L2VPN" #: netbox/templates/ipam/vlan.html:88 msgid "Add a Prefix" -msgstr "Dodawanie prefiksu" +msgstr "Dodaj prefiks" #: netbox/templates/ipam/vlangroup.html:18 msgid "Add VLAN" @@ -14274,6 +14349,10 @@ msgstr "Zasoby" msgid "Add Virtual Disk" msgstr "Dodaj dysk wirtualny" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15350,13 +15429,13 @@ msgid "Memory (MB)" msgstr "Pamięć (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Dysk (GB)" +msgid "Disk (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Rozmiar (GB)" +msgid "Size (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15539,68 +15618,80 @@ msgstr "dysk wirtualny" msgid "virtual disks" msgstr "dyski wirtualne" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Dodano {count} urządzenia do klastrowania {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Usunięto {count} urządzenia z klastra {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPsec - Transport" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec - Tunel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP w IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GREE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Piasta" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "Mówił" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Agresywny" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Główny" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Wstępnie udostępnione klucze" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Certyfikaty" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "Podpisy RSA" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "Podpisy DSA" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15609,23 +15700,27 @@ msgstr "Podpisy DSA" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Grupa {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Prywatna sieć LAN Ethernet" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Wirtualna prywatna sieć LAN Ethernet" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Prywatne drzewo Ethernet" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Wirtualne prywatne drzewo Ethernet" diff --git a/netbox/translations/pt/LC_MESSAGES/django.mo b/netbox/translations/pt/LC_MESSAGES/django.mo index 9a287344c..e6d410f9a 100644 Binary files a/netbox/translations/pt/LC_MESSAGES/django.mo and b/netbox/translations/pt/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/pt/LC_MESSAGES/django.po b/netbox/translations/pt/LC_MESSAGES/django.po index ecc4eb05e..496b8dda1 100644 --- a/netbox/translations/pt/LC_MESSAGES/django.po +++ b/netbox/translations/pt/LC_MESSAGES/django.po @@ -6,17 +6,17 @@ # Translators: # Renato Almeida de Oliveira, 2023 # Fer22f , 2024 -# Fabricio Maciel, 2024 # Jeremy Stretch, 2024 +# Fabricio Maciel, 2024 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-13 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" -"Last-Translator: Jeremy Stretch, 2024\n" +"Last-Translator: Fabricio Maciel, 2024\n" "Language-Team: Portuguese (https://app.transifex.com/netbox-community/teams/178115/pt/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -91,8 +91,8 @@ msgstr "Sua senha foi alterada com sucesso." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -105,7 +105,7 @@ msgstr "Provisionamento" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -116,8 +116,8 @@ msgid "Active" msgstr "Ativo" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Offline" @@ -130,7 +130,7 @@ msgstr "Em Desprovisionamento" msgid "Decommissioned" msgstr "Descomissionado" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Primário" @@ -154,7 +154,7 @@ msgstr "Inativo" #: netbox/dcim/filtersets.py:464 netbox/dcim/filtersets.py:1021 #: netbox/dcim/filtersets.py:1368 netbox/dcim/filtersets.py:1903 #: netbox/dcim/filtersets.py:2146 netbox/dcim/filtersets.py:2204 -#: netbox/ipam/filtersets.py:339 netbox/ipam/filtersets.py:959 +#: netbox/ipam/filtersets.py:341 netbox/ipam/filtersets.py:961 #: netbox/virtualization/filtersets.py:45 #: netbox/virtualization/filtersets.py:173 netbox/vpn/filtersets.py:358 msgid "Region (ID)" @@ -166,8 +166,8 @@ msgstr "Região (ID)" #: netbox/dcim/filtersets.py:471 netbox/dcim/filtersets.py:1028 #: netbox/dcim/filtersets.py:1375 netbox/dcim/filtersets.py:1910 #: netbox/dcim/filtersets.py:2153 netbox/dcim/filtersets.py:2211 -#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:346 -#: netbox/ipam/filtersets.py:966 netbox/virtualization/filtersets.py:52 +#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:348 +#: netbox/ipam/filtersets.py:968 netbox/virtualization/filtersets.py:52 #: netbox/virtualization/filtersets.py:180 netbox/vpn/filtersets.py:353 msgid "Region (slug)" msgstr "Região (slug)" @@ -177,8 +177,8 @@ msgstr "Região (slug)" #: netbox/dcim/filtersets.py:346 netbox/dcim/filtersets.py:477 #: netbox/dcim/filtersets.py:1034 netbox/dcim/filtersets.py:1381 #: netbox/dcim/filtersets.py:1916 netbox/dcim/filtersets.py:2159 -#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:352 -#: netbox/ipam/filtersets.py:972 netbox/virtualization/filtersets.py:58 +#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:354 +#: netbox/ipam/filtersets.py:974 netbox/virtualization/filtersets.py:58 #: netbox/virtualization/filtersets.py:186 msgid "Site group (ID)" msgstr "Grupo de sites (ID)" @@ -189,7 +189,7 @@ msgstr "Grupo de sites (ID)" #: netbox/dcim/filtersets.py:1041 netbox/dcim/filtersets.py:1388 #: netbox/dcim/filtersets.py:1923 netbox/dcim/filtersets.py:2166 #: netbox/dcim/filtersets.py:2224 netbox/extras/filtersets.py:515 -#: netbox/ipam/filtersets.py:359 netbox/ipam/filtersets.py:979 +#: netbox/ipam/filtersets.py:361 netbox/ipam/filtersets.py:981 #: netbox/virtualization/filtersets.py:65 #: netbox/virtualization/filtersets.py:193 msgid "Site group (slug)" @@ -203,12 +203,12 @@ msgstr "Grupo de sites (slug)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -217,18 +217,17 @@ msgstr "Grupo de sites (slug)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -260,8 +259,8 @@ msgstr "Site" #: netbox/circuits/filtersets.py:62 netbox/circuits/filtersets.py:229 #: netbox/circuits/filtersets.py:274 netbox/dcim/filtersets.py:242 #: netbox/dcim/filtersets.py:363 netbox/dcim/filtersets.py:458 -#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:238 -#: netbox/ipam/filtersets.py:369 netbox/ipam/filtersets.py:989 +#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:240 +#: netbox/ipam/filtersets.py:371 netbox/ipam/filtersets.py:991 #: netbox/virtualization/filtersets.py:75 #: netbox/virtualization/filtersets.py:203 netbox/vpn/filtersets.py:363 msgid "Site (slug)" @@ -280,13 +279,13 @@ msgstr "ASN" #: netbox/circuits/filtersets.py:95 netbox/circuits/filtersets.py:122 #: netbox/circuits/filtersets.py:156 netbox/circuits/filtersets.py:283 -#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:243 +#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:245 msgid "Provider (ID)" msgstr "Provedor (ID)" #: netbox/circuits/filtersets.py:101 netbox/circuits/filtersets.py:128 #: netbox/circuits/filtersets.py:162 netbox/circuits/filtersets.py:289 -#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:249 +#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:251 msgid "Provider (slug)" msgstr "Provedor (slug)" @@ -315,8 +314,8 @@ msgstr "Tipo de circuito (slug)" #: netbox/dcim/filtersets.py:452 netbox/dcim/filtersets.py:1045 #: netbox/dcim/filtersets.py:1393 netbox/dcim/filtersets.py:1928 #: netbox/dcim/filtersets.py:2170 netbox/dcim/filtersets.py:2229 -#: netbox/ipam/filtersets.py:232 netbox/ipam/filtersets.py:363 -#: netbox/ipam/filtersets.py:983 netbox/virtualization/filtersets.py:69 +#: netbox/ipam/filtersets.py:234 netbox/ipam/filtersets.py:365 +#: netbox/ipam/filtersets.py:985 netbox/virtualization/filtersets.py:69 #: netbox/virtualization/filtersets.py:197 netbox/vpn/filtersets.py:368 msgid "Site (ID)" msgstr "Site (ID)" @@ -336,10 +335,10 @@ msgstr "Terminação A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -391,7 +390,7 @@ msgstr "Grupo de circuitos (slug)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -406,33 +405,33 @@ msgstr "ASNs" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -441,7 +440,7 @@ msgstr "ASNs" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -456,7 +455,7 @@ msgstr "ASNs" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -476,7 +475,7 @@ msgstr "ASNs" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -569,10 +568,10 @@ msgid "Service ID" msgstr "ID do serviço" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -593,16 +592,16 @@ msgstr "Cor" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -657,14 +656,14 @@ msgstr "Conta do provedor" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -673,13 +672,13 @@ msgstr "Conta do provedor" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -690,7 +689,7 @@ msgstr "Conta do provedor" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -726,30 +725,30 @@ msgstr "Status" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -819,11 +818,11 @@ msgstr "Parâmetros do serviço" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -855,11 +854,11 @@ msgstr "Velocidade da porta (Kbps)" msgid "Upstream speed (Kbps)" msgstr "Velocidade de upstream (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Marcar como conectado" @@ -906,10 +905,10 @@ msgstr "Tipo de circuito" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -919,13 +918,13 @@ msgstr "Status operacional" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -950,12 +949,12 @@ msgstr "Rede do provedor" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -972,9 +971,9 @@ msgstr "Rede do provedor" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1003,8 +1002,8 @@ msgid "Contacts" msgstr "Contatos" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1012,13 +1011,12 @@ msgstr "Contatos" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1031,16 +1029,16 @@ msgid "Region" msgstr "Região" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1052,7 +1050,7 @@ msgstr "Grupo de sites" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1091,9 +1089,9 @@ msgstr "Conta" msgid "Term Side" msgstr "Lado da Terminação" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1103,11 +1101,11 @@ msgstr "Atribuição" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:1001 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1179,20 +1177,20 @@ msgid "Unique circuit ID" msgstr "ID única do circuito" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "status" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "instalado" @@ -1314,11 +1312,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1329,7 +1327,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1417,7 +1415,7 @@ msgstr "redes dos provedores" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1428,7 +1426,7 @@ msgstr "redes dos provedores" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1459,7 +1457,7 @@ msgstr "redes dos provedores" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1623,7 +1621,7 @@ msgstr "Concluído" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Falhou" @@ -1690,7 +1688,7 @@ msgid "Cancelled" msgstr "Cancelado" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Local" @@ -1777,8 +1775,8 @@ msgid "User name" msgstr "Nome de usuário" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1882,7 +1880,7 @@ msgid "Completed before" msgstr "Concluído antes" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1951,9 +1949,9 @@ msgstr "" msgid "Rack Elevations" msgstr "Elevações de Rack" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Alimentação Elétrica" @@ -2053,7 +2051,7 @@ msgid "Change logging is not supported for this object type ({type})." msgstr "Changelog não é suportado para este tipo de objeto ({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2113,7 +2111,7 @@ msgstr "tipo" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2235,58 +2233,58 @@ msgstr "arquivo gerenciado" msgid "managed files" msgstr "arquivos gerenciados" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "agendado" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "intervalo" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Intervalo de recorrência (em minutos)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "iniciado" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "concluído" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "dados" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "erro" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "ID da tarefa" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "tarefa" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "tarefas" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "Tarefas não podem ser atribuídas a este tipo de objeto ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "Status inválido para encerramento da tarefa. As opções são: {choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" @@ -2371,7 +2369,7 @@ msgstr "Versão Máxima do Netbox" msgid "No plugin data found" msgstr "Nenhum dado do plugin encontrado" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Autor" @@ -2379,7 +2377,7 @@ msgstr "Autor" msgid "Installed" msgstr "Instalado" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Certificado" @@ -2505,11 +2503,11 @@ msgstr "Tarefa {id} foi interrompida." msgid "Failed to stop job {id}" msgstr "Falha ao interromper a tarefa {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "Catálogo de plugins não pode ser carregado" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Plugin {name} não encontrado" @@ -2529,7 +2527,7 @@ msgid "Staging" msgstr "Em Preparação" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Em Descomissionamento" @@ -2593,7 +2591,7 @@ msgstr "Obsoleto" msgid "Millimeters" msgstr "Milímetros" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "Polegadas" @@ -2607,15 +2605,15 @@ msgstr "Frente para trás" msgid "Rear to front" msgstr "Trás para frente" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2695,7 +2693,7 @@ msgid "Top to bottom" msgstr "De cima para baixo" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Passivo" @@ -2724,8 +2722,8 @@ msgid "Proprietary" msgstr "Proprietário" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Outros" @@ -2738,24 +2736,24 @@ msgstr "ITA/Internacional" msgid "Physical" msgstr "Físico" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Virtual" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Wireless" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Interfaces virtuais" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2764,27 +2762,27 @@ msgstr "Interfaces virtuais" msgid "Bridge" msgstr "Bridge" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Link Aggregation (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (fixa)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (modular)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (backplane)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Celular" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2792,130 +2790,130 @@ msgstr "Celular" msgid "Serial" msgstr "Serial" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Coaxial" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "Empilhamento" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Half" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Full" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Automático" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Acesso" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Tagueada" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Tagueada (Todos)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "Padrão IEEE" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "24V passivo (2 pares)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "24V passivo (4 pares)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "48V passivo (2 pares)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "48V passivo (4 pares)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Cabo Metálico" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Fibra Óptica" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Fibra" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Conectado" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Quilômetros" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Metros" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Centímetros" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Milhas" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Pés" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Quilogramas" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Gramas" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "Libras" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Onças" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Redundante" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Monofásico" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Trifásico" @@ -2946,7 +2944,7 @@ msgid "Parent site group (slug)" msgstr "Grupo de sites principais (slug)" #: netbox/dcim/filtersets.py:164 netbox/extras/filtersets.py:364 -#: netbox/ipam/filtersets.py:841 netbox/ipam/filtersets.py:993 +#: netbox/ipam/filtersets.py:843 netbox/ipam/filtersets.py:995 msgid "Group (ID)" msgstr "Grupo (ID)" @@ -3004,15 +3002,15 @@ msgstr "Tipo de rack (ID)" #: netbox/dcim/filtersets.py:411 netbox/dcim/filtersets.py:892 #: netbox/dcim/filtersets.py:994 netbox/dcim/filtersets.py:1850 -#: netbox/ipam/filtersets.py:381 netbox/ipam/filtersets.py:493 -#: netbox/ipam/filtersets.py:1003 netbox/virtualization/filtersets.py:210 +#: netbox/ipam/filtersets.py:383 netbox/ipam/filtersets.py:495 +#: netbox/ipam/filtersets.py:1005 netbox/virtualization/filtersets.py:210 msgid "Role (ID)" msgstr "Função (ID)" #: netbox/dcim/filtersets.py:417 netbox/dcim/filtersets.py:898 #: netbox/dcim/filtersets.py:1000 netbox/dcim/filtersets.py:1856 -#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:387 -#: netbox/ipam/filtersets.py:499 netbox/ipam/filtersets.py:1009 +#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:389 +#: netbox/ipam/filtersets.py:501 netbox/ipam/filtersets.py:1011 #: netbox/virtualization/filtersets.py:216 msgid "Role (slug)" msgstr "Função (slug)" @@ -3161,7 +3159,7 @@ msgstr "Grupo de clusters (ID)" msgid "Device model (slug)" msgstr "Modelo do dispositivo (slug)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "É full-depth" @@ -3210,7 +3208,7 @@ msgstr "Contexto de Dispositivo Virtual (ID)" msgid "Device model" msgstr "Modelo de dispositivo" -#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:632 +#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:634 #: netbox/vpn/filtersets.py:102 netbox/vpn/filtersets.py:401 msgid "Interface (ID)" msgstr "Interface (ID)" @@ -3224,8 +3222,8 @@ msgid "Module bay (ID)" msgstr "Compartimento de módulo (ID)" #: netbox/dcim/filtersets.py:1333 netbox/dcim/filtersets.py:1425 -#: netbox/ipam/filtersets.py:611 netbox/ipam/filtersets.py:851 -#: netbox/ipam/filtersets.py:1115 netbox/virtualization/filtersets.py:161 +#: netbox/ipam/filtersets.py:613 netbox/ipam/filtersets.py:853 +#: netbox/ipam/filtersets.py:1117 netbox/virtualization/filtersets.py:161 #: netbox/vpn/filtersets.py:379 msgid "Device (ID)" msgstr "Dispositivo (ID)" @@ -3234,8 +3232,8 @@ msgstr "Dispositivo (ID)" msgid "Rack (name)" msgstr "Rack (nome)" -#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:606 -#: netbox/ipam/filtersets.py:846 netbox/ipam/filtersets.py:1121 +#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:608 +#: netbox/ipam/filtersets.py:848 netbox/ipam/filtersets.py:1123 #: netbox/vpn/filtersets.py:374 msgid "Device (name)" msgstr "Dispositivo (nome)" @@ -3283,21 +3281,21 @@ msgstr "VLAN Designada" msgid "Assigned VID" msgstr "VLAN ID Designada " -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 -#: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 -#: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 -#: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:318 +#: netbox/ipam/filtersets.py:329 netbox/ipam/filtersets.py:485 +#: netbox/ipam/filtersets.py:586 netbox/ipam/filtersets.py:597 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3316,19 +3314,19 @@ msgstr "VLAN ID Designada " msgid "VRF" msgstr "VRF" -#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:322 -#: netbox/ipam/filtersets.py:333 netbox/ipam/filtersets.py:489 -#: netbox/ipam/filtersets.py:590 netbox/ipam/filtersets.py:601 +#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:324 +#: netbox/ipam/filtersets.py:335 netbox/ipam/filtersets.py:491 +#: netbox/ipam/filtersets.py:592 netbox/ipam/filtersets.py:603 msgid "VRF (RD)" msgstr "VRF (RD)" -#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1030 +#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1032 #: netbox/vpn/filtersets.py:342 msgid "L2VPN (ID)" msgstr "L2VPN (ID)" #: netbox/dcim/filtersets.py:1630 netbox/dcim/forms/filtersets.py:1433 -#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1036 +#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1038 #: netbox/ipam/forms/filtersets.py:518 netbox/ipam/tables/vlans.py:137 #: netbox/templates/dcim/interface.html:93 netbox/templates/ipam/vlan.html:66 #: netbox/templates/vpn/l2vpntermination.html:12 @@ -3364,7 +3362,7 @@ msgid "LAG interface (ID)" msgstr "Interface LAG (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Contexto de Dispositivo Virtual" @@ -3438,7 +3436,7 @@ msgstr "Etiquetas" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3455,38 +3453,38 @@ msgstr "" "Intervalos alfanuméricos são suportados. (Devem corresponder ao número de " "nomes que estão sendo criados.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Contato" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Telefone de Contato" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "E-mail de Contato" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Fuso horário" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3496,58 +3494,59 @@ msgstr "Fuso horário" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Fabricante" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Formato físico" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Largura" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Altura (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Unidades descendentes" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Largura externa" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Profundidade externa" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Unidade externa" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Profundidade de montagem" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3558,10 +3557,10 @@ msgstr "Profundidade de montagem" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3570,61 +3569,61 @@ msgstr "Profundidade de montagem" msgid "Weight" msgstr "Peso" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Peso máximo" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Unidade de peso" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Tipo de Rack" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Dimensões externas" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Dimensões" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Numeração" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3652,45 +3651,50 @@ msgstr "Numeração" msgid "Role" msgstr "Função" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Tipo de rack" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Número de Série" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Etiqueta de patrimônio" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Fluxo de Ar" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3700,64 +3704,64 @@ msgstr "Fluxo de Ar" msgid "Rack" msgstr "Rack" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Hardware" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Plataforma padrão" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Part number" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "Altura em U" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Excluir da utilização" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Tipo de Dispositivo" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Tipo de Módulo" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Chassi" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "Função da VM" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3768,19 +3772,19 @@ msgstr "Função da VM" msgid "Config template" msgstr "Modelo de configuração" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Tipo de dispositivo" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Função do dispositivo" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3794,14 +3798,36 @@ msgstr "Função do dispositivo" msgid "Platform" msgstr "Plataforma" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Cluster" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3811,9 +3837,9 @@ msgstr "Plataforma" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3822,10 +3848,10 @@ msgstr "Plataforma" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3852,7 +3878,7 @@ msgstr "Plataforma" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3862,23 +3888,28 @@ msgstr "Plataforma" msgid "Device" msgstr "Dispositivo" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Configuração" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Virtualização" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Tipo de módulo" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3896,109 +3927,109 @@ msgstr "Tipo de módulo" msgid "Label" msgstr "Rótulo" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Comprimento" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Unidade de comprimento" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Domínio" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "Quadro de alimentação" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Tipo de Alimentação" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Fase" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Tensão" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Corrente" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Utilização máxima" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Consumo máximo" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Consumo máximo de energia (Watts)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Consumo alocado" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Consumo de energia alocado (Watts)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Porta de alimentação" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Ramal de alimentação" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Somente gerenciamento" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "Modo de Operação" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "Tipo de PoE" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Função do Wireless" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4012,17 +4043,17 @@ msgstr "Função do Wireless" msgid "Module" msgstr "Módulo" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "LAG" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Contextos de dispositivos virtuais" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4031,7 +4062,7 @@ msgstr "Contextos de dispositivos virtuais" msgid "Speed" msgstr "Velocidade" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4045,76 +4076,88 @@ msgstr "Velocidade" msgid "Mode" msgstr "Modo" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "Grupo de VLANs" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "VLAN Não Tagueada" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "VLANs Tagueadas" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "Adicionar VLANs tagueadas" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "Remover VLANs tagueadas" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Grupo da Rede Wireless" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "Redes Wireless" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Endereçamento" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Operação" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Interfaces Relacionadas" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "Comutação 802.1Q" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "Adicionar/Remover" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "O modo de interface deve ser especificado para atribuir VLANs" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "Uma interface de acesso não pode ter VLANs tagueadas." @@ -4140,9 +4183,9 @@ msgstr "Grupo designado" msgid "available options" msgstr "opções disponíveis" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4164,15 +4207,15 @@ msgstr "Fabricante deste tipo de rack" msgid "The lowest-numbered position in the rack" msgstr "A numeração de posição mais baixa no rack" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Largura de trilho a trilho (em polegadas)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Unidade para dimensões externas" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Unidade de peso do rack" @@ -4184,158 +4227,149 @@ msgstr "Nome do inquilino designado" msgid "Name of assigned role" msgstr "Nome da função designada" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "Modelo do tipo de rack" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Direção do fluxo de ar" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "A largura deve ser definida se um tipo de rack não for especificado." + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" +"A altura em U deve ser definida se um tipo de rack não for especificado." + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Site principal" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Localização do rack (se houver)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Unidades" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Lista separada por vírgula de unidades individuais" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "Fabricante que produz este tipo de dispositivo" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "A plataforma padrão para dispositivos deste tipo (opcional)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Peso do dispositivo" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Unidade de peso do dispositivo" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Peso do módulo" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Unidade de peso do módulo" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Limitar as atribuições de plataforma a este fabricante" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Função designada" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Fabricante do tipo de dispositivo" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Modelo do tipo de dispositivo" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Plataforma designada" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Chassi virtual" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Cluster" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Cluster de virtualização" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Local designado (se houver)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Rack designado (se houver)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Face" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Face do rack em que está montado" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Dispositivo pai (para dispositivos filhos)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Compartimento de dispositivos" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" "Compartimento de dispositivos no qual este dispositivo está instalado (para " "dispositivos filhos)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "O dispositivo no qual este módulo está instalado" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Compartimento de módulo" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "O compartimento no qual este módulo está instalado" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "O tipo de módulo" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Replicar componentes" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4343,87 +4377,87 @@ msgstr "" "Popular automaticamente os componentes associados a este tipo de módulo " "(ativado por padrão)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Adotar componentes" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Adotar componentes já existentes" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Tipo de porta" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Velocidade da porta em bps" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Tipo de tomada" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Porta de alimentação local que alimenta esta tomada" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Fase (para circuitos trifásicos)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Interface pai" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Interface bridged" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "LAG" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Interface LAG pai" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "Contextos de Dispositivos Virtuais" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" "Nomes de contextos de dispositivos virtuais separados por vírgulas, entre " "aspas duplas. Exemplo:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Meio físico" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Duplex" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "Modo de operação do PoE" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Tipo de PoE" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "Modo de operação do IEEE 802.1Q (para interfaces L2)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4431,174 +4465,174 @@ msgstr "Modo de operação do IEEE 802.1Q (para interfaces L2)" msgid "Assigned VRF" msgstr "VRF designado" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Função RF" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Função do Wireless (AP/Station)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "" "Contexto de dispositivo virtual {vdc} não está associado ao dispositivo " "{device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Porta traseira" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Porta traseira correspondente" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Tipo de conexão do meio físico" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Dispositivo instalado" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "Dispositivo filho instalado neste compartimento" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Dispositivo filho não encontrado." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Item pai do inventário" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Tipo de componente" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Tipo de Componente" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Nome do componente" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Nome do Componente" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Componente não encontrado: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Dispositivo no lado A" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Nome do dispositivo" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Tipo de terminação no lado A" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Tipo de terminação" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Nome da terminação no lado A" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Nome da terminação" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Dispositivo no lado B" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Tipo de terminação no lado B" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Nome da terminação no lado B" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Status da conexão" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "Lado {side_upper}: {device} {termination_object} já está conectado" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr " Terminação {side_upper} não encontrada: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Mestre" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Dispositivo mestre" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Nome do site principal" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "Quadro de alimentação" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Primário ou redundante" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Tipo de alimentação (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Monofásico ou trifásico" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "IPv4 Primário" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "Endereço IPv4 com máscara, por exemplo, 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "IPv6 Primário" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "Endereço IPv6 com tamanho de prefixo, por exemplo, 2001:db8: :1/64" @@ -4686,10 +4720,6 @@ msgstr "Grupo principal" msgid "Facility" msgstr "Facility" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Tipo de rack" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Função" @@ -4726,7 +4756,7 @@ msgid "Has virtual device contexts" msgstr "Possui contextos de dispositivos virtuais" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Grupo de clusters" @@ -4765,7 +4795,7 @@ msgstr "Tipo" msgid "Mgmt only" msgstr "Somente gerenciamento" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4869,36 +4899,51 @@ msgstr "" msgid "Characteristics" msgstr "Características" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" +"Intervalos alfanuméricos são suportados para criação em massa. Casos e tipos" +" mistos dentro de um único intervalo não são suportados (exemplo: " +"[ge,xe]-0/0/[0-9]). O token {module}, se presente," +" será automaticamente substituído pelo valor da posição ao criar um novo " +"módulo." + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Modelo da porta de console" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Modelo da porta do servidor de console" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Modelo da porta frontal" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Modelo da interface" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Modelo da tomada elétrica" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Modelo da porta de alimentação" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Modelo da porta traseira" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4922,7 +4967,7 @@ msgstr "Modelo da porta traseira" msgid "Interface" msgstr "Interface" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4930,14 +4975,14 @@ msgstr "Interface" msgid "Console Port" msgstr "Porta de Console" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Porta do Servidor de Console" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4948,7 +4993,7 @@ msgstr "Porta do Servidor de Console" msgid "Front Port" msgstr "Porta Frontal" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4961,40 +5006,40 @@ msgstr "Porta Frontal" msgid "Rear Port" msgstr "Porta Traseira" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Porta de Alimentação" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Tomada Elétrica" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Atribuição de Componentes" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "Um item de inventário só pode ser associado a um único componente." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "Interface LAG" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Filtre as VLANs disponíveis para atribuição por grupo." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Dispositivo Filho" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -5002,35 +5047,35 @@ msgstr "" "Os dispositivos filhos devem primeiro ser criados e atribuídos ao site e ao " "rack do dispositivo pai." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Porta de console" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Porta do servidor de console" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Porta frontal" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "Tomada elétrica" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Item de Inventário" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Função do Item de Inventário" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5048,12 +5093,12 @@ msgstr "" " esperados." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Portas traseiras" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" "Selecione uma atribuição de porta traseira para cada porta frontal que está " @@ -5069,16 +5114,7 @@ msgstr "" "deve corresponder ao número selecionado de posições dE porta traseira " "({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"A string {module} será substituída pela posição do módulo " -"designado, se houver." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5088,18 +5124,18 @@ msgstr "" "corresponder ao número selecionado de posições de portas traseiras " "({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Membros" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Posição inicial" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." @@ -5107,7 +5143,7 @@ msgstr "" "Posição do primeiro dispositivo membro. Aumenta em um para cada membro " "adicional." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "" "Uma posição deve ser especificada para o primeiro membro do chassi virtual." @@ -6056,12 +6092,12 @@ msgstr "posição (U)" msgid "rack face" msgstr "face do rack" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "IPv4 primário" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "IPv6 primário" @@ -6237,22 +6273,22 @@ msgstr "" "O módulo deve ser instalado dentro de um compartimento pertencente ao " "dispositivo ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "domínio" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "chassi virtual" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "" "O mestre selecionado ({master}) não está associado a este chassi virtual." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6261,34 +6297,34 @@ msgstr "" "Não foi possível excluir o chassi virtual {self}. Existem interfaces membro " "que formam interfaces LAG entre chassis." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "identificador" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Identificador numérico exclusivo para o dispositivo principal" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "comentários" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "contexto de dispositivo virtual" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "contextos de dispositivos virtuais" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} não é um endereço IPv{family}." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" "O endereço IP primário deve pertencer a uma interface no dispositivo " @@ -6468,7 +6504,7 @@ msgstr "função do rack" #: netbox/dcim/models/racks.py:231 msgid "rack roles" -msgstr "funções de rack" +msgstr "funções do rack" #: netbox/dcim/models/racks.py:274 msgid "facility ID" @@ -6480,7 +6516,7 @@ msgstr "Identificador atribuído localmente" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Papel funcional" @@ -6690,7 +6726,7 @@ msgstr "Acessível" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Dispositivos" @@ -6719,8 +6755,8 @@ msgid "Site Group" msgstr "Grupo de Sites" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6771,20 +6807,20 @@ msgid "Power outlets" msgstr "Tomadas elétricas" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Interfaces" @@ -6810,8 +6846,8 @@ msgid "Module Bay" msgstr "Compartimento de módulo" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6840,7 +6876,7 @@ msgstr "Consumo máximo (W)" msgid "Allocated draw (W)" msgstr "Consumo alocado (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6936,87 +6972,87 @@ msgstr "Altura em U" msgid "Instances" msgstr "Instâncias" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Portas de Console" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Portas de Servidor de Console" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Portas de Alimentação" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Tomadas Elétricas" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Portas Frontais" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Portas Traseiras" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Compartimentos de Dispositivos" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Compartimentos de Módulos" @@ -7065,7 +7101,7 @@ msgstr "Espaço" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7075,28 +7111,28 @@ msgstr "Sites" msgid "Test case must set peer_termination_type" msgstr "O caso de teste deve definir peer_termination_type" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Desconectado {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Reservas" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Dispositivos Não Montados em Rack" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Contexto de Configuração" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Renderização de Configuração" @@ -7107,36 +7143,36 @@ msgstr "Ocorreu um erro ao renderizar o modelo: {error}" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Máquinas Virtuais" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Dispositivo instalado {device} no compartimento {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Dispositivo {device} removido do compartimento {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Filhos" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Membro {device} adicionado" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "" "Não é possível remover o dispositivo principal {device} do chassi virtual." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "Removido {device} do chassi virtual {chassis}" @@ -7319,7 +7355,6 @@ msgstr "Atualizar" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -8153,19 +8188,19 @@ msgstr "Programe a execução do script para um horário definido" msgid "Interval at which this script is re-run (in minutes)" msgstr "Intervalo no qual este script é executado novamente (em minutos)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "As alterações no banco de dados foram revertidas automaticamente." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Script abortado com erro: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Ocorreu uma exceção: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "As alterações do banco de dados foram revertidas devido a um erro." @@ -9198,7 +9233,7 @@ msgstr "Widget excluído: " msgid "Error deleting widget: " msgstr "Erro ao excluir o widget: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "" "Não é possível executar o script: o processo do agente RQ não está em " @@ -9317,129 +9352,129 @@ msgstr "Exportando L2VPN" msgid "Exporting L2VPN (identifier)" msgstr "Exportando L2VPN (identificador)" -#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:281 +#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:283 #: netbox/ipam/forms/model_forms.py:229 netbox/ipam/tables/ip.py:212 #: netbox/templates/ipam/prefix.html:12 msgid "Prefix" msgstr "Prefixo" #: netbox/ipam/filtersets.py:159 netbox/ipam/filtersets.py:198 -#: netbox/ipam/filtersets.py:221 +#: netbox/ipam/filtersets.py:223 msgid "RIR (ID)" msgstr "RIR (ID)" #: netbox/ipam/filtersets.py:165 netbox/ipam/filtersets.py:204 -#: netbox/ipam/filtersets.py:227 +#: netbox/ipam/filtersets.py:229 msgid "RIR (slug)" msgstr "RIR (slug)" -#: netbox/ipam/filtersets.py:285 +#: netbox/ipam/filtersets.py:287 msgid "Within prefix" msgstr "Dentro do prefixo" -#: netbox/ipam/filtersets.py:289 +#: netbox/ipam/filtersets.py:291 msgid "Within and including prefix" msgstr "Dentro e incluindo o prefixo" -#: netbox/ipam/filtersets.py:293 +#: netbox/ipam/filtersets.py:295 msgid "Prefixes which contain this prefix or IP" msgstr "Prefixos que contêm este prefixo ou IP" -#: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/filtersets.py:306 netbox/ipam/filtersets.py:574 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Tamanho da máscara" -#: netbox/ipam/filtersets.py:373 netbox/vpn/filtersets.py:427 +#: netbox/ipam/filtersets.py:375 netbox/vpn/filtersets.py:427 msgid "VLAN (ID)" msgstr "VLAN (ID)" -#: netbox/ipam/filtersets.py:377 netbox/vpn/filtersets.py:422 +#: netbox/ipam/filtersets.py:379 netbox/vpn/filtersets.py:422 msgid "VLAN number (1-4094)" msgstr "Número da VLAN (1-4094)" -#: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:473 netbox/ipam/filtersets.py:477 +#: netbox/ipam/filtersets.py:569 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" msgstr "Endereço" -#: netbox/ipam/filtersets.py:479 +#: netbox/ipam/filtersets.py:481 msgid "Ranges which contain this prefix or IP" msgstr "Faixas que contêm este prefixo ou IP" -#: netbox/ipam/filtersets.py:507 netbox/ipam/filtersets.py:563 +#: netbox/ipam/filtersets.py:509 netbox/ipam/filtersets.py:565 msgid "Parent prefix" msgstr "Prefixo pai" -#: netbox/ipam/filtersets.py:616 netbox/ipam/filtersets.py:856 -#: netbox/ipam/filtersets.py:1131 netbox/vpn/filtersets.py:385 +#: netbox/ipam/filtersets.py:618 netbox/ipam/filtersets.py:858 +#: netbox/ipam/filtersets.py:1133 netbox/vpn/filtersets.py:385 msgid "Virtual machine (name)" msgstr "Máquina virtual (nome)" -#: netbox/ipam/filtersets.py:621 netbox/ipam/filtersets.py:861 -#: netbox/ipam/filtersets.py:1125 netbox/virtualization/filtersets.py:282 +#: netbox/ipam/filtersets.py:623 netbox/ipam/filtersets.py:863 +#: netbox/ipam/filtersets.py:1127 netbox/virtualization/filtersets.py:282 #: netbox/virtualization/filtersets.py:321 netbox/vpn/filtersets.py:390 msgid "Virtual machine (ID)" msgstr "Máquina virtual (ID)" -#: netbox/ipam/filtersets.py:627 netbox/vpn/filtersets.py:97 +#: netbox/ipam/filtersets.py:629 netbox/vpn/filtersets.py:97 #: netbox/vpn/filtersets.py:396 msgid "Interface (name)" msgstr "Interface (nome)" -#: netbox/ipam/filtersets.py:638 netbox/vpn/filtersets.py:108 +#: netbox/ipam/filtersets.py:640 netbox/vpn/filtersets.py:108 #: netbox/vpn/filtersets.py:407 msgid "VM interface (name)" msgstr "Interface da VM (nome)" -#: netbox/ipam/filtersets.py:643 netbox/vpn/filtersets.py:113 +#: netbox/ipam/filtersets.py:645 netbox/vpn/filtersets.py:113 msgid "VM interface (ID)" msgstr "Interface da VM (ID)" -#: netbox/ipam/filtersets.py:648 +#: netbox/ipam/filtersets.py:650 msgid "FHRP group (ID)" msgstr "Grupo FHRP (ID)" -#: netbox/ipam/filtersets.py:652 +#: netbox/ipam/filtersets.py:654 msgid "Is assigned to an interface" msgstr "Está associado a uma interface" -#: netbox/ipam/filtersets.py:656 +#: netbox/ipam/filtersets.py:658 msgid "Is assigned" msgstr "Está associado" -#: netbox/ipam/filtersets.py:668 +#: netbox/ipam/filtersets.py:670 msgid "Service (ID)" msgstr "Serviço (ID)" -#: netbox/ipam/filtersets.py:673 +#: netbox/ipam/filtersets.py:675 msgid "NAT inside IP address (ID)" msgstr "NAT dentro do endereço IP (ID)" -#: netbox/ipam/filtersets.py:1041 netbox/ipam/forms/bulk_import.py:322 +#: netbox/ipam/filtersets.py:1043 netbox/ipam/forms/bulk_import.py:322 msgid "Assigned interface" msgstr "Interface associada" -#: netbox/ipam/filtersets.py:1046 +#: netbox/ipam/filtersets.py:1048 msgid "Assigned VM interface" msgstr "Interface de VM atribuída" -#: netbox/ipam/filtersets.py:1136 +#: netbox/ipam/filtersets.py:1138 msgid "IP address (ID)" msgstr "Endereço IP (ID)" -#: netbox/ipam/filtersets.py:1142 netbox/ipam/models/ip.py:788 +#: netbox/ipam/filtersets.py:1144 netbox/ipam/models/ip.py:788 msgid "IP address" msgstr "Endereço IP" -#: netbox/ipam/filtersets.py:1167 +#: netbox/ipam/filtersets.py:1169 msgid "Primary IPv4 (ID)" msgstr "IPv4 Primário (ID)" -#: netbox/ipam/filtersets.py:1172 +#: netbox/ipam/filtersets.py:1174 msgid "Primary IPv6 (ID)" msgstr "IPv6 Primário (ID)" @@ -9472,16 +9507,16 @@ msgstr "A máscara CIDR (por exemplo, /24) é obrigatória." msgid "Address pattern" msgstr "Padrão de endereço" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Imponha um espaço exclusivo" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "É privado" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9495,20 +9530,20 @@ msgstr "É privado" msgid "RIR" msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Data da adição" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "Grupo de VLANs" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9521,32 +9556,32 @@ msgstr "Grupo de VLANs" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Comprimento do prefixo" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "É um pool" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Trate como totalmente utilizado" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "Atribuição de VLAN" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "Nome DNS" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9554,12 +9589,12 @@ msgstr "Nome DNS" msgid "Protocol" msgstr "Protocolo" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "ID do Grupo" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9571,12 +9606,12 @@ msgstr "ID do Grupo" msgid "Authentication type" msgstr "Tipo de autenticação" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Chave de autenticação" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9588,26 +9623,26 @@ msgstr "Chave de autenticação" msgid "Authentication" msgstr "Autenticação" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Tipo de escopo" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "Faixas para ID de VLAN." - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Escopo" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "Faixas para ID de VLAN." + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Site e Grupo" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9634,8 +9669,8 @@ msgstr "Grupo de VLANs (se houver)" msgid "Parent device of assigned interface (if any)" msgstr "Dispositivo pai da interface associada (se houver)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9661,42 +9696,65 @@ msgstr "É primário" msgid "Make this the primary IP for the assigned device" msgstr "Tornar este o IP primário do dispositivo associado" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "É out-of-band" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" +"Designar este como endereço IP out-f-band para o dispositvo associado." + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "Nenhum dispositivo ou máquina virtual especificado; não pode ser definido " "como IP primário" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" +"Nenhum dispositivo especificado; não pode ser definido como IP out-of-band" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "Não é possível definir IP out-of-band para máquinas virtuais" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "" "Nenhuma interface especificada; não é possível definir como IP primário" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" +"Nenhuma interface especificada; não pode ser definido como IP out-of-band" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Tipo de autenticação" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Tipo de escopo (aplicativo e modelo)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Grupo de VLANs associado" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "Protocolo IP" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Obrigatório se não estiver atribuído a uma VM" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Obrigatório se não estiver atribuído a um dispositivo" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} não está associado a este dispositivo/VM." @@ -9778,7 +9836,7 @@ msgstr "Associado a uma interface" msgid "DNS Name" msgstr "Nome DNS" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9789,13 +9847,13 @@ msgstr "VLANs" msgid "Contains VLAN ID" msgstr "Contém ID de VLAN" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "ID da VLAN" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9806,7 +9864,7 @@ msgstr "ID da VLAN" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9835,8 +9893,8 @@ msgstr "Atribuição de Site/VLAN" msgid "IP Range" msgstr "Faixa de IP" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "Grupo FHRP" @@ -9845,47 +9903,61 @@ msgstr "Grupo FHRP" msgid "Make this the primary IP for the device/VM" msgstr "Torne este o IP primário do dispositivo/VM" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "Definir este como endereço IP out-of-band para o dispositivo" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "IP NAT (interno)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "Um endereço IP só pode ser atribuído a um único objeto." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Não é possível reatribuir o endereço IP enquanto ele estiver designado como " -"o IP primário do objeto pai" +"Não é possível reatribuir o endereço primário para o dispositivo/VM pai" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" +"Não é possível reatribuir o endereço IP out-of-band para o dispositivo pai" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "Somente endereços IP associados a uma interface podem ser designados como " "IPs primários." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" +"Somente endereços IP atribuídos para uma interface podem ser designados como" +" IP out-of-band para o dispositivo." + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Endereço IP Virtual" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "A atribuição já existe" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "IDs de VLAN" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "VLANs filhas" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9893,33 +9965,33 @@ msgstr "" "Lista separada por vírgula de um ou mais números de portas. Um intervalo " "pode ser especificado usando hífen." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Modelo de Serviço" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Porta(s)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Serviço" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Modelo de serviço" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "Do Modelo" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Personalizado" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10202,6 +10274,14 @@ msgstr "" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Endereço IP duplicado encontrado em {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Não é possível reatribuir o endereço IP enquanto ele estiver designado como " +"o IP primário do objeto pai" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Somente endereços IPv6 podem receber o status SLAAC" @@ -10257,40 +10337,50 @@ msgstr "Não é possível definir scope_type sem scope_id." msgid "Cannot set scope_id without scope_type." msgstr "Não é possível definir scope_id sem scope_type." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "VLAN ID inicial no intervalo {value} não pode ser menor que {minimum}" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "VLAN ID final no intervalo {value} não pode ser maior que {maximum}" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" +"VLAN ID final do intervalo deve ser maior ou igual à VLAN ID inicial " +"({range})" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Os intervalos não podem se sobrepor." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"A VLAN ID máxima do filho deve ser maior ou igual a VLAN ID mínima do filho." -" ({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "O site específico ao qual esta VLAN está associada (se houver)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "Grupo de VLANs (opcional)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "ID numérica da VLAN (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Status operacional desta VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "Função principal desta VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10299,7 +10389,7 @@ msgstr "" "A VLAN está atribuída ao grupo {group} (escopo: {scope}); não pode ser " "associada ao site {site}." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "VLAN ID devem estar nas faixas {ranges} para VLANs no grupo {group}" @@ -10932,7 +11022,7 @@ msgstr "Atribuições dos Contatos" #: netbox/netbox/navigation/menu.py:50 msgid "Rack Roles" -msgstr "Funções de Rack" +msgstr "Funções do Rack" #: netbox/netbox/navigation/menu.py:54 msgid "Elevations" @@ -11065,17 +11155,12 @@ msgstr "Políticas de IPsec" msgid "IPSec Profiles" msgstr "Perfis de IPsec" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Virtualização" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Discos Virtuais" @@ -11237,7 +11322,7 @@ msgstr "Sistema" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11483,19 +11568,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Linha {i}: Objeto com ID {id} não existe" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "Nenhum {object_type} foi/foram selecionado(s)." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Renomeado(s) {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Excluído(s) {count} {object_type}" @@ -11528,7 +11613,7 @@ msgstr "Sincronizado(s) {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} deve implementar get_children ()" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11873,9 +11958,7 @@ msgid "Circuit Type" msgstr "Tipo de circuito" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11886,7 +11969,6 @@ msgstr "Adicionar" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12175,35 +12257,35 @@ msgstr "dias" msgid "Indefinite" msgstr "Indefinido" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Não instalado" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Visão Geral" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Instalar" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Detalhes do Plugin" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Sumário" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Licença" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Histórico da Versão" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Instruções para Instalação Local" @@ -12547,8 +12629,8 @@ msgstr "Adicionar um serviço" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12621,20 +12703,24 @@ msgstr "Configuração" msgid "Context Data" msgstr "Dados do Contexto" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Configuração Renderizada" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Baixar" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Nenhum modelo de configuração encontrado" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "Erro ao renderizar o modelo" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "Nenhum modelo de configuração foi atribuído para este dispositivo." #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12656,7 +12742,6 @@ msgid "Local Config Context Data" msgstr "Dados de Contexto de Configuração Local" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12703,12 +12788,12 @@ msgid "VM Role" msgstr "Função da VM" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Nome do Modelo" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Part Number" @@ -12847,7 +12932,7 @@ msgstr "Endereço MAC" msgid "Wireless Link" msgstr "Link Wireless" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Par" @@ -13471,7 +13556,7 @@ msgstr "Você não tem permissão para executar scripts" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Executar Script" @@ -13484,27 +13569,32 @@ msgstr "Erro ao carregar o script" msgid "Script no longer exists in the source file." msgstr "O script não existe mais no arquivo de origem." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Última Execução" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "O script não está mais presente no arquivo de origem" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Nunca" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Execute Novamente" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "Não foi possível carregar os scripts do módulo %(module)s" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Nenhum Script Encontrado" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13826,7 +13916,7 @@ msgstr "Todas as notificações" msgid "Select" msgstr "Selecionar" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Redefinir" @@ -14310,6 +14400,11 @@ msgstr "Recursos" msgid "Add Virtual Disk" msgstr "Adicionar Disco Virtual" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" +"Nenhum modelo de configuração foi atribuído para esta máquina virtual." + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15384,13 +15479,13 @@ msgid "Memory (MB)" msgstr "Memória (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Disco (GB)" +msgid "Disk (MB)" +msgstr "Disco (MB)" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Tamanho (GB)" +msgid "Size (MB)" +msgstr "Tamanho (MB)" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15573,68 +15668,80 @@ msgstr "disco virtual" msgid "virtual disks" msgstr "discos virtuais" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Adicionado(s) {count} dispositivo(s) para agrupar {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Removido(s) {count} dispositivo(s) do cluster {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPsec - Transporte" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec - Túnel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP-in-IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GRE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "WireGuard" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "OpenVPN" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "L2TP" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "PPTP" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Hub" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "Spoke" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Agressivo" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Principal" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Chaves pré-compartilhadas" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Certificados" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "Assinaturas RSA" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "Assinaturas DSA" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15643,23 +15750,27 @@ msgstr "Assinaturas DSA" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Grupo {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Ethernet Private LAN" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Ethernet Virtual Private LAN" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Ethernet Private Tree" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Árvore privada virtual Ethernet" diff --git a/netbox/translations/ru/LC_MESSAGES/django.mo b/netbox/translations/ru/LC_MESSAGES/django.mo index b1e1f8921..4b62c2a5b 100644 Binary files a/netbox/translations/ru/LC_MESSAGES/django.mo and b/netbox/translations/ru/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/ru/LC_MESSAGES/django.po b/netbox/translations/ru/LC_MESSAGES/django.po index 9eb264f66..2cb2074cd 100644 --- a/netbox/translations/ru/LC_MESSAGES/django.po +++ b/netbox/translations/ru/LC_MESSAGES/django.po @@ -11,17 +11,18 @@ # stavr666, 2024 # Alexander Ryazanov (alryaz) , 2024 # Vladyslav V. Prodan, 2024 -# Artem Kotik, 2024 # Jeremy Stretch, 2024 +# Michail Tatarinov, 2024 +# Artem Kotik, 2025 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2025-01-04 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" -"Last-Translator: Jeremy Stretch, 2024\n" +"Last-Translator: Artem Kotik, 2025\n" "Language-Team: Russian (https://app.transifex.com/netbox-community/teams/178115/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -94,8 +95,8 @@ msgstr "Ваш пароль успешно изменен." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -108,7 +109,7 @@ msgstr "Эксплутация" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -119,8 +120,8 @@ msgid "Active" msgstr "Активный" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Оффлайн" @@ -133,7 +134,7 @@ msgstr "Вывод из эксплуатации" msgid "Decommissioned" msgstr "Списан" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Основной" @@ -157,7 +158,7 @@ msgstr "Неактивный" #: netbox/dcim/filtersets.py:464 netbox/dcim/filtersets.py:1021 #: netbox/dcim/filtersets.py:1368 netbox/dcim/filtersets.py:1903 #: netbox/dcim/filtersets.py:2146 netbox/dcim/filtersets.py:2204 -#: netbox/ipam/filtersets.py:339 netbox/ipam/filtersets.py:959 +#: netbox/ipam/filtersets.py:341 netbox/ipam/filtersets.py:961 #: netbox/virtualization/filtersets.py:45 #: netbox/virtualization/filtersets.py:173 netbox/vpn/filtersets.py:358 msgid "Region (ID)" @@ -169,8 +170,8 @@ msgstr "Регион (ID)" #: netbox/dcim/filtersets.py:471 netbox/dcim/filtersets.py:1028 #: netbox/dcim/filtersets.py:1375 netbox/dcim/filtersets.py:1910 #: netbox/dcim/filtersets.py:2153 netbox/dcim/filtersets.py:2211 -#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:346 -#: netbox/ipam/filtersets.py:966 netbox/virtualization/filtersets.py:52 +#: netbox/extras/filtersets.py:509 netbox/ipam/filtersets.py:348 +#: netbox/ipam/filtersets.py:968 netbox/virtualization/filtersets.py:52 #: netbox/virtualization/filtersets.py:180 netbox/vpn/filtersets.py:353 msgid "Region (slug)" msgstr "Регион (подстрока)" @@ -180,8 +181,8 @@ msgstr "Регион (подстрока)" #: netbox/dcim/filtersets.py:346 netbox/dcim/filtersets.py:477 #: netbox/dcim/filtersets.py:1034 netbox/dcim/filtersets.py:1381 #: netbox/dcim/filtersets.py:1916 netbox/dcim/filtersets.py:2159 -#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:352 -#: netbox/ipam/filtersets.py:972 netbox/virtualization/filtersets.py:58 +#: netbox/dcim/filtersets.py:2217 netbox/ipam/filtersets.py:354 +#: netbox/ipam/filtersets.py:974 netbox/virtualization/filtersets.py:58 #: netbox/virtualization/filtersets.py:186 msgid "Site group (ID)" msgstr "Группа сайтов (ID)" @@ -192,7 +193,7 @@ msgstr "Группа сайтов (ID)" #: netbox/dcim/filtersets.py:1041 netbox/dcim/filtersets.py:1388 #: netbox/dcim/filtersets.py:1923 netbox/dcim/filtersets.py:2166 #: netbox/dcim/filtersets.py:2224 netbox/extras/filtersets.py:515 -#: netbox/ipam/filtersets.py:359 netbox/ipam/filtersets.py:979 +#: netbox/ipam/filtersets.py:361 netbox/ipam/filtersets.py:981 #: netbox/virtualization/filtersets.py:65 #: netbox/virtualization/filtersets.py:193 msgid "Site group (slug)" @@ -206,12 +207,12 @@ msgstr "Группа сайтов (подстрока)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -220,18 +221,17 @@ msgstr "Группа сайтов (подстрока)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -263,8 +263,8 @@ msgstr "Сайт" #: netbox/circuits/filtersets.py:62 netbox/circuits/filtersets.py:229 #: netbox/circuits/filtersets.py:274 netbox/dcim/filtersets.py:242 #: netbox/dcim/filtersets.py:363 netbox/dcim/filtersets.py:458 -#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:238 -#: netbox/ipam/filtersets.py:369 netbox/ipam/filtersets.py:989 +#: netbox/extras/filtersets.py:531 netbox/ipam/filtersets.py:240 +#: netbox/ipam/filtersets.py:371 netbox/ipam/filtersets.py:991 #: netbox/virtualization/filtersets.py:75 #: netbox/virtualization/filtersets.py:203 netbox/vpn/filtersets.py:363 msgid "Site (slug)" @@ -283,13 +283,13 @@ msgstr "ASN" #: netbox/circuits/filtersets.py:95 netbox/circuits/filtersets.py:122 #: netbox/circuits/filtersets.py:156 netbox/circuits/filtersets.py:283 -#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:243 +#: netbox/circuits/filtersets.py:325 netbox/ipam/filtersets.py:245 msgid "Provider (ID)" msgstr "Провайдер (ID)" #: netbox/circuits/filtersets.py:101 netbox/circuits/filtersets.py:128 #: netbox/circuits/filtersets.py:162 netbox/circuits/filtersets.py:289 -#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:249 +#: netbox/circuits/filtersets.py:331 netbox/ipam/filtersets.py:251 msgid "Provider (slug)" msgstr "Провайдер (подстрока)" @@ -318,8 +318,8 @@ msgstr "Тип канала связи (подстрока)" #: netbox/dcim/filtersets.py:452 netbox/dcim/filtersets.py:1045 #: netbox/dcim/filtersets.py:1393 netbox/dcim/filtersets.py:1928 #: netbox/dcim/filtersets.py:2170 netbox/dcim/filtersets.py:2229 -#: netbox/ipam/filtersets.py:232 netbox/ipam/filtersets.py:363 -#: netbox/ipam/filtersets.py:983 netbox/virtualization/filtersets.py:69 +#: netbox/ipam/filtersets.py:234 netbox/ipam/filtersets.py:365 +#: netbox/ipam/filtersets.py:985 netbox/virtualization/filtersets.py:69 #: netbox/virtualization/filtersets.py:197 netbox/vpn/filtersets.py:368 msgid "Site (ID)" msgstr "Сайт (ID)" @@ -339,10 +339,10 @@ msgstr "Точка подключения A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -394,7 +394,7 @@ msgstr "Группа каналов связи (подстрока)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -409,33 +409,33 @@ msgstr "ASN" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -444,7 +444,7 @@ msgstr "ASN" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -459,7 +459,7 @@ msgstr "ASN" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -479,7 +479,7 @@ msgstr "ASN" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -572,10 +572,10 @@ msgid "Service ID" msgstr "Идентификатор Службы" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -596,16 +596,16 @@ msgstr "Цвет" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -660,29 +660,29 @@ msgstr "Аккаунт провайдера" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 #: netbox/dcim/forms/filtersets.py:1059 netbox/dcim/forms/filtersets.py:1170 #: netbox/dcim/tables/devices.py:140 netbox/dcim/tables/devices.py:817 -#: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 +#: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:70 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -693,7 +693,7 @@ msgstr "Аккаунт провайдера" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -729,30 +729,30 @@ msgstr "Статус" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -822,11 +822,11 @@ msgstr "Параметры Службы" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -858,11 +858,11 @@ msgstr "Скорость порта (Кбит/с)" msgid "Upstream speed (Kbps)" msgstr "Скорость восходящего потока (Кбит/с)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Пометить подключенным" @@ -909,10 +909,10 @@ msgstr "Тип канала связи" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -922,13 +922,13 @@ msgstr "Операционный статус" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -953,12 +953,12 @@ msgstr "Сеть провайдера" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -975,9 +975,9 @@ msgstr "Сеть провайдера" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1006,8 +1006,8 @@ msgid "Contacts" msgstr "Контакты" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1015,13 +1015,12 @@ msgstr "Контакты" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1034,16 +1033,16 @@ msgid "Region" msgstr "Регион" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1055,7 +1054,7 @@ msgstr "Группа сайтов" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1094,9 +1093,9 @@ msgstr "Аккаунт" msgid "Term Side" msgstr "Терминология" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1106,11 +1105,11 @@ msgstr "Задание" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:1001 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1182,20 +1181,20 @@ msgid "Unique circuit ID" msgstr "Уникальный ID канала связи" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "статус" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "установлен" @@ -1317,11 +1316,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1332,7 +1331,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1420,7 +1419,7 @@ msgstr "сети провайдера" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1431,7 +1430,7 @@ msgstr "сети провайдера" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1462,7 +1461,7 @@ msgstr "сети провайдера" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1549,7 +1548,7 @@ msgstr "Гарантированная скорость" #: netbox/circuits/tables/providers.py:82 #: netbox/circuits/tables/providers.py:107 netbox/dcim/tables/devices.py:1036 #: netbox/dcim/tables/devicetypes.py:92 netbox/dcim/tables/modules.py:29 -#: netbox/dcim/tables/modules.py:72 netbox/dcim/tables/power.py:39 +#: netbox/dcim/tables/modules.py:73 netbox/dcim/tables/power.py:39 #: netbox/dcim/tables/power.py:96 netbox/dcim/tables/racks.py:84 #: netbox/dcim/tables/racks.py:145 netbox/dcim/tables/racks.py:225 #: netbox/dcim/tables/sites.py:108 netbox/extras/tables/tables.py:582 @@ -1627,7 +1626,7 @@ msgstr "Завершено" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Неисправно" @@ -1694,7 +1693,7 @@ msgid "Cancelled" msgstr "Отменено" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Локальный" @@ -1781,8 +1780,8 @@ msgid "User name" msgstr "Имя пользователя" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1886,7 +1885,7 @@ msgid "Completed before" msgstr "Завершено до" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1952,12 +1951,12 @@ msgstr "Необходимо загрузить файл или выбрать msgid "Rack Elevations" msgstr "Фасады стоек" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" -msgstr "Мощность" +msgstr "Электропитание" #: netbox/core/forms/model_forms.py:159 netbox/netbox/navigation/menu.py:154 #: netbox/templates/core/inc/config_data.html:37 @@ -2056,7 +2055,7 @@ msgstr "" "({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2116,7 +2115,7 @@ msgstr "тип" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2236,60 +2235,60 @@ msgstr "Настраиваемый файл" msgid "managed files" msgstr "Настраиваемые файлы" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "по расписанию" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "интервал" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Интервал повторения (в минутах)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "начало" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "завершено" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "данные" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "ошибка" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "идентификатор задачи" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "задача" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr " задачи" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "Нельзя присвоить задачи этому типу объектов ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "" "Неверный статус для завершения задачи. Возможны следующие варианты: " "{choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "Невозможно вызвать enqueue() со значениями schedule_at и immediate." @@ -2372,7 +2371,7 @@ msgstr "Максимальная версия NetBox" msgid "No plugin data found" msgstr "Данные плагина не найдены" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Автор" @@ -2380,7 +2379,7 @@ msgstr "Автор" msgid "Installed" msgstr "Установлен" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Сертифицирован" @@ -2506,11 +2505,11 @@ msgstr "Задача {id} остановлена." msgid "Failed to stop job {id}" msgstr "Не удалось остановить задачу {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "Не удалось загрузить каталог плагинов" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Плагин {name} не найден" @@ -2530,7 +2529,7 @@ msgid "Staging" msgstr "Подготовка к развертыванию" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Вывод из эксплуатации" @@ -2594,7 +2593,7 @@ msgstr "Выведенный(-ая) из использования" msgid "Millimeters" msgstr "Миллиметры" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "Дюймы" @@ -2608,15 +2607,15 @@ msgstr "Спереди назад" msgid "Rear to front" msgstr "Сзади вперед" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2696,7 +2695,7 @@ msgid "Top to bottom" msgstr "Сверху вниз" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Пассивный" @@ -2725,8 +2724,8 @@ msgid "Proprietary" msgstr "Проприетарный" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Другой" @@ -2739,24 +2738,24 @@ msgstr "ITA/Международный" msgid "Physical" msgstr "Физический" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Виртуальный" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Беспроводной" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Виртуальные интерфейсы" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2765,27 +2764,27 @@ msgstr "Виртуальные интерфейсы" msgid "Bridge" msgstr "Мост" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Группа агрегации линков (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (фиксированный)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (модульный)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (объединительная плата)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Сотовая связь" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2793,130 +2792,130 @@ msgstr "Сотовая связь" msgid "Serial" msgstr "Серийный" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Коаксиальный" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "Стекирование" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Полу" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Полный" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Авто" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Доступ" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Тегированный" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Тегированный (все)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "Стандарт IEEE" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "Пассивный режим 24 В (2 пары)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "Пассивное напряжение 24 В (4 пары)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "Пассивное напряжение 48 В (2 пары)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "Пассивное напряжение 48 В (4 пары)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Медь" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Оптоволоконное" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Волокно" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Подключено" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Километры" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Метры" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Сантиметры" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Мили" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Футы" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Килограммы" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Граммы" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "Фунты" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Унции" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Резервный" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Однофазный" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Трехфазный" @@ -2947,7 +2946,7 @@ msgid "Parent site group (slug)" msgstr "Группа сайтов родителя (подстрока)" #: netbox/dcim/filtersets.py:164 netbox/extras/filtersets.py:364 -#: netbox/ipam/filtersets.py:841 netbox/ipam/filtersets.py:993 +#: netbox/ipam/filtersets.py:843 netbox/ipam/filtersets.py:995 msgid "Group (ID)" msgstr "Группа (ID)" @@ -3005,15 +3004,15 @@ msgstr "Тип стойки (ID)" #: netbox/dcim/filtersets.py:411 netbox/dcim/filtersets.py:892 #: netbox/dcim/filtersets.py:994 netbox/dcim/filtersets.py:1850 -#: netbox/ipam/filtersets.py:381 netbox/ipam/filtersets.py:493 -#: netbox/ipam/filtersets.py:1003 netbox/virtualization/filtersets.py:210 +#: netbox/ipam/filtersets.py:383 netbox/ipam/filtersets.py:495 +#: netbox/ipam/filtersets.py:1005 netbox/virtualization/filtersets.py:210 msgid "Role (ID)" msgstr "Роль (ID)" #: netbox/dcim/filtersets.py:417 netbox/dcim/filtersets.py:898 #: netbox/dcim/filtersets.py:1000 netbox/dcim/filtersets.py:1856 -#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:387 -#: netbox/ipam/filtersets.py:499 netbox/ipam/filtersets.py:1009 +#: netbox/extras/filtersets.py:558 netbox/ipam/filtersets.py:389 +#: netbox/ipam/filtersets.py:501 netbox/ipam/filtersets.py:1011 #: netbox/virtualization/filtersets.py:216 msgid "Role (slug)" msgstr "Роль (подстрока)" @@ -3162,7 +3161,7 @@ msgstr "Кластерная группа (ID)" msgid "Device model (slug)" msgstr "Модель устройства (подстрока)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "Полная глубина" @@ -3211,7 +3210,7 @@ msgstr "VDC (ID)" msgid "Device model" msgstr "модель устройства" -#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:632 +#: netbox/dcim/filtersets.py:1267 netbox/ipam/filtersets.py:634 #: netbox/vpn/filtersets.py:102 netbox/vpn/filtersets.py:401 msgid "Interface (ID)" msgstr "Интерфейс (ID)" @@ -3225,8 +3224,8 @@ msgid "Module bay (ID)" msgstr "Отсек для модулей (ID)" #: netbox/dcim/filtersets.py:1333 netbox/dcim/filtersets.py:1425 -#: netbox/ipam/filtersets.py:611 netbox/ipam/filtersets.py:851 -#: netbox/ipam/filtersets.py:1115 netbox/virtualization/filtersets.py:161 +#: netbox/ipam/filtersets.py:613 netbox/ipam/filtersets.py:853 +#: netbox/ipam/filtersets.py:1117 netbox/virtualization/filtersets.py:161 #: netbox/vpn/filtersets.py:379 msgid "Device (ID)" msgstr "Устройство (ID)" @@ -3235,8 +3234,8 @@ msgstr "Устройство (ID)" msgid "Rack (name)" msgstr "Стойка (имя)" -#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:606 -#: netbox/ipam/filtersets.py:846 netbox/ipam/filtersets.py:1121 +#: netbox/dcim/filtersets.py:1431 netbox/ipam/filtersets.py:608 +#: netbox/ipam/filtersets.py:848 netbox/ipam/filtersets.py:1123 #: netbox/vpn/filtersets.py:374 msgid "Device (name)" msgstr "Устройство (имя)" @@ -3284,21 +3283,21 @@ msgstr "Назначенная VLAN" msgid "Assigned VID" msgstr "Назначенный VID" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 -#: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 -#: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 -#: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:318 +#: netbox/ipam/filtersets.py:329 netbox/ipam/filtersets.py:485 +#: netbox/ipam/filtersets.py:586 netbox/ipam/filtersets.py:597 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3317,19 +3316,19 @@ msgstr "Назначенный VID" msgid "VRF" msgstr "VRF" -#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:322 -#: netbox/ipam/filtersets.py:333 netbox/ipam/filtersets.py:489 -#: netbox/ipam/filtersets.py:590 netbox/ipam/filtersets.py:601 +#: netbox/dcim/filtersets.py:1619 netbox/ipam/filtersets.py:324 +#: netbox/ipam/filtersets.py:335 netbox/ipam/filtersets.py:491 +#: netbox/ipam/filtersets.py:592 netbox/ipam/filtersets.py:603 msgid "VRF (RD)" msgstr "VRF (RD)" -#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1030 +#: netbox/dcim/filtersets.py:1624 netbox/ipam/filtersets.py:1032 #: netbox/vpn/filtersets.py:342 msgid "L2VPN (ID)" msgstr "L2VPN (ID)" #: netbox/dcim/filtersets.py:1630 netbox/dcim/forms/filtersets.py:1433 -#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1036 +#: netbox/dcim/tables/devices.py:570 netbox/ipam/filtersets.py:1038 #: netbox/ipam/forms/filtersets.py:518 netbox/ipam/tables/vlans.py:137 #: netbox/templates/dcim/interface.html:93 netbox/templates/ipam/vlan.html:66 #: netbox/templates/vpn/l2vpntermination.html:12 @@ -3365,7 +3364,7 @@ msgid "LAG interface (ID)" msgstr "Интерфейс LAG (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Виртуальный контекст" @@ -3423,7 +3422,7 @@ msgstr "Нерасторгнутый" #: netbox/dcim/filtersets.py:2239 msgid "Power panel (ID)" -msgstr "Панель питания (ID)" +msgstr "Распределительный щит (ID)" #: netbox/dcim/forms/bulk_create.py:40 netbox/extras/forms/filtersets.py:401 #: netbox/extras/forms/model_forms.py:567 @@ -3439,7 +3438,7 @@ msgstr "Теги" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3456,99 +3455,100 @@ msgstr "" "Поддерживаются алфавитно-цифровые диапазоны. (Должно совпадать с количеством" " создаваемых имен.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Имя контактного лица" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Контактный телефон" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "Контактный адрес электронной почты" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Часовой пояс" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 -#: netbox/dcim/tables/modules.py:20 netbox/dcim/tables/modules.py:60 +#: netbox/dcim/tables/modules.py:20 netbox/dcim/tables/modules.py:61 #: netbox/dcim/tables/racks.py:58 netbox/dcim/tables/racks.py:132 #: netbox/templates/dcim/devicetype.html:14 #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Производитель" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Форм-фактор" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Ширина" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Высота (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Единицы по убыванию" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Наружная ширина" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Внешняя глубина" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Внешний блок" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Глубина крепления" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3559,10 +3559,10 @@ msgstr "Глубина крепления" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3571,61 +3571,61 @@ msgstr "Глубина крепления" msgid "Weight" msgstr "Вес" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Максимальный вес" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Единица веса" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Тип стойки" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Внешние размеры" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Габариты" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Нумерация" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3653,45 +3653,50 @@ msgstr "Нумерация" msgid "Role" msgstr "Роль" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Тип стойки" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Серийный номер" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Инвентарный номер" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Воздушный поток" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3701,64 +3706,64 @@ msgstr "Воздушный поток" msgid "Rack" msgstr "Стойка" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Аппаратное обеспечение" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Платформа по умолчанию" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Номер детали" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "Высота U" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Исключить из использования" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Тип устройства" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 -#: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:66 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Тип модуля" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Шасси" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "Роль виртуальной машины" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3769,19 +3774,19 @@ msgstr "Роль виртуальной машины" msgid "Config template" msgstr "Шаблон конфигурации" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Тип устройства" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Роль устройства" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3795,14 +3800,36 @@ msgstr "Роль устройства" msgid "Platform" msgstr "Платформа" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Кластер" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3812,9 +3839,9 @@ msgstr "Платформа" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3822,11 +3849,11 @@ msgstr "Платформа" #: netbox/dcim/tables/devices.py:697 netbox/dcim/tables/devices.py:754 #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 -#: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/dcim/tables/modules.py:53 netbox/extras/forms/filtersets.py:321 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3853,7 +3880,7 @@ msgstr "Платформа" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3863,23 +3890,28 @@ msgstr "Платформа" msgid "Device" msgstr "Устройство" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Конфигурация" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Виртуализация" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Тип модуля" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3897,109 +3929,109 @@ msgstr "Тип модуля" msgid "Label" msgstr "Лейбл" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Длина" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Единица длины" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Домен" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" -msgstr "Панель питания" +msgstr "Распределительный щит" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Снабжение" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Фаза" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Напряжение" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Сила тока" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Максимальное использование" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Максимальное потребление" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Максимальная потребляемая мощность (Вт)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Выделенная мощность" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Распределенная потребляемая мощность (Вт)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Порт питания" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Фаза электропитания" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Только управление" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "Режим PoE" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "Тип PoE" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Роль беспроводной связи" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4013,17 +4045,17 @@ msgstr "Роль беспроводной связи" msgid "Module" msgstr "Модуль" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "LAG" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Виртуальные контексты" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4032,7 +4064,7 @@ msgstr "Виртуальные контексты" msgid "Speed" msgstr "Скорость" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4046,76 +4078,88 @@ msgstr "Скорость" msgid "Mode" msgstr "Режим" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "Группа VLAN" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "VLAN без тегов" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" -msgstr "VLAN с тегами" +msgstr "Тегированные VLAN-ы" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "Добавить тегированные VLAN-ы" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "Удалить тегированные VLAN-ы" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Беспроводная группа LAN" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "Беспроводные LANы" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Адресация" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Операция" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Связанные интерфейсы" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "Коммутация 802.1Q" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "Добавить/удалить" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "Для назначения VLAN необходимо указать режим интерфейса" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "Интерфейсу доступа нельзя назначать VLAN с тегами." @@ -4141,9 +4185,9 @@ msgstr "Назначенная группа" msgid "available options" msgstr "доступные опции" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4165,15 +4209,15 @@ msgstr "Производитель этого типа стоек" msgid "The lowest-numbered position in the rack" msgstr "Позиция с наименьшим юнитом в стойке" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Ширина от рельса до рельса (в дюймах)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Единица измерения внешних размеров" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Единица измерения веса стойки" @@ -4185,158 +4229,148 @@ msgstr "Имя назначенного арендатора" msgid "Name of assigned role" msgstr "Название назначенной роли" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "Модель типа стойки" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Направление воздушного потока" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "Если не указан тип стойки, необходимо задать ширину." + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "Если не указан тип стойки, необходимо задать высоту в юнитах." + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Родительское место" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Локация стойки (если есть)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Единицы" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Список отдельных номеров объектов, разделенных запятыми" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "Производитель, выпускающий этот тип устройства" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "Платформа по умолчанию для устройств этого типа (опционально)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Вес устройства" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Единица измерения веса устройства" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Вес модуля" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Единица измерения веса модуля" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Ограничьте назначение платформ этим производителем" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Назначенная роль" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Производитель типа устройства" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Модель типа устройства" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Назначенная платформа" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Виртуальное шасси" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Кластер" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Кластер виртуализации" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Назначенная локация (если есть)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Назначенная стойка (если есть)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Лицевая сторона" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Сторона монтажа в стойке" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Родительское устройство (для дочерних устройств)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Отсек для устройств" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" "Отсек для устройств, в котором установлено данное устройство (для детских " "устройств)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "Устройство, в котором установлен данный модуль" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Отсек для модулей" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "Отсек для модулей, в котором установлен данный модуль" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "Тип модуля" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Репликация компонентов" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4344,85 +4378,85 @@ msgstr "" "Автоматическое заполнение компонентов, связанных с этим типом модуля " "(включено по умолчанию)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Принять компоненты" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Используйте уже существующие компоненты" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Тип порта" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Скорость порта в бит/с" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Тип розетки" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Локальный порт питания, питающий эту розетку" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Электрическая фаза (для трехфазных цепей)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Родительский интерфейс" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Мостовой интерфейс" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Lag" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Родительский интерфейс LAG" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "Виртуальные контексты устройств(VDCs)" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "Имена VDC разделены запятыми и заключены в двойные кавычки. Пример:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Физическая среда" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Дуплекс" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "Режим Poe" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Тип Poe" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "Рабочий режим IEEE 802.1Q (для интерфейсов L2)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4430,172 +4464,172 @@ msgstr "Рабочий режим IEEE 802.1Q (для интерфейсов L2) msgid "Assigned VRF" msgstr "Назначенный VRF" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Роль Rf" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Роль беспроводной сети (точка доступа/станция)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "В ПОСТОЯННОГО ТОКА {vdc} не присвоено устройству {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Задний порт" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Соответствующий задний порт" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Классификация физических сред" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Установленное устройство" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "Дочернее устройство, установленное в этом отсеке" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Дочернее устройство не найдено." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Предмет родительского инвентаря" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Тип компонента" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Тип компонента" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Имя компонента" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Имя компонента" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Компонент не найден: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Устройство на стороне А" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Имя устройства" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Сторона типа А" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Тип точки подключения" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Название стороны А" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Название точки подключения" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Устройство на стороне B" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Тип стороны B" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Название стороны B" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Состояние подключения" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "Сторона {side_upper}: {device} {termination_object} уже подключен" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} боковое завершение не найдено: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Мастер" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Мастер-устройство" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Имя родительского сайта" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" -msgstr "Панель питания в восходящем направлении" +msgstr "Распределительный щит" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Основное или резервное" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Тип питания (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Однофазный или трехфазный" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "Основной IPv4" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "Адрес IPv4 с маской, напр. 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "Основной IPv6" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "Адрес IPv6 с длиной префикса, напр. 2001:db8::1/64" @@ -4651,13 +4685,13 @@ msgstr "A {model} названный {name} уже существует" #: netbox/templates/dcim/powerpanel.html:19 #: netbox/templates/dcim/trace/powerpanel.html:4 msgid "Power Panel" -msgstr "Панель питания" +msgstr "Распределительный щит" #: netbox/dcim/forms/connections.py:58 netbox/dcim/forms/model_forms.py:765 #: netbox/templates/dcim/powerfeed.html:21 #: netbox/templates/dcim/powerport.html:80 msgid "Power Feed" -msgstr "Подача питания" +msgstr "Кабель питания" #: netbox/dcim/forms/connections.py:81 msgid "Side" @@ -4684,10 +4718,6 @@ msgstr "Родительская группа" msgid "Facility" msgstr "Объект" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Тип стойки" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Функция" @@ -4724,7 +4754,7 @@ msgid "Has virtual device contexts" msgstr "Имеет контексты виртуальных устройств" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Кластерная группа" @@ -4763,7 +4793,7 @@ msgstr "Вид" msgid "Mgmt only" msgstr "Только менеджмент" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4867,36 +4897,50 @@ msgstr "Автоматическое заполнение компонентов msgid "Characteristics" msgstr "Характеристики" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" +"Для массового создания поддерживаются алфавитно-цифровые диапазоны. " +"Смешанные имена и номера в одном диапазоне не поддерживаются (например: " +"[ge, xe]-0/0/[0-9]). Переменная {module} будет " +"автоматически заменена значением позиции при создании нового модуля." + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Шаблон консольного порта" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Шаблон порта консольного сервера" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Шаблон переднего порта" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Шаблон интерфейса" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Шаблон розетки питания" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Шаблон порта питания" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Шаблон заднего порта" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4920,7 +4964,7 @@ msgstr "Шаблон заднего порта" msgid "Interface" msgstr "Интерфейс" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4928,14 +4972,14 @@ msgstr "Интерфейс" msgid "Console Port" msgstr "Консольный порт" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Порт консольного сервера" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4946,7 +4990,7 @@ msgstr "Порт консольного сервера" msgid "Front Port" msgstr "Передний порт" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4959,40 +5003,40 @@ msgstr "Передний порт" msgid "Rear Port" msgstr "Задний порт" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Порт питания" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Розетка питания" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Назначение компонентов" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "Инвентарный номер можно присвоить только одному компоненту." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "Интерфейс LAG" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Фильтровать доступные к назначению VLAN-ы по группе." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Дочернее устройство" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -5000,35 +5044,35 @@ msgstr "" "Сначала необходимо создать дочерние устройства и назначить их сайту и стойке" " родительского устройства." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Консольный порт" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Порт консольного сервера" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Передний порт" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "Розетка питания" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Комплектующие" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Роли комплектующих" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5046,12 +5090,12 @@ msgstr "" " ожидаются." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Задние порты" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" "Выберите одно назначение заднего порта для каждого создаваемого переднего " @@ -5067,16 +5111,7 @@ msgstr "" "должно соответствовать выбранному количеству положений задних портов " "({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"Строка {module} будет заменено позицией назначенного модуля, " -"если таковая имеется." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5086,18 +5121,18 @@ msgstr "" "соответствовать выбранному количеству положений задних портов " "({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Участники" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Исходное положение" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." @@ -5105,7 +5140,7 @@ msgstr "" "Положение первого элементного устройства. Увеличивается на единицу за каждый" " дополнительный элемент." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "Должность должна быть указана для первого члена VC." @@ -5599,7 +5634,7 @@ msgstr "VLAN без тегов" #: netbox/dcim/models/device_components.py:703 #: netbox/virtualization/models/virtualmachines.py:341 msgid "tagged VLANs" -msgstr "VLAN без тегов" +msgstr "тегированные VLAN" #: netbox/dcim/models/device_components.py:745 #: netbox/virtualization/models/virtualmachines.py:377 @@ -6046,12 +6081,12 @@ msgstr "положение (U)" msgid "rack face" msgstr "лицевая сторона стойки" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "основной IPv4" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "основной IPv6" @@ -6224,21 +6259,21 @@ msgstr "" "Модуль должен быть установлен в модульном отсеке, принадлежащем назначенному" " устройству ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "Домен" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "виртуальное шасси" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "Выбранный мастер ({master}) не назначено этому виртуальному шасси." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6247,34 +6282,34 @@ msgstr "" "Невозможно удалить виртуальное шасси {self}. Существуют интерфейсы-члены, " "которые образуют межкорпусные интерфейсы LAG." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "идентификатор" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Цифровой идентификатор, уникальный для родительского устройства" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "комментарии" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "виртуальный контекст" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "виртуальные контексты" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} не является IPV{family} адрес." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" "Основной IP-адрес должен принадлежать интерфейсу на назначенном устройстве." @@ -6295,11 +6330,11 @@ msgstr "При установке веса необходимо указать #: netbox/dcim/models/power.py:55 msgid "power panel" -msgstr "панель питания" +msgstr "распределительный щит" #: netbox/dcim/models/power.py:56 msgid "power panels" -msgstr "панели питания" +msgstr "распределительный щиты" #: netbox/dcim/models/power.py:70 #, python-brace-format @@ -6339,11 +6374,11 @@ msgstr "доступная мощность" #: netbox/dcim/models/power.py:164 msgid "power feed" -msgstr "подача питания" +msgstr "Кабель питания" #: netbox/dcim/models/power.py:165 msgid "power feeds" -msgstr "источники питания" +msgstr "кабели питания" #: netbox/dcim/models/power.py:179 #, python-brace-format @@ -6351,7 +6386,7 @@ msgid "" "Rack {rack} ({rack_site}) and power panel {powerpanel} ({powerpanel_site}) " "are in different sites." msgstr "" -"Стойка {rack} ({rack_site}) и панель питания {powerpanel} " +"Стойка {rack} ({rack_site}) и распределительный щит {powerpanel} " "({powerpanel_site}) расположены на разных сайтах." #: netbox/dcim/models/power.py:190 @@ -6466,7 +6501,7 @@ msgstr "Локально назначенный идентификатор" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Функциональная роль" @@ -6677,7 +6712,7 @@ msgstr "Доступен" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Устройства" @@ -6706,8 +6741,8 @@ msgid "Site Group" msgstr "Группа сайтов" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6758,20 +6793,20 @@ msgid "Power outlets" msgstr "Розетки питания" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Интерфейсы" @@ -6791,14 +6826,14 @@ msgstr "Отсеки для модулей" msgid "Inventory items" msgstr "Комплектующие" -#: netbox/dcim/tables/devices.py:305 netbox/dcim/tables/modules.py:56 +#: netbox/dcim/tables/devices.py:305 netbox/dcim/tables/modules.py:57 #: netbox/templates/dcim/modulebay.html:17 msgid "Module Bay" msgstr "Модульный отсек" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6827,7 +6862,7 @@ msgstr "Максимальная потребляемая мощность (Вт msgid "Allocated draw (W)" msgstr "Выделенная мощность (Вт)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6923,94 +6958,94 @@ msgstr "Высота U" msgid "Instances" msgstr "Инстансы" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Порты консоли" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Порты консольного сервера" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Порты питания" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Розетки питания" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Фронтальные порты" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Задние порты" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Отсеки для устройств" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Отсеки для модулей" #: netbox/dcim/tables/power.py:36 netbox/netbox/navigation/menu.py:297 #: netbox/templates/dcim/powerpanel.html:51 msgid "Power Feeds" -msgstr "Источники питания" +msgstr "Кабели питания" #: netbox/dcim/tables/power.py:80 netbox/templates/dcim/powerfeed.html:99 msgid "Max Utilization" @@ -7052,7 +7087,7 @@ msgstr "Пространство" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7063,28 +7098,28 @@ msgid "Test case must set peer_termination_type" msgstr "" "В тестовом примере должно быть установлено значение peer_termination_type" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Отключен {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Резервирование" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Устройства без стоек" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Контекст конфигурации" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Конфигурация рендера" @@ -7095,35 +7130,35 @@ msgstr "Во время рендеринга шаблона произошла #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Виртуальные машины" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Установлено устройство {device} в отсек {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Удалено устройство {device} из отсека {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Потомки" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Добавлен участник {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "Невозможно удалить главное устройство {device} из виртуального шасси." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "{device} удалено из виртуального шасси {chassis}" @@ -7306,7 +7341,6 @@ msgstr "Обновить" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -7521,12 +7555,12 @@ msgstr "Закладки" msgid "Show your personal bookmarks" msgstr "Покажите свои личные закладки" -#: netbox/extras/events.py:147 +#: netbox/extras/events.py:151 #, python-brace-format msgid "Unknown action type for an event rule: {action_type}" msgstr "Неизвестный тип действия для правила события: {action_type}" -#: netbox/extras/events.py:192 +#: netbox/extras/events.py:196 #, python-brace-format msgid "Cannot import events pipeline {name} error: {error}" msgstr "Невозможно импортировать конвейер событий {name} ошибка: {error}" @@ -8140,19 +8174,19 @@ msgstr "Запланируйте выполнение скрипта на зад msgid "Interval at which this script is re-run (in minutes)" msgstr "Интервал повторного запуска этого скрипта (в минутах)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "Изменения в базе данных были автоматически отменены." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Скрипт прерван с ошибкой: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Возникло исключение: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "Изменения в базе данных отменены из-за ошибки." @@ -9181,7 +9215,7 @@ msgstr "Удален виджет: " msgid "Error deleting widget: " msgstr "Ошибка при удалении виджета: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "Невозможно запустить скрипт: процесс RQ не запущен." @@ -9297,129 +9331,129 @@ msgstr "Экспорт L2VPN" msgid "Exporting L2VPN (identifier)" msgstr "Экспорт L2VPN (идентификатор)" -#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:281 +#: netbox/ipam/filtersets.py:155 netbox/ipam/filtersets.py:283 #: netbox/ipam/forms/model_forms.py:229 netbox/ipam/tables/ip.py:212 #: netbox/templates/ipam/prefix.html:12 msgid "Prefix" msgstr "Префикс" #: netbox/ipam/filtersets.py:159 netbox/ipam/filtersets.py:198 -#: netbox/ipam/filtersets.py:221 +#: netbox/ipam/filtersets.py:223 msgid "RIR (ID)" msgstr "RIR (ID)" #: netbox/ipam/filtersets.py:165 netbox/ipam/filtersets.py:204 -#: netbox/ipam/filtersets.py:227 +#: netbox/ipam/filtersets.py:229 msgid "RIR (slug)" msgstr "RIR (подстрока)" -#: netbox/ipam/filtersets.py:285 +#: netbox/ipam/filtersets.py:287 msgid "Within prefix" msgstr "В префиксе" -#: netbox/ipam/filtersets.py:289 +#: netbox/ipam/filtersets.py:291 msgid "Within and including prefix" msgstr "В префиксе и включительно" -#: netbox/ipam/filtersets.py:293 +#: netbox/ipam/filtersets.py:295 msgid "Prefixes which contain this prefix or IP" msgstr "Префиксы, содержащие этот префикс или IP-адрес" -#: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/filtersets.py:306 netbox/ipam/filtersets.py:574 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Длина маски" -#: netbox/ipam/filtersets.py:373 netbox/vpn/filtersets.py:427 +#: netbox/ipam/filtersets.py:375 netbox/vpn/filtersets.py:427 msgid "VLAN (ID)" msgstr "VLAN (ID)" -#: netbox/ipam/filtersets.py:377 netbox/vpn/filtersets.py:422 +#: netbox/ipam/filtersets.py:379 netbox/vpn/filtersets.py:422 msgid "VLAN number (1-4094)" msgstr "Номер VLAN (1-4094)" -#: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:473 netbox/ipam/filtersets.py:477 +#: netbox/ipam/filtersets.py:569 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" msgstr "Адрес" -#: netbox/ipam/filtersets.py:479 +#: netbox/ipam/filtersets.py:481 msgid "Ranges which contain this prefix or IP" msgstr "Диапазоны, содержащие этот префикс или IP-адрес" -#: netbox/ipam/filtersets.py:507 netbox/ipam/filtersets.py:563 +#: netbox/ipam/filtersets.py:509 netbox/ipam/filtersets.py:565 msgid "Parent prefix" msgstr "Родительский префикс" -#: netbox/ipam/filtersets.py:616 netbox/ipam/filtersets.py:856 -#: netbox/ipam/filtersets.py:1131 netbox/vpn/filtersets.py:385 +#: netbox/ipam/filtersets.py:618 netbox/ipam/filtersets.py:858 +#: netbox/ipam/filtersets.py:1133 netbox/vpn/filtersets.py:385 msgid "Virtual machine (name)" msgstr "Виртуальная машина (имя)" -#: netbox/ipam/filtersets.py:621 netbox/ipam/filtersets.py:861 -#: netbox/ipam/filtersets.py:1125 netbox/virtualization/filtersets.py:282 +#: netbox/ipam/filtersets.py:623 netbox/ipam/filtersets.py:863 +#: netbox/ipam/filtersets.py:1127 netbox/virtualization/filtersets.py:282 #: netbox/virtualization/filtersets.py:321 netbox/vpn/filtersets.py:390 msgid "Virtual machine (ID)" msgstr "Виртуальная машина (ID)" -#: netbox/ipam/filtersets.py:627 netbox/vpn/filtersets.py:97 +#: netbox/ipam/filtersets.py:629 netbox/vpn/filtersets.py:97 #: netbox/vpn/filtersets.py:396 msgid "Interface (name)" msgstr "Интерфейс (имя)" -#: netbox/ipam/filtersets.py:638 netbox/vpn/filtersets.py:108 +#: netbox/ipam/filtersets.py:640 netbox/vpn/filtersets.py:108 #: netbox/vpn/filtersets.py:407 msgid "VM interface (name)" msgstr "Интерфейс виртуальной машины (имя)" -#: netbox/ipam/filtersets.py:643 netbox/vpn/filtersets.py:113 +#: netbox/ipam/filtersets.py:645 netbox/vpn/filtersets.py:113 msgid "VM interface (ID)" msgstr "Интерфейс виртуальной машины (ID)" -#: netbox/ipam/filtersets.py:648 +#: netbox/ipam/filtersets.py:650 msgid "FHRP group (ID)" msgstr "FHRP группа (ID)" -#: netbox/ipam/filtersets.py:652 +#: netbox/ipam/filtersets.py:654 msgid "Is assigned to an interface" msgstr "Присвоен интерфейсу" -#: netbox/ipam/filtersets.py:656 +#: netbox/ipam/filtersets.py:658 msgid "Is assigned" msgstr "Назначено" -#: netbox/ipam/filtersets.py:668 +#: netbox/ipam/filtersets.py:670 msgid "Service (ID)" msgstr "Сервис (ID)" -#: netbox/ipam/filtersets.py:673 +#: netbox/ipam/filtersets.py:675 msgid "NAT inside IP address (ID)" msgstr "Внутренний NAT IP-адрес (ID)" -#: netbox/ipam/filtersets.py:1041 netbox/ipam/forms/bulk_import.py:322 +#: netbox/ipam/filtersets.py:1043 netbox/ipam/forms/bulk_import.py:322 msgid "Assigned interface" msgstr "Назначенный интерфейс" -#: netbox/ipam/filtersets.py:1046 +#: netbox/ipam/filtersets.py:1048 msgid "Assigned VM interface" msgstr "Назначенный интерфейс виртуальной машины" -#: netbox/ipam/filtersets.py:1136 +#: netbox/ipam/filtersets.py:1138 msgid "IP address (ID)" msgstr "IP-адрес (ID)" -#: netbox/ipam/filtersets.py:1142 netbox/ipam/models/ip.py:788 +#: netbox/ipam/filtersets.py:1144 netbox/ipam/models/ip.py:788 msgid "IP address" msgstr "IP-адрес" -#: netbox/ipam/filtersets.py:1167 +#: netbox/ipam/filtersets.py:1169 msgid "Primary IPv4 (ID)" msgstr "Основной IPv4 (ID)" -#: netbox/ipam/filtersets.py:1172 +#: netbox/ipam/filtersets.py:1174 msgid "Primary IPv6 (ID)" msgstr "Основной IPv6 (ID)" @@ -9452,16 +9486,16 @@ msgstr "Требуется маска CIDR (например, /24)." msgid "Address pattern" msgstr "Шаблон адреса" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Обеспечить уникальное пространство" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "Является приватным" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9475,20 +9509,20 @@ msgstr "Является приватным" msgid "RIR" msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Дата добавления" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "VLAN группа" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9501,32 +9535,32 @@ msgstr "VLAN группа" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Длина префикса" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "Является пулом" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Считать полностью использованным" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "Назначение VLAN" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "DNS-имя" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9534,12 +9568,12 @@ msgstr "DNS-имя" msgid "Protocol" msgstr "Протокол" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "Идентификатор группы" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9551,12 +9585,12 @@ msgstr "Идентификатор группы" msgid "Authentication type" msgstr "Тип аутентификации" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Ключ аутентификации" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9568,26 +9602,26 @@ msgstr "Ключ аутентификации" msgid "Authentication" msgstr "Аутентификация" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Тип прицела" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "Диапазоны идентификаторов VLAN" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Область применения" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "Диапазоны идентификаторов VLAN" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Сайт и группа" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9614,8 +9648,8 @@ msgstr "Группа VLAN (если есть)" msgid "Parent device of assigned interface (if any)" msgstr "Родительское устройство назначенного интерфейса (если есть)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9641,42 +9675,62 @@ msgstr "Является основным" msgid "Make this the primary IP for the assigned device" msgstr "Сделайте этот IP-адрес основным для назначенного устройства" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "Внеполосный IP-адрес" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "Назначьте это как внеполосный IP-адрес для указанного устройства" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "Не указано устройство или виртуальная машина; невозможно установить в " "качестве основного IP-адреса" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "Устройство не указано; невозможно установить как внеполосный IP-адрес" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "Невозможно установить внеполосный IP-адрес для виртуальных машин" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "" "Интерфейс не указан; невозможно установить в качестве основного IP-адреса" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "Интерфейс не указан; невозможно установить как внеполосный IP-адрес" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Тип авторизации" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Тип прицела (приложение и модель)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Назначенная VLAN группа" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "протокол IP" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Требуется, если не назначено виртуальной машине" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Требуется, если не назначено устройству" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} не назначено этому устройству/виртуальной машине." @@ -9758,24 +9812,24 @@ msgstr "Назначено интерфейсу" msgid "DNS Name" msgstr "DNS-имя" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 msgid "VLANs" -msgstr "VLAN" +msgstr "VLAN-ы" #: netbox/ipam/forms/filtersets.py:457 msgid "Contains VLAN ID" msgstr "Содержит идентификатор VLAN" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "VLAN ID" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9786,7 +9840,7 @@ msgstr "VLAN ID" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9815,8 +9869,8 @@ msgstr "Назначение сайта/VLAN" msgid "IP Range" msgstr "Диапазон IP-адресов" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "Группа компаний FHRP" @@ -9825,47 +9879,62 @@ msgstr "Группа компаний FHRP" msgid "Make this the primary IP for the device/VM" msgstr "Сделайте этот IP-адрес основным для устройства/виртуальной машины" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "Назначить внеполосным IP-адресом устройства" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "IP-адрес NAT (внутренний)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "IP-адрес можно присвоить только одному объекту." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Невозможно переназначить IP-адрес, если он назначен основным IP-адресом " -"родительского объекта" +"Невозможно переназначить основной IP-адрес родительского " +"устройства/виртуальной машины" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" +"Невозможно переназначить внеполосный IP-адрес родительскому устройству" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "В качестве основных IP-адресов можно назначить только IP-адреса, назначенные" " интерфейсу." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" +"В качестве внеполосного IP-адреса устройства можно указать только IP-адреса," +" назначенные интерфейсу устройства." + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Виртуальный IP-адрес" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "Задание уже существует" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "Идентификаторы VLAN" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "Дочерние VLAN" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9873,33 +9942,33 @@ msgstr "" "Список одного или нескольких номеров портов, разделенных запятыми. Диапазон " "можно указать с помощью дефиса." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Шаблон Службы" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Порт(ы)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Служба" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Шаблон службы" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "Из шаблона" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Настраиваемый" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10183,6 +10252,14 @@ msgstr "" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Дубликат IP-адреса обнаружен в {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Невозможно переназначить IP-адрес, если он назначен основным IP-адресом " +"родительского объекта" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Только адресам IPv6 можно присвоить статус SLAAC" @@ -10233,40 +10310,54 @@ msgstr "Невозможно установить scope_type без scope_id." msgid "Cannot set scope_id without scope_type." msgstr "Невозможно установить scope_id без scope_type." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" +"Начальный идентификатор VLAN в диапазоне ({value}) не может быть меньше " +"{minimum}" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" +"Последний идентификатор VLAN в диапазоне ({value}) не может превышать " +"{maximum}" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" +"Последний идентификатор VLAN в диапазоне должен быть больше или равен " +"начальному идентификатору VLAN ({range})" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Диапазоны не могут перекрываться." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"Максимальное количество детских VID должно быть больше или равно " -"минимальному детскому VID ({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "Конкретный сайт, которому назначена эта VLAN (если есть)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "Группа VLAN (опционально)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "Цифровой VLAN ID (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Рабочее состояние этой VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "Основная функция этой VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10275,7 +10366,7 @@ msgstr "" "VLAN назначена группе {group} (область применения: {scope}); также не может " "быть присвоено сайту {site}." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "" @@ -11045,17 +11136,12 @@ msgstr "Политики IPsec" msgid "IPSec Profiles" msgstr "Профили IPsec" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Виртуализация" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Виртуальные диски" @@ -11099,7 +11185,7 @@ msgstr "Сети провайдеров" #: netbox/netbox/navigation/menu.py:298 msgid "Power Panels" -msgstr "Панели питания" +msgstr "Распределительный щиты" #: netbox/netbox/navigation/menu.py:309 msgid "Configurations" @@ -11217,7 +11303,7 @@ msgstr "система" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11466,19 +11552,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Ряд {i}: Объект с идентификатором {id} не существует" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "{object_type} не были выбраны." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Переименован(-о) {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Удален(-о) {count} {object_type}" @@ -11510,7 +11596,7 @@ msgstr "Синхронизирован(-о) {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} должен реализовать get_children ()" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11855,9 +11941,7 @@ msgid "Circuit Type" msgstr "Тип канала связи" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11868,7 +11952,6 @@ msgstr "Добавить" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12042,7 +12125,7 @@ msgstr "Ширина юнита по умолчанию" #: netbox/templates/core/inc/config_data.html:20 msgid "Power feeds" -msgstr "Источники питания" +msgstr "Кабели питания" #: netbox/templates/core/inc/config_data.html:23 msgid "Default voltage" @@ -12158,35 +12241,35 @@ msgstr "дни" msgid "Indefinite" msgstr "Бессрочно" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Не установлено" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Обзор" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Установить" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Сведения о плагине" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Резюме" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Лицензия" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "История версий" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Инструкции по локальной установке" @@ -12530,8 +12613,8 @@ msgstr "Добавить службу" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12604,20 +12687,24 @@ msgstr "Конфигурация" msgid "Context Data" msgstr "Контекстные данные" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Отображенная конфигурация" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Скачать" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Шаблон конфигурации не найден" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "Ошибка при отображении шаблона" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "Для этого устройства не назначен шаблон конфигурации." #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12639,7 +12726,6 @@ msgid "Local Config Context Data" msgstr "Контекстные данные локальной конфигурации" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12686,12 +12772,12 @@ msgid "VM Role" msgstr "Роль виртуальной машины" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Название модели" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Номер детали" @@ -12772,7 +12858,7 @@ msgstr "Без тегов" #: netbox/templates/dcim/inc/interface_vlans_table.html:37 msgid "No VLANs Assigned" -msgstr "VLAN не назначены" +msgstr "VLAN-ы не назначены" #: netbox/templates/dcim/inc/interface_vlans_table.html:44 #: netbox/templates/ipam/prefix_list.html:16 @@ -12830,7 +12916,7 @@ msgstr "MAC-адрес" msgid "Wireless Link" msgstr "Беспроводная связь" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Peer" @@ -12943,7 +13029,7 @@ msgstr "Фаза электропитания" #: netbox/templates/dcim/powerpanel.html:72 msgid "Add Power Feeds" -msgstr "Добавить каналы питания" +msgstr "Добавить кабели питания" #: netbox/templates/dcim/powerport.html:44 msgid "Maximum Draw" @@ -13453,7 +13539,7 @@ msgstr "У вас нет разрешения на запуск скриптов #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Запустить скрипт" @@ -13466,27 +13552,32 @@ msgstr "Ошибка при загрузке скрипта" msgid "Script no longer exists in the source file." msgstr "Скрипт больше не существует в исходном файле." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Последний запуск" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "Скрипт больше не присутствует в исходном файле" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Никогда" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Повторить" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "Не удалось загрузить скрипты из модуля %(module)s" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Скрипты не найдены" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13809,7 +13900,7 @@ msgstr "Все уведомления" msgid "Select" msgstr "Выберите" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Сбросить" @@ -14292,6 +14383,10 @@ msgstr "Ресурсы" msgid "Add Virtual Disk" msgstr "Добавить виртуальный диск" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "Для этой виртуальной машины не назначен шаблон конфигурации." + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15368,13 +15463,13 @@ msgid "Memory (MB)" msgstr "Память (МБ)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Диск (ГБ)" +msgid "Disk (MB)" +msgstr "Диск (МБ)" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Размер (ГБ)" +msgid "Size (MB)" +msgstr "Размер (МБ)" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15557,68 +15652,80 @@ msgstr "виртуальный диск" msgid "virtual disks" msgstr "виртуальные диски" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Добавлено {count} устройств(-а) для кластеризации {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Удалено {count} устройств(-а) из кластера {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPsec — транспорт" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec — туннель" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP-адрес в IP-адресе" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GRE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "WireGuard" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "OpenVPN" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "L2TP" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "PPTP" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Hub" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "Spoke" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Агрессивный" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Главная" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "PSK" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Сертификаты" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "Подписи RSA" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "Подписи DSA" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15627,23 +15734,27 @@ msgstr "Подписи DSA" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Группа {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Частная локальная сеть Ethernet" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Виртуальная частная локальная сеть Ethernet" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Частное дерево Ethernet" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Виртуальное частное дерево Ethernet" diff --git a/netbox/translations/tr/LC_MESSAGES/django.mo b/netbox/translations/tr/LC_MESSAGES/django.mo index 9117323f5..0455483e3 100644 Binary files a/netbox/translations/tr/LC_MESSAGES/django.mo and b/netbox/translations/tr/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/tr/LC_MESSAGES/django.po b/netbox/translations/tr/LC_MESSAGES/django.po index 34544341e..18fd06563 100644 --- a/netbox/translations/tr/LC_MESSAGES/django.po +++ b/netbox/translations/tr/LC_MESSAGES/django.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" "Last-Translator: Jeremy Stretch, 2024\n" "Language-Team: Turkish (https://app.transifex.com/netbox-community/teams/178115/tr/)\n" @@ -90,8 +90,8 @@ msgstr "Şifreniz başarıyla değiştirildi." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -104,7 +104,7 @@ msgstr "Tedarik" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -115,8 +115,8 @@ msgid "Active" msgstr "Aktif" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Çevrim dışı" @@ -129,7 +129,7 @@ msgstr "Hazırlıktan Kaldırma" msgid "Decommissioned" msgstr "Hizmet dışı bırakıldı" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Birincil" @@ -202,12 +202,12 @@ msgstr "Site grubu (kısa ad)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -216,18 +216,17 @@ msgstr "Site grubu (kısa ad)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -335,10 +334,10 @@ msgstr "Fesih A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -390,7 +389,7 @@ msgstr "Devre grubu (sümüklü böcek)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -405,33 +404,33 @@ msgstr "ASN'ler" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -440,7 +439,7 @@ msgstr "ASN'ler" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -455,7 +454,7 @@ msgstr "ASN'ler" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -475,7 +474,7 @@ msgstr "ASN'ler" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -568,10 +567,10 @@ msgid "Service ID" msgstr "Servis ID" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -592,16 +591,16 @@ msgstr "Renk" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -656,14 +655,14 @@ msgstr "Sağlayıcı hesabı" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -672,13 +671,13 @@ msgstr "Sağlayıcı hesabı" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -689,7 +688,7 @@ msgstr "Sağlayıcı hesabı" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -725,30 +724,30 @@ msgstr "Durum" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -818,11 +817,11 @@ msgstr "Servis Parametreleri" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -854,11 +853,11 @@ msgstr "Bağlantı noktası hızı (Kbps)" msgid "Upstream speed (Kbps)" msgstr "Yukarı akış hızı (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "Bağlı olarak işaretle" @@ -905,10 +904,10 @@ msgstr "Devre tipi" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -918,13 +917,13 @@ msgstr "Operasyonel durum" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -949,12 +948,12 @@ msgstr "Sağlayıcı ağı" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -971,9 +970,9 @@ msgstr "Sağlayıcı ağı" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1002,8 +1001,8 @@ msgid "Contacts" msgstr "İletişim" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1011,13 +1010,12 @@ msgstr "İletişim" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1030,16 +1028,16 @@ msgid "Region" msgstr "Bölge" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1051,7 +1049,7 @@ msgstr "Site grubu" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1090,9 +1088,9 @@ msgstr "Hesap" msgid "Term Side" msgstr "Dönem Tarafı" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1102,11 +1100,11 @@ msgstr "Ödev" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1178,20 +1176,20 @@ msgid "Unique circuit ID" msgstr "Benzersiz devre ID" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "durum" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "kurulmuş" @@ -1310,11 +1308,11 @@ msgstr "Devre sonlandırma hem siteye hem de sağlayıcı ağına bağlanamaz." #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1325,7 +1323,7 @@ msgstr "Devre sonlandırma hem siteye hem de sağlayıcı ağına bağlanamaz." #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1413,7 +1411,7 @@ msgstr "sağlayıcı ağları" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1424,7 +1422,7 @@ msgstr "sağlayıcı ağları" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1455,7 +1453,7 @@ msgstr "sağlayıcı ağları" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1619,7 +1617,7 @@ msgstr "Tamamlandı" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Başarısız" @@ -1686,7 +1684,7 @@ msgid "Cancelled" msgstr "İptal Edildi" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Yerel" @@ -1773,8 +1771,8 @@ msgid "User name" msgstr "Kullanıcı adı" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1878,7 +1876,7 @@ msgid "Completed before" msgstr "Daha önce tamamlandı" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1945,9 +1943,9 @@ msgstr "" msgid "Rack Elevations" msgstr "Raf Yükseltmeleri" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Güç" @@ -2047,7 +2045,7 @@ msgid "Change logging is not supported for this object type ({type})." msgstr "Değişiklik günlüğü bu nesne türü için desteklenmez ({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2107,7 +2105,7 @@ msgstr "türü" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2227,59 +2225,59 @@ msgstr "yönetilen dosya" msgid "managed files" msgstr "yönetilen dosyalar" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "planlanmış" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "aralık" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Tekrarlama aralığı (dakika cinsinden)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "başladı" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "tamamlandı" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "veri" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "hata" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "görev ID" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "görev" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "görevler" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "İşler bu nesne türüne atanamaz ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "" "İşin sonlandırılması için geçersiz durum. Seçenekler şunlardır: {choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "enqueue () hem schedule_at hem de imediat değerleriyle çağrılamaz." @@ -2362,7 +2360,7 @@ msgstr "Maksimum NetBox Sürümü" msgid "No plugin data found" msgstr "Eklenti verisi bulunamadı" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Yazar" @@ -2370,7 +2368,7 @@ msgstr "Yazar" msgid "Installed" msgstr "Kurulmuş" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Sertifikalı" @@ -2496,11 +2494,11 @@ msgstr "İş {id} durduruldu." msgid "Failed to stop job {id}" msgstr "İş durdurulamadı {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "Eklentiler kataloğu yüklenemedi" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Eklenti {name} bulunamadı" @@ -2520,7 +2518,7 @@ msgid "Staging" msgstr "Sahneleme" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Hizmetten çıkarma" @@ -2584,7 +2582,7 @@ msgstr "Kullanımdan kaldırıldı" msgid "Millimeters" msgstr "Milimetre" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "İnç" @@ -2598,15 +2596,15 @@ msgstr "Önden arkaya" msgid "Rear to front" msgstr "Arkadan öne" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2686,7 +2684,7 @@ msgid "Top to bottom" msgstr "Yukarıdan aşağıya" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Pasif" @@ -2715,8 +2713,8 @@ msgid "Proprietary" msgstr "Tescilli" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Diğer" @@ -2729,24 +2727,24 @@ msgstr "ITA/Uluslararası" msgid "Physical" msgstr "Fiziksel" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Sanal" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Kablosuz" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Sanal arayüzler" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2755,27 +2753,27 @@ msgstr "Sanal arayüzler" msgid "Bridge" msgstr "Köprü" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Bağlantı Toplama Grubu (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (sabit)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (modüler)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (arka panel)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Hücresel" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2783,130 +2781,130 @@ msgstr "Hücresel" msgid "Serial" msgstr "Seri" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Koaksiyel" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "İstifleme" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Yarım" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Dolu" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Oto" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Erişim" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Etiketlenmiş" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Etiketlenmiş (Tümü)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "IEEE Standardı" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "Pasif 24V (2 çift)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "Pasif 24V (4 çift)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "Pasif 48V (2 çift)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "Pasif 48V (4 çift)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Bakır" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Fiber Optik" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Fiber" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Bağlı" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Kilometre" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Sayaçlar" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Santimetre" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Mil" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Feet" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Kilogram" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Gramlar" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "Pound'lar" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "ons" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Yedekli" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Tek fazlı" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Üç fazlı" @@ -3152,7 +3150,7 @@ msgstr "Küme grubu (ID)" msgid "Device model (slug)" msgstr "Cihaz modeli (kısa ad)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "Tam derinlik mi" @@ -3274,21 +3272,21 @@ msgstr "Atanmış VLAN" msgid "Assigned VID" msgstr "Atanmış VID" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3355,7 +3353,7 @@ msgid "LAG interface (ID)" msgstr "LAG arabirimi (ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Sanal Cihaz Bağlamı" @@ -3429,7 +3427,7 @@ msgstr "Etiketler" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3446,38 +3444,38 @@ msgstr "" "Alfasayısal aralıklar desteklenir. (Oluşturulan isim sayısıyla " "eşleşmelidir.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "İrtibat Kişisi Adı" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "İletişim telefonu" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "İletişim E-posta" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Saat dilimi" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3487,58 +3485,59 @@ msgstr "Saat dilimi" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Üretici" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Form faktörü" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Genişlik" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Yükseklik (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Azalan birimler" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Dış genişlik" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Dış derinlik" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Dış ünite" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Montaj derinliği" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3549,10 +3548,10 @@ msgstr "Montaj derinliği" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3561,61 +3560,61 @@ msgstr "Montaj derinliği" msgid "Weight" msgstr "Ağırlığı" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Maksimum ağırlık" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Ağırlık birimi" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Raf Tipi" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Dış Ölçüler" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Ölçüler" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Numaralandırma" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3643,45 +3642,50 @@ msgstr "Numaralandırma" msgid "Role" msgstr "Rol" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Raf tipi" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Seri Numarası" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Varlık etiketi" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Hava akışı" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3691,64 +3695,64 @@ msgstr "Hava akışı" msgid "Rack" msgstr "Raf" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Donanım" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Varsayılan platform" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Parça numarası" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "U yüksekliği" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Kullanımdan hariç tut" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Cihaz Türü" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Modül Türü" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Şasi" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "VM rolü" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3759,19 +3763,19 @@ msgstr "VM rolü" msgid "Config template" msgstr "Yapılandırma şablonu" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Cihaz tipi" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Cihaz rolü" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3785,14 +3789,36 @@ msgstr "Cihaz rolü" msgid "Platform" msgstr "Platform" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Küme" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3802,9 +3828,9 @@ msgstr "Platform" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3813,10 +3839,10 @@ msgstr "Platform" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3843,7 +3869,7 @@ msgstr "Platform" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3853,23 +3879,28 @@ msgstr "Platform" msgid "Device" msgstr "Cihaz" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Yapılandırma" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Sanallaştırma" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Modül tipi" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3887,109 +3918,109 @@ msgstr "Modül tipi" msgid "Label" msgstr "etiket" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Uzunluk" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Uzunluk birimi" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Alan adı" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "Güç paneli" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Tedarik" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Faz" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Gerilim" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Amper" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Maksimum kullanım" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Maksimum çekiliş" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Maksimum güç çekimi (watt)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Tahsis edilen çekiliş" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Tahsis edilen güç çekimi (watt)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Güç bağlantı noktası" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Besleme bacağı" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Yalnızca yönetim" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "PoE modu" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "PoE tipi" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Kablosuz rolü" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4003,17 +4034,17 @@ msgstr "Kablosuz rolü" msgid "Module" msgstr "Modül" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "GECİKME" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Sanal cihaz bağlamları" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4022,7 +4053,7 @@ msgstr "Sanal cihaz bağlamları" msgid "Speed" msgstr "Hız" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4036,76 +4067,88 @@ msgstr "Hız" msgid "Mode" msgstr "Modu" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "VLAN grubu" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "Etiketsiz VLAN" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "Etiketli VLAN'lar" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Kablosuz LAN grubu" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "Kablosuz LAN'lar" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Adresleme" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Operasyon" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "İlgili Arayüzler" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "802.1Q Anahtarlama" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "VLAN'ları atamak için arayüz modu belirtilmelidir" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "Bir erişim arabirimi VLAN'ları etiketlemiş olamaz." @@ -4131,9 +4174,9 @@ msgstr "Atanan grup" msgid "available options" msgstr "mevcut seçenekler" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4155,15 +4198,15 @@ msgstr "Bu raf tipinin üreticisi" msgid "The lowest-numbered position in the rack" msgstr "Raftaki en düşük numaralı konum" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Ray-ray genişliği (inç cinsinden)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Dış boyutlar için birim" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Raf ağırlıkları için ünite" @@ -4175,156 +4218,146 @@ msgstr "Atanan kiracının adı" msgid "Name of assigned role" msgstr "Atanan rolün adı" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Hava akışı yönü" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Ana site" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Rafın konumu (varsa)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Birimler" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Bireysel birim numaralarının virgülle ayrılmış listesi" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "Bu cihaz tipini üreten üretici" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "Bu tür cihazlar için varsayılan platform (isteğe bağlı)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Cihaz ağırlığı" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Cihaz ağırlığı için birim" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Modül ağırlığı" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Modül ağırlığı için birim" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Platform atamalarını bu üreticiye sınırlayın" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Atanan rol" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Cihaz tipi üreticisi" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Cihaz tipi modeli" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Atanan platform" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Sanal şasi" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Küme" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Sanallaştırma kümesi" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Atanan konum (varsa)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Atanmış raf (varsa)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Yüz" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Monte edilmiş raf yüzü" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Ana cihaz (alt cihazlar için)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Cihaz yuvası" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "Bu cihazın kurulu olduğu cihaz yuvası (alt cihazlar için)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "Bu modülün kurulu olduğu cihaz" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Modül yuvası" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "Bu modülün kurulu olduğu modül yuvası" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "Modül türü" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Bileşenleri çoğaltın" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4332,87 +4365,87 @@ msgstr "" "Bu modül türüyle ilişkili bileşenleri otomatik olarak doldurun (varsayılan " "olarak etkindir)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Bileşenleri benimseyin" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Mevcut bileşenleri benimseyin" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Bağlantı noktası tipi" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Bps cinsinden bağlantı noktası hızı" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Çıkış tipi" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Bu prizi besleyen yerel güç portu" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Elektrik fazı (üç fazlı devreler için)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Ebeveyn arayüzü" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Köprülü arayüz" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "Gecikme" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Ebeveyn LAG arayüzü" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "Vdcs" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" "VDC isimleri virgülle ayrılmış, çift tırnak işareti ile çevrelenmiştir. " "Örnek:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Fiziksel ortam" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Dubleks" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "Poe modu" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Poe tipi" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "IEEE 802.1Q çalışma modu (L2 arayüzleri için)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4420,172 +4453,172 @@ msgstr "IEEE 802.1Q çalışma modu (L2 arayüzleri için)" msgid "Assigned VRF" msgstr "Atanmış VRF" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "Rf rolü" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Kablosuz rolü (AP/istasyon)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} cihaza atanmadı {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Arka bağlantı noktası" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "İlgili arka bağlantı noktası" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Fiziksel ortam sınıflandırması" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Yüklü cihaz" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "Bu bölmeye takılan çocuk cihazı" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Çocuk cihazı bulunamadı." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Ana envanter kalemi" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Bileşen tipi" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Bileşen Türü" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Bileşen adı" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Bileşen Adı" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Bileşen bulunamadı: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "A Tarafı Cihazı" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Cihaz adı" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Taraf A tipi" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "Sonlandırma türü" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "A Tarafı adı" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "Fesih adı" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "B tarafı cihazı" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Taraf B tipi" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "B tarafı adı" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Bağlantı durumu" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "Yan {side_upper}: {device} {termination_object} zaten bağlı" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} yan sonlandırma bulunamadı: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Usta" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Ana cihaz" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Ana sitenin adı" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "Yukarı akış güç paneli" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Birincil veya gereksiz" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Besleme tipi (AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Tek veya üç fazlı" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "Birincil IPv4" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "Maskeli IPv4 adresi, örn. 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "Birincil IPv6" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "Önek uzunluğuna sahip IPv6 adresi, örn. 2001:db8: :1/64" @@ -4672,10 +4705,6 @@ msgstr "Ebeveyn grubu" msgid "Facility" msgstr "Tesis" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Raf tipi" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Fonksiyon" @@ -4712,7 +4741,7 @@ msgid "Has virtual device contexts" msgstr "Sanal cihaz bağlamlarına sahiptir" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Küme grubu" @@ -4751,7 +4780,7 @@ msgstr "Tür" msgid "Mgmt only" msgstr "Sadece Mgmt" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4855,36 +4884,46 @@ msgstr "Bu modül türüyle ilişkili bileşenleri otomatik olarak doldurun" msgid "Characteristics" msgstr "ÖZELLİKLERİ" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Konsol bağlantı noktası şablonu" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Konsol sunucusu bağlantı noktası şablonu" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Ön bağlantı noktası şablonu" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Arayüz şablonu" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Elektrik prizi şablonu" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Güç bağlantı noktası şablonu" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Arka bağlantı noktası şablonu" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4908,7 +4947,7 @@ msgstr "Arka bağlantı noktası şablonu" msgid "Interface" msgstr "Arayüz" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4916,14 +4955,14 @@ msgstr "Arayüz" msgid "Console Port" msgstr "Konsol Bağlantı Noktası" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Konsol Sunucusu Bağlantı Noktası" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4934,7 +4973,7 @@ msgstr "Konsol Sunucusu Bağlantı Noktası" msgid "Front Port" msgstr "Ön Bağlantı Noktası" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4947,40 +4986,40 @@ msgstr "Ön Bağlantı Noktası" msgid "Rear Port" msgstr "Arka Bağlantı Noktası" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Güç Bağlantı Noktası" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Güç Çıkışı" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Bileşen Ataması" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "Bir InventoryItem yalnızca tek bir bileşene atanabilir." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "LAG arayüzü" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "Gruba göre atama için mevcut VLAN'ları filtreleyin." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Çocuk Cihazı" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -4988,35 +5027,35 @@ msgstr "" "Alt aygıtlar önce oluşturulmalı ve ana aygıtın sahasına ve rafına " "atanmalıdır." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Konsol bağlantı noktası" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Konsol sunucusu bağlantı noktası" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Ön bağlantı noktası" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "Güç çıkışı" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Envanter Öğesi" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Envanter Öğesi Rolü" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5034,12 +5073,12 @@ msgstr "" "bekleniyor." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Arka bağlantı noktaları" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" "Oluşturulan her ön bağlantı noktası için bir arka bağlantı noktası ataması " @@ -5054,16 +5093,7 @@ msgstr "" "Oluşturulacak ön bağlantı noktası şablonlarının sayısı ({frontport_count}) " "seçilen arka port konumu sayısıyla eşleşmelidir ({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"Dize {module} varsa atanan modülün konumu ile " -"değiştirilecektir." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " @@ -5072,24 +5102,24 @@ msgstr "" "Oluşturulacak ön bağlantı noktalarının sayısı ({frontport_count}) seçilen " "arka port konumu sayısıyla eşleşmelidir ({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Üyeler" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Başlangıç pozisyonu" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." msgstr "İlk üye cihazın konumu. Her ek üye için bir artar." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "İlk VC üyesi için bir pozisyon belirtilmelidir." @@ -6002,12 +6032,12 @@ msgstr "pozisyon (U)" msgid "rack face" msgstr "raf yüzü" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "birincil IPv4" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "birincil IPv6" @@ -6175,21 +6205,21 @@ msgid "" "device ({device})." msgstr "Modül, atanan cihaza ait bir modül bölmesine kurulmalıdır ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "domain" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "sanal kasa" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "Seçilen usta ({master}) bu sanal kasaya atanmamıştır." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6198,34 +6228,34 @@ msgstr "" "Sanal kasa silinemiyor {self}. Çapraz şasi LAG arabirimleri oluşturan üye " "arayüzleri vardır." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "belirlemek" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Ana aygıta benzersiz sayısal tanımlayıcı" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "yorumlar" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "sanal cihaz bağlamı" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "sanal cihaz bağlamları" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} IPV değil{family} adres." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "Birincil IP adresi, atanan cihazdaki bir arayüze ait olmalıdır." @@ -6412,7 +6442,7 @@ msgstr "Yerel olarak atanmış tanımlayıcı" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Fonksiyonel rol" @@ -6621,7 +6651,7 @@ msgstr "Ulaşılabilir" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Aygıtlar" @@ -6650,8 +6680,8 @@ msgid "Site Group" msgstr "Site Grubu" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6702,20 +6732,20 @@ msgid "Power outlets" msgstr "Elektrik prizleri" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Arayüzler" @@ -6741,8 +6771,8 @@ msgid "Module Bay" msgstr "Modül Yuvası" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6771,7 +6801,7 @@ msgstr "Maksimum çekim (W)" msgid "Allocated draw (W)" msgstr "Tahsis edilen çekiliş (W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6867,87 +6897,87 @@ msgstr "U Yüksekliği" msgid "Instances" msgstr "Örnekler" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Konsol Bağlantı Noktaları" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Konsol Sunucusu Bağlantı Noktaları" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Güç Bağlantı Noktaları" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Elektrik Prizleri" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Ön Bağlantı Noktaları" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Arka Bağlantı Noktaları" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Cihaz Yuvaları" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Modül Bölmeleri" @@ -6996,7 +7026,7 @@ msgstr "Uzay" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7006,28 +7036,28 @@ msgstr "Siteler" msgid "Test case must set peer_termination_type" msgstr "Test senaryosu peer_termination_type ayarlamalıdır" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Bağlantısı kesildi {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Rezervasyon" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Raf Olmayan Cihazlar" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Yapılandırma Bağlamı" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "Oluştur Yapılandırması" @@ -7038,35 +7068,35 @@ msgstr "Şablon oluşturulurken bir hata oluştu: {error}" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Sanal Makineler" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Yüklü cihaz {device} körfezde {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Kaldırılan cihaz {device} körfezden {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Çocuklar" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Eklenen üye {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "Ana aygıt kaldırılamıyor {device} sanal kasadan." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "Kaldırıldı {device} sanal kasadan {chassis}" @@ -7249,7 +7279,6 @@ msgstr "Güncelleme" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -8077,19 +8106,19 @@ msgstr "Komut dosyasının yürütülmesini belirli bir zamana planlayın" msgid "Interval at which this script is re-run (in minutes)" msgstr "Bu komut dosyasının yeniden çalıştırıldığı aralık (dakika cinsinden)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "Veritabanı değişiklikleri otomatik olarak geri alındı." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Komut dosyası hatayla iptal edildi: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Bir istisna oluştu: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "Veritabanı değişiklikleri hata nedeniyle geri alındı." @@ -9115,7 +9144,7 @@ msgstr "Silinen widget: " msgid "Error deleting widget: " msgstr "Widget silinirken hata oluştu: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "Komut dosyası çalıştırılamıyor: RQ işçi işlemi çalışmıyor." @@ -9260,7 +9289,7 @@ msgid "Prefixes which contain this prefix or IP" msgstr "Bu önek veya IP'yi içeren önekler" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Maske uzunluğu" @@ -9274,7 +9303,7 @@ msgid "VLAN number (1-4094)" msgstr "VLAN numarası (1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9386,16 +9415,16 @@ msgstr "CIDR maskesi (örn. /24) gereklidir." msgid "Address pattern" msgstr "Adres deseni" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "Benzersiz alanı uygulayın" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "Özeldir" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9409,20 +9438,20 @@ msgstr "Özeldir" msgid "RIR" msgstr "ZIVIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Eklenen tarih" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "VLAN Grubu" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9435,32 +9464,32 @@ msgstr "VLAN Grubu" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Önek uzunluğu" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "Havuz mu" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "Tamamen kullanılmış gibi davran" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "VLAN Ataması" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "DNS adı" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9468,12 +9497,12 @@ msgstr "DNS adı" msgid "Protocol" msgstr "Protokol" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "Grup Kimliği" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9485,12 +9514,12 @@ msgstr "Grup Kimliği" msgid "Authentication type" msgstr "Kimlik doğrulama türü" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Kimlik doğrulama anahtarı" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9502,26 +9531,26 @@ msgstr "Kimlik doğrulama anahtarı" msgid "Authentication" msgstr "Kimlik Doğrulama" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Kapsam türü" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "VLAN ID aralıkları" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Kapsam" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "VLAN ID aralıkları" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Site ve Grup" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9548,8 +9577,8 @@ msgstr "VLAN grubu (varsa)" msgid "Parent device of assigned interface (if any)" msgstr "Atanan arayüzün ana cihazı (varsa)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9575,40 +9604,60 @@ msgstr "Birincildir" msgid "Make this the primary IP for the assigned device" msgstr "Bunu atanan cihaz için birincil IP yapın" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" "Aygıt veya sanal makine belirtilmemiş; birincil IP olarak ayarlanamıyor" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "Arayüz belirtilmedi; birincil IP olarak ayarlanamıyor" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Kimlik doğrulama türü" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Kapsam türü (uygulama ve model)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Atanmış VLAN grubu" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "IP protokolü" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "Bir VM'ye atanmadıysa gereklidir" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "Bir cihaza atanmadıysa gereklidir" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} bu cihaza/VM'ye atanmamıştır." @@ -9690,7 +9739,7 @@ msgstr "Bir arayüze atandı" msgid "DNS Name" msgstr "DNS Adı" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9701,13 +9750,13 @@ msgstr "VLAN'lar" msgid "Contains VLAN ID" msgstr "VLAN Kimliği içerir" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "VLAN KİMLİĞİ" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9718,7 +9767,7 @@ msgstr "VLAN KİMLİĞİ" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9747,8 +9796,8 @@ msgstr "Site/VLAN Ataması" msgid "IP Range" msgstr "IP Aralığı" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "FHRP Grubu" @@ -9757,45 +9806,56 @@ msgstr "FHRP Grubu" msgid "Make this the primary IP for the device/VM" msgstr "Bunu cihaz/VM için birincil IP yapın" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "NAT IP (İç)" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "IP adresi yalnızca tek bir nesneye atanabilir." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Üst nesne için birincil IP olarak belirlenirken IP adresi yeniden atanamıyor" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" "Yalnızca bir arayüze atanan IP adresleri birincil IP olarak belirlenebilir." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Sanal IP Adresi" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "Atama zaten var" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "VLAN kimlikleri" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "Çocuk VLAN'ları" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9803,33 +9863,33 @@ msgstr "" "Bir veya daha fazla bağlantı noktası numarasının virgülle ayrılmış listesi. " "Bir aralık bir tire kullanılarak belirtilebilir." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Hizmet Şablonu" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Liman (lar)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Hizmet" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Hizmet şablonu" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "Şablondan" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Özel" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" @@ -10109,6 +10169,13 @@ msgstr "{ip} bir arayüze atanamayacak bir yayın adresidir." msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Yinelenen IP adresi şurada bulundu {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Üst nesne için birincil IP olarak belirlenirken IP adresi yeniden atanamıyor" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Yalnızca IPv6 adreslerine SLAAC durumu atanabilir" @@ -10159,40 +10226,48 @@ msgstr "scope_id olmadan scope_type ayarlanamıyor." msgid "Cannot set scope_id without scope_type." msgstr "scope_type olmadan scope_id ayarlanamıyor." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Aralıklar üst üste gelemez." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"Maksimum çocuk VID, minimum çocuk VID'den büyük veya ona eşit olmalıdır " -"({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "Bu VLAN'ın atandığı belirli site (varsa)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "VLAN grubu (isteğe bağlı)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "Sayısal VLAN Kimliği (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Bu VLAN'ın operasyonel durumu" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "Bu VLAN'ın birincil işlevi" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10201,7 +10276,7 @@ msgstr "" "VLAN {group} adlı gruba (kapsam: {scope}) atandığı için; {site} adlı siteye " "de atanamaz ." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "VID aralıklarda olmalıdır {ranges} gruptaki VLAN'lar için {group}" @@ -10967,17 +11042,12 @@ msgstr "IPsec İlkeleri" msgid "IPSec Profiles" msgstr "IPsec Profilleri" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Sanallaştırma" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Sanal Diskler" @@ -11139,7 +11209,7 @@ msgstr "Sistem" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11387,19 +11457,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Satır {i}: Kimliği olan nesne {id} mevcut değil" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "Hayır {object_type} seçildi." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Yeniden adlandırıldı {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Silinmiş {count} {object_type}" @@ -11431,7 +11501,7 @@ msgstr "Senkronize {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name} get_children () uygulamasını uygulamalıdır" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11775,9 +11845,7 @@ msgid "Circuit Type" msgstr "Devre Tipi" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11788,7 +11856,6 @@ msgstr "Ekle" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -12077,35 +12144,35 @@ msgstr "günler" msgid "Indefinite" msgstr "belirsiz" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Yüklü değil" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Genel Bakış" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Yüklemek" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Eklenti Ayrıntıları" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "Özet" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Lisans" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Sürüm Geçmişi" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Yerel Kurulum Talimatları" @@ -12451,8 +12518,8 @@ msgstr "Hizmet ekle" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12525,20 +12592,24 @@ msgstr "Yapılandırma" msgid "Context Data" msgstr "Bağlam Verileri" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Oluşturulan Yapılandırma" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "İndir" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Yapılandırma şablonu bulunamadı" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12560,7 +12631,6 @@ msgid "Local Config Context Data" msgstr "Yerel Yapılandırma Bağlam Verileri" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12607,12 +12677,12 @@ msgid "VM Role" msgstr "VM Rolü" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Model Adı" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Parça Numarası" @@ -12751,7 +12821,7 @@ msgstr "MAC Adresi" msgid "Wireless Link" msgstr "Kablosuz Bağlantı" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Akran" @@ -13374,7 +13444,7 @@ msgstr "Komut dosyalarını çalıştırma izniniz yok" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Komut Dosyasını Çalıştır" @@ -13387,27 +13457,32 @@ msgstr "Komut dosyası yüklenirken hata oluştu" msgid "Script no longer exists in the source file." msgstr "Kaynak dosyada komut dosyası artık mevcut değil." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Son Koşu" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "Komut dosyası artık kaynak dosyada mevcut değil" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Asla" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Tekrar koş" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Komut Dosyası Bulunamadı" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13727,7 +13802,7 @@ msgstr "Tüm bildirimler" msgid "Select" msgstr "Seçiniz" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Sıfırla" @@ -14211,6 +14286,10 @@ msgstr "Kaynaklar" msgid "Add Virtual Disk" msgstr "Sanal Disk Ekle" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -15272,13 +15351,13 @@ msgid "Memory (MB)" msgstr "Bellek (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Disk (GB)" +msgid "Disk (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Boyut (GB)" +msgid "Size (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15459,68 +15538,80 @@ msgstr "sanal disk" msgid "virtual disks" msgstr "sanal diskler" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "Eklendi {count} kümelenecek cihazlar {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "Kaldırıldı {count} kümeden aygıtlar {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPsec - Taşıma" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec - Tünel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP içinde IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GREC" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "göbek" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "konuştu" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "Agresif" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Ana" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Önceden paylaşılan anahtarlar" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Sertifikalar" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "RSA imzaları" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "DSA imzaları" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15529,23 +15620,27 @@ msgstr "DSA imzaları" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Grup {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Ethernet Özel LAN" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Ethernet Sanal Özel LAN" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Ethernet Özel Ağacı" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Ethernet Sanal Özel Ağacı" diff --git a/netbox/translations/uk/LC_MESSAGES/django.mo b/netbox/translations/uk/LC_MESSAGES/django.mo index 14d595e16..04eed761a 100644 Binary files a/netbox/translations/uk/LC_MESSAGES/django.mo and b/netbox/translations/uk/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/uk/LC_MESSAGES/django.po b/netbox/translations/uk/LC_MESSAGES/django.po index 39cbf3bda..1588a5495 100644 --- a/netbox/translations/uk/LC_MESSAGES/django.po +++ b/netbox/translations/uk/LC_MESSAGES/django.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" "Last-Translator: Vladyslav V. Prodan, 2024\n" "Language-Team: Ukrainian (https://app.transifex.com/netbox-community/teams/178115/uk/)\n" @@ -89,8 +89,8 @@ msgstr "Ваш пароль успішно змінено." #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -103,7 +103,7 @@ msgstr "Забезпечення" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -114,8 +114,8 @@ msgid "Active" msgstr "Активний" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "Офлайн" @@ -128,7 +128,7 @@ msgstr "Зняття з експлуатації" msgid "Decommissioned" msgstr "Виведені з експлуатації" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "Первинний" @@ -201,12 +201,12 @@ msgstr "Група тех. майданчиків (скорочення)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -215,18 +215,17 @@ msgstr "Група тех. майданчиків (скорочення)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -334,10 +333,10 @@ msgstr "Припинення A (ідентифікатор)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -380,16 +379,16 @@ msgstr "Канал зв'язку (ідентифікатор вмісту)" #: netbox/circuits/filtersets.py:345 msgid "Circuit group (ID)" -msgstr "Группа каналів зв'язку (ідентифікатор)" +msgstr "Група каналів зв'язку (ідентифікатор)" #: netbox/circuits/filtersets.py:351 msgid "Circuit group (slug)" -msgstr "Группа каналів зв'язку (скорочення)" +msgstr "Група каналів зв'язку (скорочення)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -404,33 +403,33 @@ msgstr "ASNs" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -439,7 +438,7 @@ msgstr "ASNs" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -454,7 +453,7 @@ msgstr "ASNs" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -474,7 +473,7 @@ msgstr "ASNs" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -567,10 +566,10 @@ msgid "Service ID" msgstr "Ідентифікатор служби" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -591,16 +590,16 @@ msgstr "Колір" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -655,14 +654,14 @@ msgstr "Обліковий запис постачальника" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -671,13 +670,13 @@ msgstr "Обліковий запис постачальника" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -688,7 +687,7 @@ msgstr "Обліковий запис постачальника" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -724,30 +723,30 @@ msgstr "Статус" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -805,7 +804,7 @@ msgstr "Дата припинення дії" #: netbox/circuits/forms/bulk_edit.py:158 #: netbox/circuits/forms/filtersets.py:186 msgid "Commit rate (Kbps)" -msgstr "Гарантована мінімальна швідкість (Кбіт/с)" +msgstr "Гарантована мінімальна швидкість (Кбіт/с)" #: netbox/circuits/forms/bulk_edit.py:173 #: netbox/circuits/forms/model_forms.py:112 @@ -817,11 +816,11 @@ msgstr "Параметри обслуговування" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -843,7 +842,7 @@ msgstr "Оренда" #: netbox/templates/circuits/inc/circuit_termination_fields.html:62 #: netbox/templates/circuits/providernetwork.html:17 msgid "Provider Network" -msgstr "Мережа провайдерів" +msgstr "Мережа провайдера" #: netbox/circuits/forms/bulk_edit.py:199 msgid "Port speed (Kbps)" @@ -853,13 +852,13 @@ msgstr "Швидкість порту (Кбіт/с)" msgid "Upstream speed (Kbps)" msgstr "Швидкість висхідного потоку (Кбіт/с)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" -msgstr "Позначка з'єднана" +msgstr "Позначити з'єднаним" #: netbox/circuits/forms/bulk_edit.py:219 #: netbox/circuits/forms/model_forms.py:157 @@ -873,7 +872,7 @@ msgstr "Кінець каналу зв'язку" #: netbox/circuits/forms/bulk_edit.py:221 #: netbox/circuits/forms/model_forms.py:159 msgid "Termination Details" -msgstr "Деталі припинення" +msgstr "Деталі кінця" #: netbox/circuits/forms/bulk_edit.py:251 #: netbox/circuits/forms/filtersets.py:268 @@ -896,7 +895,7 @@ msgstr "Призначений провайдер" #: netbox/circuits/forms/bulk_import.py:83 msgid "Assigned provider account" -msgstr "Призначений обліковий запис постачальника" +msgstr "Призначений обліковий запис провайдера" #: netbox/circuits/forms/bulk_import.py:90 msgid "Type of circuit" @@ -904,10 +903,10 @@ msgstr "Тип каналу зв'язку" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -917,13 +916,13 @@ msgstr "Операційний стан" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -937,23 +936,23 @@ msgstr "Призначений орендар" #: netbox/templates/dcim/cable.html:68 netbox/templates/dcim/cable.html:72 #: netbox/vpn/forms/bulk_import.py:100 netbox/vpn/forms/filtersets.py:77 msgid "Termination" -msgstr "Припинення" +msgstr "Кінець" #: netbox/circuits/forms/bulk_import.py:130 #: netbox/circuits/forms/filtersets.py:147 #: netbox/circuits/forms/filtersets.py:227 #: netbox/circuits/forms/model_forms.py:144 msgid "Provider network" -msgstr "Мережа провайдерів" +msgstr "Мережа провайдера" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -970,9 +969,9 @@ msgstr "Мережа провайдерів" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1001,8 +1000,8 @@ msgid "Contacts" msgstr "Контакти" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1010,13 +1009,12 @@ msgstr "Контакти" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1029,16 +1027,16 @@ msgid "Region" msgstr "Регіон" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1050,7 +1048,7 @@ msgstr "Група тех. майданчиків" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1083,15 +1081,15 @@ msgstr "Атрибути" #: netbox/templates/circuits/circuit.html:22 #: netbox/templates/circuits/provideraccount.html:24 msgid "Account" -msgstr "Рахунок" +msgstr "Обліковий запис" #: netbox/circuits/forms/filtersets.py:217 msgid "Term Side" -msgstr "Сторона терміну" +msgstr "Сторона завершення" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1101,11 +1099,11 @@ msgstr "Призначення" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1147,7 +1145,7 @@ msgstr "Група" #: netbox/circuits/forms/model_forms.py:182 #: netbox/templates/circuits/circuitgroup.html:25 msgid "Circuit Group" -msgstr "Група каналу зв'язку" +msgstr "Група каналів зв'язку" #: netbox/circuits/models/circuits.py:27 netbox/dcim/models/cables.py:67 #: netbox/dcim/models/device_component_templates.py:517 @@ -1170,27 +1168,27 @@ msgstr "типи каналів зв'язку" #: netbox/circuits/models/circuits.py:48 msgid "circuit ID" -msgstr "iдентифікатор каналу зв'язку" +msgstr "ідентифікатор каналу зв'язку" #: netbox/circuits/models/circuits.py:49 msgid "Unique circuit ID" msgstr "Унікальний ідентифікатор каналу зв'язку" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "статус" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "встановлено" @@ -1200,11 +1198,11 @@ msgstr "припинється" #: netbox/circuits/models/circuits.py:94 msgid "commit rate (Kbps)" -msgstr "гарантована мінімальна швідкість (Кбіт/с)" +msgstr "гарантована швидкість (Кбіт/с)" #: netbox/circuits/models/circuits.py:95 msgid "Committed rate" -msgstr "Гарантирована швідкість" +msgstr "Гарантована швидкість" #: netbox/circuits/models/circuits.py:137 msgid "circuit" @@ -1216,7 +1214,7 @@ msgstr "канали зв'язку" #: netbox/circuits/models/circuits.py:170 msgid "circuit group" -msgstr "група каналу зв'язку" +msgstr "група каналів зв'язку" #: netbox/circuits/models/circuits.py:171 msgid "circuit groups" @@ -1237,7 +1235,7 @@ msgstr "Призначення групи каналів зв'язку" #: netbox/circuits/models/circuits.py:240 msgid "termination" -msgstr "припинення" +msgstr "кінець" #: netbox/circuits/models/circuits.py:257 msgid "port speed (Kbps)" @@ -1253,7 +1251,8 @@ msgstr "швидкість висхідного потоку (Кбіт/с)" #: netbox/circuits/models/circuits.py:266 msgid "Upstream speed, if different from port speed" -msgstr "Швидкість висхідного потоку, якщо відрізняється від швидкості порту" +msgstr "" +"Швидкість висхідного потоку, якщо вона відрізняється від швидкості порту" #: netbox/circuits/models/circuits.py:271 msgid "cross-connect ID" @@ -1312,11 +1311,11 @@ msgstr "" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1327,7 +1326,7 @@ msgstr "" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1340,11 +1339,11 @@ msgstr "" #: netbox/vpn/models/crypto.py:221 netbox/vpn/models/l2vpn.py:22 #: netbox/vpn/models/tunnels.py:35 netbox/wireless/models.py:51 msgid "name" -msgstr "найменування" +msgstr "назва" #: netbox/circuits/models/providers.py:25 msgid "Full name of the provider" -msgstr "Повне найменування провайдера" +msgstr "Повна назва провайдера" #: netbox/circuits/models/providers.py:28 netbox/dcim/models/devices.py:86 #: netbox/dcim/models/racks.py:137 netbox/dcim/models/sites.py:149 @@ -1366,7 +1365,7 @@ msgstr "провайдери" #: netbox/circuits/models/providers.py:63 msgid "account ID" -msgstr "iдентифікатор рахунку" +msgstr "ідентифікатор облікового запису" #: netbox/circuits/models/providers.py:86 msgid "provider account" @@ -1374,11 +1373,11 @@ msgstr "обліковий запис провайдера" #: netbox/circuits/models/providers.py:87 msgid "provider accounts" -msgstr "акаунти провайдера" +msgstr "облікові записи провайдера" #: netbox/circuits/models/providers.py:115 msgid "service ID" -msgstr "iдентифікатор послуги" +msgstr "ідентифікатор послуги" #: netbox/circuits/models/providers.py:126 msgid "provider network" @@ -1386,7 +1385,7 @@ msgstr "мережа провайдера" #: netbox/circuits/models/providers.py:127 msgid "provider networks" -msgstr "мережі провайдерів" +msgstr "мережі провайдера" #: netbox/circuits/tables/circuits.py:32 #: netbox/circuits/tables/circuits.py:132 @@ -1415,7 +1414,7 @@ msgstr "мережі провайдерів" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1426,7 +1425,7 @@ msgstr "мережі провайдерів" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1457,7 +1456,7 @@ msgstr "мережі провайдерів" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1589,7 +1588,7 @@ msgstr "Кількість ASN" #: netbox/circuits/views.py:331 #, python-brace-format msgid "No terminations have been defined for circuit {circuit}." -msgstr "Не визначено кінців для каналу зв'язку{circuit}." +msgstr "Не визначено кінців для каналу зв'язку {circuit}." #: netbox/circuits/views.py:380 #, python-brace-format @@ -1621,7 +1620,7 @@ msgstr "Завершено" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "Збій" @@ -1688,7 +1687,7 @@ msgid "Cancelled" msgstr "Скасовано" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "Місцеві" @@ -1775,8 +1774,8 @@ msgid "User name" msgstr "Ім'я користувача" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1880,7 +1879,7 @@ msgid "Completed before" msgstr "Завершено раніше" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1930,24 +1929,24 @@ msgstr "Параметри бекенду" #: netbox/core/forms/model_forms.py:96 msgid "File Upload" -msgstr "Завантаження файлу" +msgstr "Вивантажити файл" #: netbox/core/forms/model_forms.py:108 msgid "Cannot upload a file and sync from an existing file" -msgstr "Не вдається завантажити файл і синхронізувати з існуючого файлу" +msgstr "Не вдається вивантажити файл і синхронізувати з існуючого файлу" #: netbox/core/forms/model_forms.py:110 msgid "Must upload a file or select a data file to sync" -msgstr "Потрібно завантажити файл або вибрати файл даних для синхронізації" +msgstr "Потрібно вивантажити файл або вибрати файл даних для синхронізації" #: netbox/core/forms/model_forms.py:153 #: netbox/templates/dcim/rack_elevation_list.html:6 msgid "Rack Elevations" msgstr "Висота стійки" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "Електрика" @@ -2039,7 +2038,7 @@ msgstr "зміна об'єкта" #: netbox/core/models/change_logging.py:107 msgid "object changes" -msgstr "зміни об'єкта" +msgstr "змін об'єкта" #: netbox/core/models/change_logging.py:123 #, python-brace-format @@ -2047,7 +2046,7 @@ msgid "Change logging is not supported for this object type ({type})." msgstr "Журнал змін не підтримується для цього типу об'єктів ({type})." #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2107,7 +2106,7 @@ msgstr "тип" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2172,7 +2171,7 @@ msgstr "доріжка" #: netbox/core/models/data.py:283 msgid "File path relative to the data source's root" -msgstr "Шляху до файлу відносно кореня джерела даних" +msgstr "Шлях до файлу відносно кореня джерела даних" #: netbox/core/models/data.py:287 netbox/ipam/models/ip.py:503 msgid "size" @@ -2200,7 +2199,7 @@ msgstr "файли даних" #: netbox/core/models/data.py:401 msgid "auto sync record" -msgstr "запис автоматичної синхронізації" +msgstr "автоматична синхронізація запису" #: netbox/core/models/data.py:402 msgid "auto sync records" @@ -2216,7 +2215,7 @@ msgstr "шлях до файлу" #: netbox/core/models/files.py:44 msgid "File path relative to the designated root path" -msgstr "Шляху до файлу відносно призначеного кореневого шляху" +msgstr "Шлях до файлу відносно призначеного кореневого шляху" #: netbox/core/models/files.py:61 msgid "managed file" @@ -2226,59 +2225,59 @@ msgstr "керований файл" msgid "managed files" msgstr "керовані файли" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "заплановано" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "інтервал" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "Інтервал рецидивів (у хвилинах)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "розпочато" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "завершено" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "дані" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "помилка" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" -msgstr "iдентифікатор завдання" +msgstr "ідентифікатор завдання" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "завдання" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "завдання" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "Завдання не можуть бути призначені для цього типу об'єкта ({type})." -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "" "Невірний статус для припинення виконання завдання. Треба вибрати: {choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "" @@ -2321,7 +2320,7 @@ msgstr "Є активним" #: netbox/core/tables/data.py:50 netbox/templates/core/datafile.html:31 msgid "Path" -msgstr "Шляху" +msgstr "Шлях" #: netbox/core/tables/data.py:54 #: netbox/templates/extras/inc/result_pending.html:7 @@ -2339,7 +2338,7 @@ msgstr "Ідентифікатор" #: netbox/core/tables/jobs.py:35 msgid "Interval" -msgstr "інтервал" +msgstr "Інтервал" #: netbox/core/tables/plugins.py:14 netbox/templates/vpn/ipsecprofile.html:44 #: netbox/vpn/forms/bulk_edit.py:141 netbox/vpn/forms/bulk_import.py:172 @@ -2363,7 +2362,7 @@ msgstr "Максимальна версія NetBox" msgid "No plugin data found" msgstr "Не знайдено даних плагіна" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "Автор" @@ -2371,7 +2370,7 @@ msgstr "Автор" msgid "Installed" msgstr "Встановлено" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "Сертифіковано" @@ -2497,11 +2496,11 @@ msgstr "Завдання {id} було зупинено." msgid "Failed to stop job {id}" msgstr "Не вдалося зупинити завдання {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "Не вдалося завантажити каталог плагінів" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "Плагін {name} не знайдено" @@ -2521,7 +2520,7 @@ msgid "Staging" msgstr "Підготовка" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "Виведення з експлуатації" @@ -2585,7 +2584,7 @@ msgstr "Застарілий" msgid "Millimeters" msgstr "Міліметри" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "Дюйми" @@ -2599,15 +2598,15 @@ msgstr "Спереду ззаду" msgid "Rear to front" msgstr "Ззаду спереду" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2687,7 +2686,7 @@ msgid "Top to bottom" msgstr "Зверху вниз" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "Пасивний" @@ -2716,8 +2715,8 @@ msgid "Proprietary" msgstr "Пропрієтарний" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "Інше" @@ -2730,24 +2729,24 @@ msgstr "ITA/Міжнародні" msgid "Physical" msgstr "Фізичний" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "Віртуальний" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "Бездротові мережі" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "Віртуальні інтерфейси" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2756,27 +2755,27 @@ msgstr "Віртуальні інтерфейси" msgid "Bridge" msgstr "Міст" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "Група агрегації каналів (LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "Ethernet (фіксований)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "Ethernet (модульний)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "Ethernet (панель)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "Стільниковий" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2784,130 +2783,130 @@ msgstr "Стільниковий" msgid "Serial" msgstr "Серійний" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "Коаксіальний" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "Стекований" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "Половинний" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "Повний" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "Авто" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "Доступ" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "З мітками" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "З мітками (Усі)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "Стандарт IEEE" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "Пасивний 24В (2-парний)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "Пасивний 24В (4-парний)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "Пасивний 48В (2-парний)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "Пасивний 48В (4-парний)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "Мідний" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "Волоконно-оптичний" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "Волоконний" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "Підключений" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "Кілометри" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "Метри" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "Сантиметри" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "Милі" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "Фути" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "Кілограми" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "Грами" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "Фунтів" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "Унцій" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "Надлишковий" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "Однофазний" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "Трифазний" @@ -3124,17 +3123,17 @@ msgstr "Платформа (ідентифікатор)" #: netbox/dcim/filtersets.py:1015 netbox/extras/filtersets.py:569 #: netbox/virtualization/filtersets.py:226 msgid "Platform (slug)" -msgstr "Платформа (скоречення)" +msgstr "Платформа (скорочення)" #: netbox/dcim/filtersets.py:1051 netbox/dcim/filtersets.py:1399 #: netbox/dcim/filtersets.py:1934 netbox/dcim/filtersets.py:2176 #: netbox/dcim/filtersets.py:2235 msgid "Site name (slug)" -msgstr "Назва тех. майданчика (скоречення)" +msgstr "Назва тех. майданчика (скорочення)" #: netbox/dcim/filtersets.py:1067 msgid "Parent bay (ID)" -msgstr "Батьківська бухта (ідентифікатор)" +msgstr "Батьківський відсік (ідентифікатор)" #: netbox/dcim/filtersets.py:1071 msgid "VM cluster (ID)" @@ -3143,7 +3142,7 @@ msgstr "Кластер віртуальних машини (ідентифіка #: netbox/dcim/filtersets.py:1077 netbox/extras/filtersets.py:591 #: netbox/virtualization/filtersets.py:136 msgid "Cluster group (slug)" -msgstr "Кластерна група (скоречення)" +msgstr "Кластерна група (скорочення)" #: netbox/dcim/filtersets.py:1082 netbox/virtualization/filtersets.py:130 msgid "Cluster group (ID)" @@ -3151,9 +3150,9 @@ msgstr "Група кластерів (ідентифікатор)" #: netbox/dcim/filtersets.py:1088 msgid "Device model (slug)" -msgstr "Модель пристрою (скоречення)" +msgstr "Модель пристрою (скорочення)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "Це повна глибина" @@ -3242,7 +3241,7 @@ msgstr "Роль пристрою (ідентифікатор)" #: netbox/dcim/filtersets.py:1453 msgid "Device role (slug)" -msgstr "Роль пристрою (скоречення)" +msgstr "Роль пристрою (скорочення)" #: netbox/dcim/filtersets.py:1458 msgid "Virtual Chassis (ID)" @@ -3275,21 +3274,21 @@ msgstr "Призначений VLAN" msgid "Assigned VID" msgstr "Призначений VID" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3356,7 +3355,7 @@ msgid "LAG interface (ID)" msgstr "Інтерфейс LAG (ідентифікатор)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "Контекст віртуального пристрою" @@ -3377,7 +3376,7 @@ msgstr "Бездротова зв'язок" #: netbox/dcim/filtersets.py:1803 msgid "Parent module bay (ID)" -msgstr "Відсік батьківського модуля (iдентифікатор)" +msgstr "Відсік батьківського модуля (ідентифікатор)" #: netbox/dcim/filtersets.py:1808 msgid "Installed module (ID)" @@ -3406,7 +3405,7 @@ msgstr "Орендар (ідентифікатор)" #: netbox/dcim/filtersets.py:1945 netbox/extras/filtersets.py:618 #: netbox/tenancy/filtersets.py:251 msgid "Tenant (slug)" -msgstr "Орендар (скоречення)" +msgstr "Орендар (скорочення)" #: netbox/dcim/filtersets.py:1981 netbox/dcim/forms/filtersets.py:1077 msgid "Unterminated" @@ -3430,7 +3429,7 @@ msgstr "Мітки" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3447,38 +3446,38 @@ msgstr "" "Підтримуються буквено-цифрові діапазони. (Повинен збігатися з кількістю " "створених імен.)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "Ім'я контакту" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "Контактний телефон" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "Контактна адреса електронної пошти" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "Часовий пояс" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3488,58 +3487,59 @@ msgstr "Часовий пояс" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "Виробник" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "Форм-фактор" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "Ширина" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "Висота (U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "Юніти у низхідному порядку" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "Зовнішня ширина" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "Зовнішня глибина" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "Зовнішній блок" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "Глибина монтажу" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3550,10 +3550,10 @@ msgstr "Глибина монтажу" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3562,61 +3562,61 @@ msgstr "Глибина монтажу" msgid "Weight" msgstr "Вага" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "Максимальна вага" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "Вага юніта" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "Тип стійки" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "Зовнішні розміри" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "Габарити" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "Нумерація" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3644,45 +3644,50 @@ msgstr "Нумерація" msgid "Role" msgstr "Роль" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "Тип стійки" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "Серійний номер" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "Призначеня міток" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "Потік повітря" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3692,64 +3697,64 @@ msgstr "Потік повітря" msgid "Rack" msgstr "Стійка" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "Апаратне забезпечення" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "Платформа за замовчуванням" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "Номер партії" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "Висота U" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "Виключити з утилізації" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "Тип пристрою" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "Тип модуля" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "Шасі" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "Роль віртуальної машини" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3760,19 +3765,19 @@ msgstr "Роль віртуальної машини" msgid "Config template" msgstr "Шаблон конфігурації" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "Тип пристрою" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "Роль пристрою" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3786,14 +3791,36 @@ msgstr "Роль пристрою" msgid "Platform" msgstr "Платформа" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "Кластер" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3803,9 +3830,9 @@ msgstr "Платформа" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3814,10 +3841,10 @@ msgstr "Платформа" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3844,7 +3871,7 @@ msgstr "Платформа" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3854,23 +3881,28 @@ msgstr "Платформа" msgid "Device" msgstr "Пристрій" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "Конфігурація" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "Віртуалізація" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "Тип модуля" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3888,109 +3920,109 @@ msgstr "Тип модуля" msgid "Label" msgstr "Етикетка" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "Довжина" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "Довжина юніта" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "Домен" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "Панель живлення" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "Постачання" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "Фаза" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "Напруга" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "Сила струму" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "Максимальне використання" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "Максимальна потужність" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "Максимальна споживана потужність (Вт)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "Виділена потужність" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "Виділена споживана потужність (Вт)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "Порт живлення" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "Фідер живлення" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "Тільки управління" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "Режим PoE" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "Тип PoE" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "Бездротова роль" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -4004,17 +4036,17 @@ msgstr "Бездротова роль" msgid "Module" msgstr "Модуль" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "LAG" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "Контексти віртуальних пристроїв" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4023,7 +4055,7 @@ msgstr "Контексти віртуальних пристроїв" msgid "Speed" msgstr "Швидкість" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4037,76 +4069,88 @@ msgstr "Швидкість" msgid "Mode" msgstr "Режим" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "Група VLAN" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "VLAN без міток" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" -msgstr "VLAN з мітками" +msgstr "VLAN'и з мітками" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "Додати VLAN'и з мітками" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "Видалити мітки з VLAN'ів" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "Група бездротової локальної мережі" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "Бездротові локальні мережі" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "Адресація" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "Операція" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "Пов'язані інтерфейси" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "Комутація 802.1Q" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 -msgid "Interface mode must be specified to assign VLANs" -msgstr "Для призначення VLANs необхідно вказати режим інтерфейсу" +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "Додати/Видалити" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 +msgid "Interface mode must be specified to assign VLANs" +msgstr "Для призначення VLAN'ів необхідно вказати режим інтерфейсу" + +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "Інтерфейс доступу не може призначити VLAN'и з мітками." @@ -4132,9 +4176,9 @@ msgstr "Призначена група" msgid "available options" msgstr "доступні опції" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4156,15 +4200,15 @@ msgstr "Виробник даного стелажного типу" msgid "The lowest-numbered position in the rack" msgstr "Позиція з найменшою нумерованістю в стійці" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "Ширина рейки до рейки (у дюймах)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "Блок для зовнішніх розмірів" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "Блок для стелажних ваг" @@ -4176,158 +4220,148 @@ msgstr "ПІБ призначеного орендаря" msgid "Name of assigned role" msgstr "Назва призначеної ролі" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "Напрямок повітряного потоку" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "Батьківський тех. майданчик" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "Розташування стійки (якщо є)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "Юніти" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "Список окремих номерів юнітів, розділених комами" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "Виробник, який випускає цей тип пристрою" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "Платформа за замовчуванням для пристроїв такого типу (опціонально)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "Вага пристрою" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "Вага пристрою на 1 юніт" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "Вага модуля" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "Вага модуля на 1 юніт" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "Обмежте призначення платформи цьому виробнику" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "Призначена роль" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "Тип пристрою виробник" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "Модель типу пристрою" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "Призначена платформа" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "Віртуальне шасі" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "Кластер" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "Кластер віртуалізації" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "Призначене місце розташування (якщо є)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "Призначена стійка (якщо така є)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "Лицева сторона" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "Змонтована лицева сторона стійки" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "Батьківський пристрій (для підпорядкованих пристроїв)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "Відсік для пристроїв" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "" "Відсік для пристрою, в якому встановлено цей пристрій (для підпорядкованих " "пристроїв)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "Пристрій, в якому встановлений даний модуль" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "Відсік для модулів" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "Відсік для модуля, в якому встановлений цей модуль" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "Тип модуля" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "Повторювання компонентів" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" @@ -4335,87 +4369,87 @@ msgstr "" "Автоматично заповнювати компоненти, пов'язані з цим типом модуля (увімкнено " "за замовчуванням)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "Прийняти компоненти" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "Прийняти вже існуючі компоненти" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "Тип порту" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "Швидкість порту в біт/с" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "Тип розетки (живлення)" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "Локальний порт живлення, який живить цю розетку" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "Електрична фаза (для трифазних ланцюгів)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "Батьківський інтерфейс" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "Інтерфейс типу мост" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "LAG" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "Батьківський інтерфейс LAG" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" -msgstr "Джерела живлення постійного струму " +msgstr "Джерела живлення постійного струму" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "" "Імена джерел живлення постійного струму, розділені комами, укладені " "подвійними лапками. Приклад:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "Фізичне середовище" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "Дуплекс" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "Режим PoE" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "Тип PoE" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "Режим роботи IEEE 802.1Q (для інтерфейсів L2)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4423,176 +4457,176 @@ msgstr "Режим роботи IEEE 802.1Q (для інтерфейсів L2)" msgid "Assigned VRF" msgstr "Призначений VRF" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "роль RF" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "Бездротова роль (AP/станція)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "" "Джерело живлення постійного струму {vdc} не призначається до пристрою " "{device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "Задній порт" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "Відповідний задній порт" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "Класифікація фізичного середовища" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "Встановлений пристрій" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "Підпорядкований пристрій, встановлений у цьому відсіку" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "Підпорядкований пристрій не знайдено." -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "Батьківський предмет інвентарю" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "Тип компонента" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "Тип компонента" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "Назва компонента" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "Назва компонента" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "Компонент не знайдено: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "Сторона А пристрою" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "Назва пристрою" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "Тип сторони А" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" -msgstr "Тип припинення" +msgstr "Тип кінця" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "Назва сторони A" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" -msgstr "Назва припинення" +msgstr "Назва кінця" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "Сторона Б пристрою" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "Тип сторони Б" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "Назва сторони B" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "Статус підключення" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr "Сторона {side_upper}: {device} {termination_object} вже підключена" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} кінцева сторона не знайдена: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Майстер" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "Головний пристрій" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "Назва батьківського тех. майданчика" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "Вища за течією панель живлення" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "Первинний або надлишковий" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "Тип живлення (змінній/постійний струм)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "Однофазний або трифазний (струм)" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" -msgstr "Первинний IPv4" +msgstr "Первинна адреса IPv4" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "IPv4 адреса з маскою, наприклад 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" -msgstr "Первинний IPv6" +msgstr "Первинна адреса IPv6" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" -msgstr "IPv6 адреса з довжиною префікса, наприклад 2001:db8: :1/64" +msgstr "IPv6 адреса з довжиною префікса, наприклад 2001:db8::1/64" #: netbox/dcim/forms/common.py:24 netbox/dcim/models/device_components.py:527 #: netbox/templates/dcim/interface.html:57 @@ -4631,7 +4665,8 @@ msgstr "" #: netbox/dcim/forms/common.py:144 #, python-brace-format msgid "Cannot adopt {model} {name} as it already belongs to a module" -msgstr "Не можна усиновити {model} {name} оскільки він вже належить до модуля" +msgstr "" +"Не можна усиновити {model} {name}, оскільки він вже належить до модуля" #: netbox/dcim/forms/common.py:153 #, python-brace-format @@ -4678,10 +4713,6 @@ msgstr "Батьківська група" msgid "Facility" msgstr "Об'єкт" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "Тип стійки" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "Функція" @@ -4718,7 +4749,7 @@ msgid "Has virtual device contexts" msgstr "Має контексти віртуальних пристроїв" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "Кластерна група" @@ -4757,7 +4788,7 @@ msgstr "Вид" msgid "Mgmt only" msgstr "Тільки управління" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4861,36 +4892,50 @@ msgstr "Автоматично заповнювати компоненти, по msgid "Characteristics" msgstr "Характеристики" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" +"Буквено-цифрові діапазони підтримуються для масового створення. Змішані " +"регістри та типи в межах одного діапазону не підтримуються (приклад: " +"[ге, хе] -0/0/ [0-9]). Жетон {module}, якщо є, " +"буде автоматично замінено значенням позиції при створенні нового модуля." + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "Шаблон порту консолі" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "Шаблон порту консольного сервера" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "Шаблон фронтального порту" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "Шаблон інтерфейсу" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "Шаблон електрічної розетки" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "Шаблон порту живлення" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "Шаблон порту ззаду" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4914,7 +4959,7 @@ msgstr "Шаблон порту ззаду" msgid "Interface" msgstr "Інтерфейс" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4922,14 +4967,14 @@ msgstr "Інтерфейс" msgid "Console Port" msgstr "Порт консолі" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Порт консольного сервера" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4940,7 +4985,7 @@ msgstr "Порт консольного сервера" msgid "Front Port" msgstr "Передній порт" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4953,40 +4998,40 @@ msgstr "Передній порт" msgid "Rear Port" msgstr "Порт ззаду" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "Порт живлення" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "Електрична розетка" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "Призначення компонентів" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "Елемент інвентаря можна призначити лише одному компоненту." -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "Інтерфейс LAG" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." -msgstr "Фільтр VLAN, доступних для призначення за групами." +msgstr "Фільтр VLAN'ів, доступних для призначення за групами." -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "Підпорядкований пристрій" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." @@ -4994,35 +5039,35 @@ msgstr "" "Підпорядковані пристрої спочатку повинні бути створені та присвоєні до тех. " "майданчику та стійки батьківського пристрою." -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Консольний порт" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Порт консольного сервера" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "Передній порт" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "Розетка живлення" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "Елемент інвентаря" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "Роль елемента інвентаря" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5040,12 +5085,12 @@ msgstr "" "очікуються." #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "Порти ззаду" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "" "Виберіть одне призначення порту ззаду для кожного створюваного переднього " @@ -5058,39 +5103,30 @@ msgid "" "match the selected number of rear port positions ({rearport_count})." msgstr "" "Кількість шаблонів передніх портів, які потрібно створити " -"({frontport_count}) повинен відповідати вибраній кількості позицій портів " +"({frontport_count}) повинна відповідати вибраній кількості позицій портів " "ззаду ({rearport_count})." -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "" -"Струна {module} буде замінено позицією призначеного модуля, " -"якщо такий є." - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " "selected number of rear port positions ({rearport_count})." msgstr "" -"Кількість передніх портів, які потрібно створити ({frontport_count}) повинен" +"Кількість передніх портів, які потрібно створити ({frontport_count}) повинна" " відповідати вибраній кількості позицій портів ззаду ({rearport_count})." -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "Члени" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "Початкова позиція" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." @@ -5098,9 +5134,9 @@ msgstr "" "Положення пристрою першого члена. Збільшується на одного для кожного " "додаткового члена." -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." -msgstr "Посада повинна бути вказана для першого члена VC." +msgstr "Позиція повинна бути вказана для першого члена VC." #: netbox/dcim/models/cables.py:62 #: netbox/dcim/models/device_component_templates.py:55 @@ -5131,7 +5167,7 @@ msgstr "Необхідно вказати номер юніта при уста #: netbox/dcim/models/cables.py:168 msgid "Must define A and B terminations when creating a new cable." -msgstr "Необхідно визначити кінцівки А і Б при створенні нового кабелю." +msgstr "Необхідно визначити кінці А і Б при створенні нового кабелю." #: netbox/dcim/models/cables.py:175 msgid "Cannot connect different termination types to same end of cable." @@ -5152,11 +5188,11 @@ msgstr "кінець" #: netbox/dcim/models/cables.py:313 msgid "cable termination" -msgstr "кабельна кінцівка" +msgstr "кабельний кінець" #: netbox/dcim/models/cables.py:314 msgid "cable terminations" -msgstr "кабельні кінцівки" +msgstr "кабельні кінці" #: netbox/dcim/models/cables.py:333 #, python-brace-format @@ -5164,7 +5200,7 @@ msgid "" "Duplicate termination found for {app_label}.{model} {termination_id}: cable " "{cable_pk}" msgstr "" -"Знайдено дублікат кінцівки {app_label}.{model} {termination_id}: кабель " +"Знайдено дублікат кінця {app_label}.{model} {termination_id}: кабель " "{cable_pk}" #: netbox/dcim/models/cables.py:343 @@ -5271,7 +5307,7 @@ msgstr "шаблони портів живлення" msgid "Allocated draw cannot exceed the maximum draw ({maximum_draw}W)." msgstr "" "Виділена потужність не може перевищувати максимальну потужність " -"({maximum_draw}W)." +"({maximum_draw}Вт)." #: netbox/dcim/models/device_component_templates.py:347 #: netbox/dcim/models/device_components.py:477 @@ -5295,14 +5331,14 @@ msgstr "шаблони розеток" #, python-brace-format msgid "Parent power port ({power_port}) must belong to the same device type" msgstr "" -"Батьківський порт живлення ({power_port}) повинні належати до одного типу " +"Батьківський порт живлення ({power_port}) повинен належати до одного типу " "пристрою" #: netbox/dcim/models/device_component_templates.py:371 #, python-brace-format msgid "Parent power port ({power_port}) must belong to the same module type" msgstr "" -"Батьківський порт живлення ({power_port}) повинні належати до одного типу " +"Батьківський порт живлення ({power_port}) повинен належати до одного типу " "модуля" #: netbox/dcim/models/device_component_templates.py:423 @@ -5388,7 +5424,7 @@ msgstr "шаблони портів ззаду" #: netbox/dcim/models/device_component_templates.py:662 #: netbox/dcim/models/device_components.py:1103 msgid "position" -msgstr "позиції" +msgstr "позиція" #: netbox/dcim/models/device_component_templates.py:665 #: netbox/dcim/models/device_components.py:1106 @@ -5981,7 +6017,7 @@ msgstr "" #: netbox/dcim/models/devices.py:337 msgid "Child device types must be 0U." -msgstr "Дитячі типи пристроїв повинні бути висоту 0 юніт." +msgstr "Підпорядковані типи пристроїв повинні бути висоту 0 юніт." #: netbox/dcim/models/devices.py:411 msgid "module type" @@ -6036,15 +6072,15 @@ msgstr "позиція (юніт)" msgid "rack face" msgstr "лицева частина стійки" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" -msgstr "первинний IPv4" +msgstr "первинна адреса IPv4" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" -msgstr "первинний IPv6" +msgstr "первинна адреса IPv6" #: netbox/dcim/models/devices.py:686 msgid "out-of-band IP" @@ -6099,7 +6135,7 @@ msgstr "Стійка {rack} не належить до тех. майданчи #: netbox/dcim/models/devices.py:840 #, python-brace-format msgid "Location {location} does not belong to site {site}." -msgstr "Розташування {location} не належить до тех. майданчика{site}." +msgstr "Розташування {location} не належить до тех. майданчика {site}." #: netbox/dcim/models/devices.py:846 #, python-brace-format @@ -6170,7 +6206,7 @@ msgstr "Зазначена IP-адреса ({ip}) не призначаєтьс #: netbox/dcim/models/devices.py:937 #, python-brace-format msgid "{ip} is not an IPv6 address." -msgstr "{ip} Це не IPv6 адреса ." +msgstr "{ip} Це не IPv6 адреса." #: netbox/dcim/models/devices.py:964 #, python-brace-format @@ -6218,21 +6254,21 @@ msgstr "" "Модуль повинен бути встановлений у відсіку модуля, що належить призначеному " "пристрою ({device})." -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "домен" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "віртуальні шасі" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "Обраний майстер ({master}) не присвоюється цьому віртуальному шасі." -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " @@ -6241,34 +6277,34 @@ msgstr "" "Неможливо видалити віртуальне шасі {self}. Існують мережеві інтерфейси, які " "утворюють інтерфейси LAG між шасі." -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "ідентифікатор" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "Числовий ідентифікатор, унікальний для батьківського пристрою" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "коментарі" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "контекст віртуального пристрою" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "контексти віртуальних пристроїв" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." -msgstr "{ip} не є IPv{family} адресой." +msgstr "{ip} не є IPv{family} адресою." -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "" "Первинна IP-адреса повинна належати інтерфейсу на призначеному пристрої." @@ -6459,7 +6495,7 @@ msgstr "Локально призначений ідентифікатор" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "Функціональна роль" @@ -6521,7 +6557,8 @@ msgstr "бронювання стійки" #: netbox/dcim/models/racks.py:714 #, python-brace-format msgid "Invalid unit(s) for {height}U rack: {unit_list}" -msgstr "Недійсне монтажне місце для стійки висотою{height}юнітів: {unit_list}" +msgstr "" +"Недійсне монтажне місце для стійки висотою {height} юнітів: {unit_list}" #: netbox/dcim/models/racks.py:727 #, python-brace-format @@ -6534,7 +6571,7 @@ msgstr "Регіон верхнього рівня з такою назвою в #: netbox/dcim/models/sites.py:59 msgid "A top-level region with this slug already exists." -msgstr "Регіон верхнього рівня з цим слимаком вже існує." +msgstr "Регіон верхнього рівня з цим скореченням вже існує." #: netbox/dcim/models/sites.py:62 msgid "region" @@ -6550,7 +6587,7 @@ msgstr "Група тех. майданчиків верхнього рівня #: netbox/dcim/models/sites.py:112 msgid "A top-level site group with this slug already exists." -msgstr "Група тех. майданчиків верхнього рівня з цим слимаком вже існує." +msgstr "Група тех. майданчиків верхнього рівня з цим скореченням вже існує." #: netbox/dcim/models/sites.py:115 msgid "site group" @@ -6624,11 +6661,11 @@ msgstr "" #: netbox/dcim/tables/cables.py:55 msgid "Termination A" -msgstr "Припинення А" +msgstr "Кінець А" #: netbox/dcim/tables/cables.py:60 msgid "Termination B" -msgstr "Припинення Б" +msgstr "Кінець Б" #: netbox/dcim/tables/cables.py:66 netbox/wireless/tables/wirelesslink.py:23 msgid "Device A" @@ -6675,14 +6712,14 @@ msgstr "Доступний" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "Пристрої" #: netbox/dcim/tables/devices.py:63 netbox/dcim/tables/devices.py:111 #: netbox/virtualization/tables/clusters.py:88 msgid "VMs" -msgstr "віртуальні машини" +msgstr "Віртуальні машини" #: netbox/dcim/tables/devices.py:100 netbox/dcim/tables/devices.py:216 #: netbox/extras/forms/model_forms.py:630 @@ -6704,8 +6741,8 @@ msgid "Site Group" msgstr "Група тех. майданчиків" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6756,20 +6793,20 @@ msgid "Power outlets" msgstr "Розетки" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "Інтерфейси" @@ -6795,8 +6832,8 @@ msgid "Module Bay" msgstr "Резервуар модулів" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6819,13 +6856,13 @@ msgstr "Позначене підключення" #: netbox/dcim/tables/devices.py:461 msgid "Maximum draw (W)" -msgstr "Максимальна потужність (W)" +msgstr "Максимальна потужність (Вт)" #: netbox/dcim/tables/devices.py:464 msgid "Allocated draw (W)" -msgstr "Виділена потужність (W)" +msgstr "Виділена потужність (Вт)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6860,7 +6897,7 @@ msgstr "Тільки управління" #: netbox/dcim/tables/devices.py:623 msgid "VDCs" -msgstr "Джерела живлення постійного струму " +msgstr "Джерела живлення постійного струму" #: netbox/dcim/tables/devices.py:873 netbox/templates/dcim/modulebay.html:53 msgid "Installed Module" @@ -6868,7 +6905,7 @@ msgstr "Встановлений модуль" #: netbox/dcim/tables/devices.py:876 msgid "Module Serial" -msgstr "Послідовний модуль " +msgstr "Послідовний модуль" #: netbox/dcim/tables/devices.py:880 msgid "Module Asset Tag" @@ -6914,94 +6951,94 @@ msgstr "Повна глибина" #: netbox/dcim/tables/devicetypes.py:98 msgid "U Height" -msgstr "Висота юніта" +msgstr "Висота юніта(U)" #: netbox/dcim/tables/devicetypes.py:113 netbox/dcim/tables/modules.py:26 #: netbox/dcim/tables/racks.py:89 msgid "Instances" msgstr "Екземпляри" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Консольні порти" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Порти консольного сервера" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "Порти живлення" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "Розетки" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "Передні порти" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "Задні порти" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "Відсіки для пристроїв" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "Модульні відсіки" @@ -7050,7 +7087,7 @@ msgstr "Простір" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -7060,30 +7097,30 @@ msgstr "Тех. майданчики" msgid "Test case must set peer_termination_type" msgstr "Тестовий випадок повинен встановити peer_termination_type" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "Відключено {count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "Бронювання" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "Пристрої без можливості кріплення у стійку" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "Контекст конфігурації" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" -msgstr "Відтворювати конфігурацію" +msgstr "Відтворення конфігурації" #: netbox/dcim/views.py:2131 netbox/virtualization/views.py:450 #, python-brace-format @@ -7092,35 +7129,35 @@ msgstr "Під час візуалізації шаблону сталася п #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "Віртуальні машини" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "Встановлений пристрій {device} в бухті {device_bay}." -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "Видалений пристрій {device} з бухти {device_bay}." -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "Підпорядкований" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "Доданий член {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "Неможливо видалити головний пристрій {device} від віртуального шасі." -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "Вилучено {device} з віртуального шасі {chassis}" @@ -7157,7 +7194,7 @@ msgstr "Десяткове число" #: netbox/extras/choices.py:34 msgid "Boolean (true/false)" -msgstr "Булевий тип (істинна/хибна)" +msgstr "Булевий тип (правда/неправда)" #: netbox/extras/choices.py:35 msgid "Date" @@ -7303,7 +7340,6 @@ msgstr "Оновити" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -7480,7 +7516,7 @@ msgstr "Відображення довільного списку об'єкті #: netbox/extras/dashboard/widgets.py:222 msgid "The default number of objects to display" -msgstr "Типова кількість об'єктів для відображення" +msgstr "Кількість об'єктів за замовченням для відображення" #: netbox/extras/dashboard/widgets.py:234 msgid "Invalid format. URL parameters must be passed as a dictionary." @@ -7550,7 +7586,7 @@ msgstr "Тип кластера" #: netbox/extras/filtersets.py:580 netbox/virtualization/filtersets.py:95 #: netbox/virtualization/filtersets.py:147 msgid "Cluster type (slug)" -msgstr "Кластерний тип (скоречення)" +msgstr "Кластерний тип (скорочення)" #: netbox/extras/filtersets.py:601 netbox/tenancy/forms/forms.py:16 #: netbox/tenancy/forms/forms.py:39 @@ -7560,7 +7596,7 @@ msgstr "Група орендарів" #: netbox/extras/filtersets.py:607 netbox/tenancy/filtersets.py:188 #: netbox/tenancy/filtersets.py:208 msgid "Tenant group (slug)" -msgstr "Група орендарів (скоречення)" +msgstr "Група орендарів (скорочення)" #: netbox/extras/filtersets.py:623 netbox/extras/forms/model_forms.py:495 #: netbox/templates/extras/tag.html:11 @@ -7569,7 +7605,7 @@ msgstr "Мітка" #: netbox/extras/filtersets.py:629 msgid "Tag (slug)" -msgstr "Мітка (скоречення)" +msgstr "Мітка (скорочення)" #: netbox/extras/filtersets.py:689 netbox/extras/forms/filtersets.py:429 msgid "Has local config context data" @@ -7600,7 +7636,7 @@ msgstr "Видимий інтерфейс користувача" #: netbox/extras/forms/filtersets.py:94 #: netbox/extras/models/customfields.py:216 msgid "UI editable" -msgstr "Редагований інтерфейс користувача " +msgstr "Редагований інтерфейс користувача" #: netbox/extras/forms/bulk_edit.py:71 netbox/extras/forms/filtersets.py:97 msgid "Is cloneable" @@ -7654,7 +7690,7 @@ msgstr "Спільний" #: netbox/extras/forms/bulk_edit.py:215 netbox/extras/forms/filtersets.py:265 #: netbox/extras/models/models.py:174 msgid "HTTP method" -msgstr "метод HTTP" +msgstr "Метод HTTP" #: netbox/extras/forms/bulk_edit.py:219 netbox/extras/forms/filtersets.py:259 #: netbox/templates/extras/webhook.html:30 @@ -7751,7 +7787,8 @@ msgid "" "separated by colon: \"choice1:First Choice,choice2:Second Choice\"" msgstr "" "Цитуючий рядок параметрів полів, розділених комами, з необов'язковими " -"мітками, розділеними двокрапкою: «Вибір1:Перший вибір, Вибір2:другий вибір»" +"мітками, розділеними двокрапкою: \"Вибір1:Перший вибір, Вибір2:другий " +"вибір\"" #: netbox/extras/forms/bulk_import.py:123 netbox/extras/models/models.py:323 msgid "button class" @@ -8008,7 +8045,7 @@ msgstr "Код шаблону" #: netbox/extras/forms/model_forms.py:247 #: netbox/templates/extras/exporttemplate.html:12 msgid "Export Template" -msgstr "Шаблон експорту" +msgstr "Експортувати шаблон" #: netbox/extras/forms/model_forms.py:249 msgid "Rendering" @@ -8132,19 +8169,19 @@ msgstr "Заплануйте виконання сценарію до встан msgid "Interval at which this script is re-run (in minutes)" msgstr "Інтервал повторного запуску сценарію (у хвилині)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "Зміни бази даних були автоматично скасовані." -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "Скрипт перерваний з помилкою: " -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "Виняток стався: " -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "Зміни бази даних були скасовані через помилку." @@ -8406,7 +8443,7 @@ msgstr "Поля виділення повинні вказувати набір #: netbox/extras/models/customfields.py:368 msgid "Choices may be set only on selection fields." -msgstr "Вибір можна встановити лише для полів виділення." +msgstr "Вибір можна встановити лише для виділених полів." #: netbox/extras/models/customfields.py:375 msgid "Object fields must define an object type." @@ -8743,7 +8780,7 @@ msgstr "" #: netbox/extras/models/models.py:410 msgid "Defaults to text/plain; charset=utf-8" -msgstr "За замовчуванням текст/простий; набір символів = utf-8" +msgstr "За замовчуванням text/plain; charset=utf-8" #: netbox/extras/models/models.py:413 msgid "file extension" @@ -8897,7 +8934,7 @@ msgstr "підписки" #: netbox/extras/models/scripts.py:42 msgid "is executable" -msgstr "виконуваний" +msgstr "є виконуваним" #: netbox/extras/models/scripts.py:64 msgid "script" @@ -8941,7 +8978,7 @@ msgstr "гілка" #: netbox/extras/models/staging.py:45 msgid "branches" -msgstr "відділення" +msgstr "гілки" #: netbox/extras/models/staging.py:97 msgid "staged change" @@ -9031,7 +9068,7 @@ msgstr "Максимальне значення" #: netbox/extras/tables/tables.py:104 msgid "Validation Regex" -msgstr "Перевірка регулярного вираза " +msgstr "Перевірка регулярного вираза" #: netbox/extras/tables/tables.py:137 msgid "Count" @@ -9170,7 +9207,7 @@ msgstr "Видалений віджет: " msgid "Error deleting widget: " msgstr "Помилка при видаленні віджета: " -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "Неможливо запустити скрипт: робочий процес RQ не запущений." @@ -9185,7 +9222,8 @@ msgstr "Невірний формат IP-адреси: {data}" #: netbox/ipam/api/field_serializers.py:37 msgid "Enter a valid IPv4 or IPv6 prefix and mask in CIDR notation." -msgstr "Введіть дійсний префікс IPv4 або IPv6 та маску в позначенні CIDR." +msgstr "" +"Введіть дійсний мережевий префікс IPv4 або IPv6 та маску в позначенні CIDR." #: netbox/ipam/api/field_serializers.py:44 #, python-brace-format @@ -9207,11 +9245,11 @@ msgstr "DHCP" #: netbox/ipam/choices.py:73 msgid "SLAAC" -msgstr "СЛААК" +msgstr "SLAAC" #: netbox/ipam/choices.py:89 msgid "Loopback" -msgstr "Петлебек" +msgstr "Loopback" #: netbox/ipam/choices.py:91 msgid "Anycast" @@ -9300,22 +9338,22 @@ msgstr "RIR (ідентифікатор)" #: netbox/ipam/filtersets.py:165 netbox/ipam/filtersets.py:204 #: netbox/ipam/filtersets.py:227 msgid "RIR (slug)" -msgstr "RIR (скоречення)" +msgstr "RIR (скорочення)" #: netbox/ipam/filtersets.py:285 msgid "Within prefix" -msgstr "Всередині префікса" +msgstr "У межах префікса" #: netbox/ipam/filtersets.py:289 msgid "Within and including prefix" -msgstr "Всередині та включаючи префікс" +msgstr "У межах та включаючи префікс" #: netbox/ipam/filtersets.py:293 msgid "Prefixes which contain this prefix or IP" msgstr "Мережеві префікси, які містять цей префікс або IP" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "Довжина маски" @@ -9329,7 +9367,7 @@ msgid "VLAN number (1-4094)" msgstr "Номер VLAN (1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9386,7 +9424,7 @@ msgstr "Сервіс (ідентифікатор)" #: netbox/ipam/filtersets.py:673 msgid "NAT inside IP address (ID)" -msgstr "NAT всередині IP-адреси (ідентифікатор)" +msgstr "NAT внутрішня IP-адреса (ідентифікатор)" #: netbox/ipam/filtersets.py:1041 netbox/ipam/forms/bulk_import.py:322 msgid "Assigned interface" @@ -9406,11 +9444,11 @@ msgstr "IP-адреса" #: netbox/ipam/filtersets.py:1167 msgid "Primary IPv4 (ID)" -msgstr "Первинний IPv4 (ідентифікатор)" +msgstr "Первинна адреса IPv4 (ідентифікатор)" #: netbox/ipam/filtersets.py:1172 msgid "Primary IPv6 (ID)" -msgstr "Первинний IPv6 (ідентифікатор)" +msgstr "Первинна адреса IPv6 (ідентифікатор)" #: netbox/ipam/formfields.py:14 msgid "Enter a valid IPv4 or IPv6 address (without a mask)." @@ -9441,16 +9479,16 @@ msgstr "Потрібна маска CIDR (наприклад, /24)." msgid "Address pattern" msgstr "Адресний шаблон" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" -msgstr "Забезпечте унікальний простір" +msgstr "Забезпечте унікальність простору" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "Є приватним" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9462,22 +9500,22 @@ msgstr "Є приватним" #: netbox/templates/ipam/asn.html:27 netbox/templates/ipam/asnrange.html:19 #: netbox/templates/ipam/rir.html:19 msgid "RIR" -msgstr "ЗРИГНУТИ" +msgstr "RIR" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "Дата додавання" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "Група VLAN" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9490,32 +9528,32 @@ msgstr "Група VLAN" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "Довжина префікса" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" -msgstr "Чи є басейн" +msgstr "Чи є пулом" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" -msgstr "Ставтеся до повного використання" +msgstr "Вважати повністю використаним" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "Призначення VLAN" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "Ім'я DNS" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9523,12 +9561,12 @@ msgstr "Ім'я DNS" msgid "Protocol" msgstr "Протокол" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "Ідентифікатор групи" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9540,12 +9578,12 @@ msgstr "Ідентифікатор групи" msgid "Authentication type" msgstr "Тип аутентифікації" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "Ключ аутентифікації" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9557,26 +9595,26 @@ msgstr "Ключ аутентифікації" msgid "Authentication" msgstr "Аутентифікація" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "Тип сфери застосування" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "Діапазони ідентифікаторів VLAN" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "Сфера застосування" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "Діапазони ідентифікаторів VLAN" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "Тех. майданчик і група" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9584,11 +9622,11 @@ msgstr "Порти" #: netbox/ipam/forms/bulk_import.py:48 msgid "Import route targets" -msgstr "Імпортувати цілі маршруту" +msgstr "Імпортувати маршрути до цілей" #: netbox/ipam/forms/bulk_import.py:54 msgid "Export route targets" -msgstr "Експортувати цілі маршруту" +msgstr "Експортувати маршрути до цілей" #: netbox/ipam/forms/bulk_import.py:92 netbox/ipam/forms/bulk_import.py:112 #: netbox/ipam/forms/bulk_import.py:132 @@ -9597,14 +9635,14 @@ msgstr "Призначений RIR" #: netbox/ipam/forms/bulk_import.py:182 msgid "VLAN's group (if any)" -msgstr "Група VLAN (якщо така є)" +msgstr "Група VLAN'ів (якщо така є)" #: netbox/ipam/forms/bulk_import.py:308 msgid "Parent device of assigned interface (if any)" msgstr "Батьківський пристрій призначеного інтерфейсу (якщо є)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9630,41 +9668,61 @@ msgstr "Є первинним" msgid "Make this the primary IP for the assigned device" msgstr "Зробіть це основним IP для призначеного пристрою" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "" -"Пристрій або віртуальна машина не вказано; неможливо встановити як основний " -"IP" +"Пристрій або віртуальна машина не вказано; неможливо встановити як первинний" +" IP" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" -msgstr "Інтерфейс не вказано; неможливо встановити як основний IP" +msgstr "Інтерфейс не вказано; неможливо встановити як первинний IP" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "Тип авторизації" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "Тип сфери застосування (додаток і модель)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "Призначена група VLAN" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "протокол IP" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" -msgstr "Необхідний, якщо він не призначений для віртуальної машини" +msgstr "Необхідний, якщо він не був призначений для віртуальної машини" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" -msgstr "Обов'язково, якщо пристрій не призначений" +msgstr "Обов'язково, якщо він не був призначений для пристрою" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} не призначається цьому пристрою/віртуальній машині." @@ -9672,7 +9730,7 @@ msgstr "{ip} не призначається цьому пристрою/вір #: netbox/ipam/forms/filtersets.py:47 netbox/ipam/forms/model_forms.py:63 #: netbox/netbox/navigation/menu.py:189 netbox/vpn/forms/model_forms.py:410 msgid "Route Targets" -msgstr "Маршрутні цілі" +msgstr "Маршрути до цілей" #: netbox/ipam/forms/filtersets.py:53 netbox/ipam/forms/model_forms.py:50 #: netbox/vpn/forms/filtersets.py:224 netbox/vpn/forms/model_forms.py:397 @@ -9682,15 +9740,15 @@ msgstr "Імпортувати цілі" #: netbox/ipam/forms/filtersets.py:58 netbox/ipam/forms/model_forms.py:55 #: netbox/vpn/forms/filtersets.py:229 netbox/vpn/forms/model_forms.py:402 msgid "Export targets" -msgstr "Експортні цілі" +msgstr "Експортувати цілі" #: netbox/ipam/forms/filtersets.py:73 msgid "Imported by VRF" -msgstr "Імпортований VRF" +msgstr "Імпортований до VRF" #: netbox/ipam/forms/filtersets.py:78 msgid "Exported by VRF" -msgstr "Експортується VRF" +msgstr "Експортувати з VRF" #: netbox/ipam/forms/filtersets.py:87 netbox/ipam/tables/ip.py:89 #: netbox/templates/ipam/rir.html:30 @@ -9700,7 +9758,7 @@ msgstr "Приватний" #: netbox/ipam/forms/filtersets.py:105 netbox/ipam/forms/filtersets.py:191 #: netbox/ipam/forms/filtersets.py:272 netbox/ipam/forms/filtersets.py:326 msgid "Address family" -msgstr "Адреса сім'ї" +msgstr "Сімейство адрес" #: netbox/ipam/forms/filtersets.py:119 netbox/templates/ipam/asnrange.html:25 msgid "Range" @@ -9716,7 +9774,7 @@ msgstr "Кінець" #: netbox/ipam/forms/filtersets.py:186 msgid "Search within" -msgstr "Пошук всередині" +msgstr "Пошук в межах" #: netbox/ipam/forms/filtersets.py:207 netbox/ipam/forms/filtersets.py:342 msgid "Present in VRF" @@ -9732,38 +9790,38 @@ msgstr "Батьківський префікс" #: netbox/ipam/forms/filtersets.py:347 msgid "Assigned Device" -msgstr "Призначений пристрій" +msgstr "Призначено на пристрій" #: netbox/ipam/forms/filtersets.py:352 msgid "Assigned VM" -msgstr "Призначена віртуальна машина" +msgstr "Призначено на віртуальну машину" #: netbox/ipam/forms/filtersets.py:366 msgid "Assigned to an interface" -msgstr "Призначено до інтерфейсу" +msgstr "Призначено на інтерфейс" #: netbox/ipam/forms/filtersets.py:373 netbox/templates/ipam/ipaddress.html:51 msgid "DNS Name" msgstr "Ім'я DNS" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 msgid "VLANs" -msgstr "VLANs" +msgstr "VLAN'и" #: netbox/ipam/forms/filtersets.py:457 msgid "Contains VLAN ID" msgstr "Містить ідентифікатор VLAN" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" -msgstr "ІДЕНТИФІКАТОР VLAN" +msgstr "Ідентифікатор VLAN" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9774,7 +9832,7 @@ msgstr "ІДЕНТИФІКАТОР VLAN" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9783,7 +9841,7 @@ msgstr "Віртуальна машина" #: netbox/ipam/forms/model_forms.py:80 #: netbox/templates/ipam/routetarget.html:10 msgid "Route Target" -msgstr "Мета маршруту" +msgstr "Маршрут до цілі" #: netbox/ipam/forms/model_forms.py:114 netbox/ipam/tables/ip.py:117 #: netbox/templates/ipam/aggregate.html:11 @@ -9803,8 +9861,8 @@ msgstr "Призначення тех. майданчику/VLAN" msgid "IP Range" msgstr "Діапазон IP" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "Група FHRP/VRRP" @@ -9813,47 +9871,57 @@ msgstr "Група FHRP/VRRP" msgid "Make this the primary IP for the device/VM" msgstr "Зробіть це основним IP для пристрою/віртуальної машини" -#: netbox/ipam/forms/model_forms.py:325 -msgid "NAT IP (Inside)" -msgstr "NAT IP (всередині)" +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:329 +msgid "NAT IP (Inside)" +msgstr "NAT IP (внутрішній)" + +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "IP-адреса може бути призначена лише одному об'єкту." -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" msgstr "" -"Не вдається перепризначити IP-адресу, поки вона призначена як основний IP " -"для батьківського об'єкта" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "" -"Тільки IP-адреси, призначені інтерфейсу, можуть бути визначені основними IP-" -"адресами." +"Тільки IP-адреси, призначені інтерфейсу, можуть бути визначені первинними " +"IP-адресами." -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "Віртуальна IP-адреса" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "Призначення вже існує" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "Ідентифікатори VLAN" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" -msgstr "Дитячі VLAN" +msgstr "Підпорядковані VLAN'и" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." @@ -9861,38 +9929,38 @@ msgstr "" "Список одного або декількох номерів портів, розділених комами. Діапазон " "можна вказати за допомогою дефіса." -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "Шаблон сервісу" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "Порт (и)" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "Сервіс" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "Шаблон сервісу" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "З шаблону" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "Користувацький" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "" -"Необхідно вказати ім'я, протокол та порт (и), якщо не використовується " -"шаблон служби." +"Необхідно вказати ім'я, протокол та порт(и), якщо не використовується шаблон" +" служби." #: netbox/ipam/models/asns.py:34 msgid "start" @@ -9909,11 +9977,11 @@ msgstr "Діапазони ASN" #: netbox/ipam/models/asns.py:72 #, python-brace-format msgid "Starting ASN ({start}) must be lower than ending ASN ({end})." -msgstr "Запуск ASN ({start}) повинен бути нижчим за кінцевий ASN ({end})." +msgstr "Початковий ASN ({start}) повинен бути нижчим за кінцевий ASN ({end})." #: netbox/ipam/models/asns.py:104 msgid "Regional Internet Registry responsible for this AS number space" -msgstr "Регіональний інтернет-реєстр, відповідальний за цей номер AS" +msgstr "Регіональний інтернет-реєстр(RIR), відповідальний за цей номер AS" #: netbox/ipam/models/asns.py:109 msgid "16- or 32-bit autonomous system number" @@ -9921,7 +9989,7 @@ msgstr "16- або 32-розрядний номер автономної сис #: netbox/ipam/models/fhrp.py:22 msgid "group ID" -msgstr "Ідентифікатор групи" +msgstr "ідентифікатор групи" #: netbox/ipam/models/fhrp.py:30 netbox/ipam/models/services.py:22 msgid "protocol" @@ -9961,7 +10029,7 @@ msgstr "Простір IP, керований цим RIR, вважається #: netbox/ipam/models/ip.py:72 netbox/netbox/navigation/menu.py:182 msgid "RIRs" -msgstr "RIR" +msgstr "RIRи" #: netbox/ipam/models/ip.py:84 msgid "IPv4 or IPv6 network" @@ -9969,7 +10037,7 @@ msgstr "Мережа IPv4 або IPv6" #: netbox/ipam/models/ip.py:91 msgid "Regional Internet Registry responsible for this IP space" -msgstr "Регіональний Інтернет-реєстр, відповідальний за цей IP-простір" +msgstr "Регіональний Інтернет-реєстр(RIR), відповідальний за цей IP-простір" #: netbox/ipam/models/ip.py:101 msgid "date added" @@ -9981,11 +10049,11 @@ msgstr "сукупний" #: netbox/ipam/models/ip.py:116 msgid "aggregates" -msgstr "агреговані мережі" +msgstr "сукупні мережі" #: netbox/ipam/models/ip.py:132 msgid "Cannot create aggregate with /0 mask." -msgstr "Не вдається створити агрегат з маскою /0." +msgstr "Не вдається створити сукупну мережу з маскою /0." #: netbox/ipam/models/ip.py:144 #, python-brace-format @@ -9993,8 +10061,8 @@ msgid "" "Aggregates cannot overlap. {prefix} is already covered by an existing " "aggregate ({aggregate})." msgstr "" -"Агрегати не можуть перекриватися. {prefix} вже покривається існуючим " -"агрегатом ({aggregate})." +"Сукупні мережі не можуть перекриватися. {prefix} вже покривається існуючим " +"сукупною мережею ({aggregate})." #: netbox/ipam/models/ip.py:158 #, python-brace-format @@ -10002,8 +10070,8 @@ msgid "" "Prefixes cannot overlap aggregates. {prefix} covers an existing aggregate " "({aggregate})." msgstr "" -"Мережеві префікси не можуть перекривати агрегати. {prefix} охоплює існуючий " -"агрегат ({aggregate})." +"Мережеві префікси не можуть перекривати сукупні мережі. {prefix} охоплює " +"існуючий сукупну мережу ({aggregate})." #: netbox/ipam/models/ip.py:200 netbox/ipam/models/ip.py:737 #: netbox/vpn/models/tunnels.py:114 @@ -10032,7 +10100,7 @@ msgstr "Основна функція цього префікса" #: netbox/ipam/models/ip.py:265 msgid "is a pool" -msgstr "є басейном" +msgstr "є у пулі" #: netbox/ipam/models/ip.py:267 msgid "All IP addresses within this prefix are considered usable" @@ -10053,7 +10121,7 @@ msgstr "Неможливо створити префікс з маскою /0." #: netbox/ipam/models/ip.py:324 netbox/ipam/models/ip.py:874 #, python-brace-format msgid "VRF {vrf}" -msgstr "ВРФ {vrf}" +msgstr "VRF {vrf}" #: netbox/ipam/models/ip.py:324 netbox/ipam/models/ip.py:874 msgid "global table" @@ -10112,7 +10180,7 @@ msgstr "" #, python-brace-format msgid "Defined addresses overlap with range {overlapping_range} in VRF {vrf}" msgstr "" -"Визначені адреси перекриваються з діапазоном {overlapping_range} в ВРФ {vrf}" +"Визначені адреси перекриваються з діапазоном {overlapping_range} в VRF {vrf}" #: netbox/ipam/models/ip.py:599 #, python-brace-format @@ -10126,19 +10194,19 @@ msgstr "адреса" #: netbox/ipam/models/ip.py:734 msgid "The operational status of this IP" -msgstr "Операційний стан цього ІП" +msgstr "Операційний стан цього IP" #: netbox/ipam/models/ip.py:741 msgid "The functional role of this IP" -msgstr "Функціональна роль цього ІП" +msgstr "Функціональна роль цього IP" #: netbox/ipam/models/ip.py:765 netbox/templates/ipam/ipaddress.html:72 msgid "NAT (inside)" -msgstr "NAT (всередині)" +msgstr "NAT (внутрішній)" #: netbox/ipam/models/ip.py:766 msgid "The IP for which this address is the \"outside\" IP" -msgstr "IP, для якого ця адреса є \"зовнішнім\" IP" +msgstr "IP, для якого ця адреса є \"зовнішньою\"" #: netbox/ipam/models/ip.py:773 msgid "Hostname or FQDN (not case-sensitive)" @@ -10162,13 +10230,21 @@ msgstr "" #, python-brace-format msgid "" "{ip} is a broadcast address, which may not be assigned to an interface." -msgstr "{ip} це адреса трансляції, яка може не бути присвоєна інтерфейсу." +msgstr "{ip} це широкомовна адреса, яка може не бути присвоєна інтерфейсу." #: netbox/ipam/models/ip.py:876 #, python-brace-format msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "Дублікати IP-адреси знайдено в {table}: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "" +"Не вдається перепризначити IP-адресу, поки вона призначена як первинний IP " +"для батьківського об'єкта" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "Статус SLAAC може бути призначений лише адресам IPv6" @@ -10221,40 +10297,54 @@ msgstr "Не вдається встановити scope_type без scope_id." msgid "Cannot set scope_id without scope_type." msgstr "Не вдається встановити scope_id без scope_type." -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" +"Початковий ідентифікатор VLAN в діапазоні ({value}) не може бути менше " +"{minimum}" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" +"Кінцевий ідентифікатор VLAN в діапазоні ({value}) не може перевищувати " +"{maximum}" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" +"Кінцевий ідентифікатор VLAN в діапазоні повинен бути більшим або дорівнювати" +" початковому ідентифікатору VLAN ({range})" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "Діапазони не можуть перекриватися." -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "" -"Максимальний підпорядкований VID повинен бути більшим або дорівнює " -"мінімальному підпорядкований VID ({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "Конкретний тех. майданчик, якому присвоєно цей VLAN (якщо такий є)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "Група VLAN (необов'язково)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "Числовий ідентифікатор VLAN (1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "Операційний стан цього VLAN" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "Основна функція цього VLAN" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " @@ -10263,18 +10353,19 @@ msgstr "" "VLAN присвоюється групі {group} (сфера застосування: {scope}); також не може" " призначатися до тех. майданчику {site}." -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" -msgstr "VID повинен знаходитися в діапазоні {ranges} для VLAN в групі {group}" +msgstr "" +"VID повинен знаходитися в діапазоні {ranges} для VLAN'ів у групі {group}" #: netbox/ipam/models/vrfs.py:30 msgid "route distinguisher" -msgstr "розрізнювач маршруту" +msgstr "розрізнювач маршруту (RD)" #: netbox/ipam/models/vrfs.py:31 msgid "Unique route distinguisher (as defined in RFC 4364)" -msgstr "Унікальний розрізнювач маршруту (як визначено в RFC 4364)" +msgstr "Унікальний розрізнювач маршруту (RD) (як визначено в RFC 4364)" #: netbox/ipam/models/vrfs.py:42 msgid "enforce unique space" @@ -10287,7 +10378,7 @@ msgstr "Запобігання дублікуванню префіксів/IP-а #: netbox/ipam/models/vrfs.py:63 netbox/netbox/navigation/menu.py:186 #: netbox/netbox/navigation/menu.py:188 msgid "VRFs" -msgstr "VRF" +msgstr "VRFи" #: netbox/ipam/models/vrfs.py:82 msgid "Route target value (formatted in accordance with RFC 4360)" @@ -10295,15 +10386,15 @@ msgstr "Цільове значення маршруту (відформатов #: netbox/ipam/models/vrfs.py:94 msgid "route target" -msgstr "цільовий маршрут" +msgstr "маршрут до цілі" #: netbox/ipam/models/vrfs.py:95 msgid "route targets" -msgstr "маршрутні цілі" +msgstr "маршрут до цілей" #: netbox/ipam/tables/asn.py:52 msgid "ASDOT" -msgstr "АСДОТ" +msgstr "ASDOT" #: netbox/ipam/tables/asn.py:57 msgid "Site Count" @@ -10316,7 +10407,7 @@ msgstr "Кількість провайдерів" #: netbox/ipam/tables/ip.py:95 netbox/netbox/navigation/menu.py:179 #: netbox/netbox/navigation/menu.py:181 msgid "Aggregates" -msgstr "Агрегати" +msgstr "Сукупні мережі" #: netbox/ipam/tables/ip.py:125 msgid "Added" @@ -10351,11 +10442,11 @@ msgstr "Глибина" #: netbox/ipam/tables/ip.py:262 msgid "Pool" -msgstr "Басейн" +msgstr "Пул" #: netbox/ipam/tables/ip.py:266 netbox/ipam/tables/ip.py:320 msgid "Marked Utilized" -msgstr "Позначений Використовуваний" +msgstr "Позначено як використане" #: netbox/ipam/tables/ip.py:304 msgid "Start address" @@ -10363,15 +10454,15 @@ msgstr "Початкова адреса" #: netbox/ipam/tables/ip.py:383 msgid "NAT (Inside)" -msgstr "NAT (всередині)" +msgstr "NAT (внутрішній)" #: netbox/ipam/tables/ip.py:388 msgid "NAT (Outside)" -msgstr "NAT (зовні)" +msgstr "NAT (зовнішній)" #: netbox/ipam/tables/ip.py:393 msgid "Assigned" -msgstr "Призначено" +msgstr "Призначений" #: netbox/ipam/tables/ip.py:429 netbox/templates/vpn/l2vpntermination.html:16 #: netbox/vpn/forms/filtersets.py:240 @@ -10389,11 +10480,11 @@ msgstr "Діапазони VID" #: netbox/ipam/tables/vlans.py:111 netbox/ipam/tables/vlans.py:214 #: netbox/templates/dcim/inc/interface_vlans_table.html:4 msgid "VID" -msgstr "ВИД" +msgstr "VID" #: netbox/ipam/tables/vrfs.py:30 msgid "RD" -msgstr "Р-Н" +msgstr "RD" #: netbox/ipam/tables/vrfs.py:33 msgid "Unique" @@ -10405,7 +10496,7 @@ msgstr "Імпортувати цілі" #: netbox/ipam/tables/vrfs.py:42 netbox/vpn/tables/l2vpn.py:32 msgid "Export Targets" -msgstr "Експортні цілі" +msgstr "Експортувати цілі" #: netbox/ipam/validators.py:9 #, python-brace-format @@ -10415,12 +10506,12 @@ msgstr "{prefix} не є дійсним префіксом. Ви мали на #: netbox/ipam/validators.py:16 #, python-format msgid "The prefix length must be less than or equal to %(limit_value)s." -msgstr "Довжина префікса повинна бути менше або дорівнює %(limit_value)s." +msgstr "Довжина префікса повинна бути менше або дорівнює %(limit_value)sи." #: netbox/ipam/validators.py:24 #, python-format msgid "The prefix length must be greater than or equal to %(limit_value)s." -msgstr "Довжина префікса повинна бути більше або дорівнює %(limit_value)s." +msgstr "Довжина префікса повинна бути більше або дорівнює %(limit_value)sи." #: netbox/ipam/validators.py:33 msgid "" @@ -10436,7 +10527,7 @@ msgstr "Підпорядковані мережеві префікси" #: netbox/ipam/views.py:569 msgid "Child Ranges" -msgstr "Дитячі діапазони" +msgstr "Підпорядковані діапазони" #: netbox/ipam/views.py:898 msgid "Related IPs" @@ -10444,7 +10535,7 @@ msgstr "Пов'язані IP-адреси" #: netbox/ipam/views.py:1127 msgid "Device Interfaces" -msgstr "Інтерфейси пристроїв" +msgstr "Інтерфейси пристрою" #: netbox/ipam/views.py:1145 msgid "VM Interfaces" @@ -10478,7 +10569,7 @@ msgstr "Невірне значення. Вкажіть тип вмісту як #: netbox/netbox/api/fields.py:167 msgid "Ranges must be specified in the form (lower, upper)." -msgstr "Діапазони повинні бути вказані в формі (нижній, верхній)." +msgstr "Діапазони повинні бути вказані у форматі (нижня межа, верхня межа)." #: netbox/netbox/api/fields.py:169 msgid "Range boundaries must be defined as integers." @@ -10500,11 +10591,11 @@ msgstr "Темно-червоний" #: netbox/netbox/choices.py:52 msgid "Rose" -msgstr "Роза" +msgstr "Трояндовий" #: netbox/netbox/choices.py:53 msgid "Fuchsia" -msgstr "Фуксія" +msgstr "Малиновий" #: netbox/netbox/choices.py:55 msgid "Dark Purple" @@ -10516,7 +10607,7 @@ msgstr "Світло-блакитний" #: netbox/netbox/choices.py:61 msgid "Aqua" -msgstr "Аква" +msgstr "Бирюзовый" #: netbox/netbox/choices.py:62 msgid "Dark Green" @@ -10528,11 +10619,11 @@ msgstr "Світло-зелений" #: netbox/netbox/choices.py:65 msgid "Lime" -msgstr "Лайм" +msgstr "Кислотно-зелений" #: netbox/netbox/choices.py:67 msgid "Amber" -msgstr "Бурштин" +msgstr "Бурштиновий" #: netbox/netbox/choices.py:69 msgid "Dark Orange" @@ -10544,7 +10635,7 @@ msgstr "Коричневий" #: netbox/netbox/choices.py:71 msgid "Light Grey" -msgstr "Світло-сірий" +msgstr "Сріблясто-сірий" #: netbox/netbox/choices.py:72 msgid "Grey" @@ -10552,7 +10643,7 @@ msgstr "Сірий" #: netbox/netbox/choices.py:73 msgid "Dark Grey" -msgstr "Темно-сірий" +msgstr "Антрацитовий" #: netbox/netbox/choices.py:128 msgid "Direct" @@ -10560,7 +10651,7 @@ msgstr "прямий" #: netbox/netbox/choices.py:129 msgid "Upload" -msgstr "Завантажити" +msgstr "Вивантажити" #: netbox/netbox/choices.py:141 netbox/netbox/choices.py:155 msgid "Auto-detect" @@ -10576,7 +10667,7 @@ msgstr "Крапка з комою" #: netbox/netbox/choices.py:158 msgid "Tab" -msgstr "Вкладка" +msgstr "Табуляція" #: netbox/netbox/config/__init__.py:67 #, python-brace-format @@ -10638,19 +10729,19 @@ msgstr "Віддавайте перевагу IPv4 адресам над IPv6" #: netbox/netbox/config/parameters.py:84 msgid "Rack unit height" -msgstr "Висота юніта стійки" +msgstr "Висота стійки у юнітах" #: netbox/netbox/config/parameters.py:86 msgid "Default unit height for rendered rack elevations" -msgstr "Висота юніта за замовчуванням для візуалізованих висот стійки" +msgstr "Висота одиниці за замовчуванням для візуалізованих стійки" #: netbox/netbox/config/parameters.py:91 msgid "Rack unit width" -msgstr "Ширина юніта стійки" +msgstr "Ширина стійки у юнітах" #: netbox/netbox/config/parameters.py:93 msgid "Default unit width for rendered rack elevations" -msgstr "Типова одиниця ширини для візуалізованих висот стійки" +msgstr "Ширина одиниці за замовчуванням для візуалізованих стійки" #: netbox/netbox/config/parameters.py:100 msgid "Powerfeed voltage" @@ -10666,7 +10757,7 @@ msgstr "Сила струму подачі живлення" #: netbox/netbox/config/parameters.py:109 msgid "Default amperage for powerfeeds" -msgstr "Сила струму за замовчуванням для подачі живлення" +msgstr "Сила струму за замовчуванням при подачі живлення" #: netbox/netbox/config/parameters.py:114 msgid "Powerfeed max utilization" @@ -10674,7 +10765,7 @@ msgstr "Максимальне використання при подачі жи #: netbox/netbox/config/parameters.py:116 msgid "Default max utilization for powerfeeds" -msgstr "Максимальне використання за замовчуванням для подач живлення" +msgstr "Максимальне використання за замовчуванням при подачі живлення" #: netbox/netbox/config/parameters.py:123 #: netbox/templates/core/inc/config_data.html:53 @@ -10723,7 +10814,7 @@ msgstr "Налаштування за замовчуванням для нови #: netbox/netbox/config/parameters.py:181 #: netbox/templates/core/inc/config_data.html:129 msgid "Maintenance mode" -msgstr "Режим обслуговування" +msgstr "Режим технічного обслуговування" #: netbox/netbox/config/parameters.py:183 msgid "Enable maintenance mode" @@ -10782,11 +10873,11 @@ msgstr "Починається з" #: netbox/netbox/forms/__init__.py:15 msgid "Ends with" -msgstr "Закінчується з" +msgstr "Закінчується на" #: netbox/netbox/forms/__init__.py:16 msgid "Regex" -msgstr "Регекс" +msgstr "Регулярний вираз" #: netbox/netbox/forms/__init__.py:34 msgid "Object type(s)" @@ -10801,8 +10892,8 @@ msgid "" "Tag slugs separated by commas, encased with double quotes (e.g. " "\"tag1,tag2,tag3\")" msgstr "" -"Слимаки міток, розділені комами, укладені подвійними лапками (наприклад, " -"\"tag1, tag2, tag3\")" +"Мітки скорочень, розділені комами, укладені подвійними лапками (наприклад, " +"\"мітка1, мітка2, мітка3\")" #: netbox/netbox/forms/base.py:120 msgid "Add tags" @@ -10847,11 +10938,11 @@ msgstr "шлях даних" #: netbox/netbox/models/features.py:476 msgid "Path to remote file (relative to data source root)" -msgstr "Шляху до віддаленого файлу (відносно кореня джерела даних)" +msgstr "Шлях до віддаленого файлу (відносно кореня джерела даних)" #: netbox/netbox/models/features.py:479 msgid "auto sync enabled" -msgstr "увімкнено автоматичну синхронізацію" +msgstr "увімкнути автоматичну синхронізацію" #: netbox/netbox/models/features.py:481 msgid "Enable automatic synchronization of data when the data file is updated" @@ -10864,7 +10955,7 @@ msgstr "дата синхронізована" #: netbox/netbox/models/features.py:578 #, python-brace-format msgid "{class_name} must implement a sync_data() method." -msgstr "{class_name} повинен реалізувати метод sync_data ()." +msgstr "{class_name} повинен реалізувати метод sync_data()." #: netbox/netbox/navigation/menu.py:11 msgid "Organization" @@ -10939,7 +11030,7 @@ msgstr "Бездротові зв'язки" #: netbox/netbox/navigation/menu.py:121 msgid "Interface Connections" -msgstr "Інтерфейсні з'єднання" +msgstr "Інтерфейсні підключення" #: netbox/netbox/navigation/menu.py:126 msgid "Console Connections" @@ -10951,7 +11042,7 @@ msgstr "Підключення живлення" #: netbox/netbox/navigation/menu.py:147 msgid "Wireless LAN Groups" -msgstr "Групи бездротової локальної мережі" +msgstr "Групи WLAN" #: netbox/netbox/navigation/menu.py:168 msgid "Prefix & VLAN Roles" @@ -10991,7 +11082,7 @@ msgstr "Тунельні групи" #: netbox/netbox/navigation/menu.py:219 msgid "Tunnel Terminations" -msgstr "Закінчення тунелів" +msgstr "Кінці тунелів" #: netbox/netbox/navigation/menu.py:223 netbox/netbox/navigation/menu.py:225 #: netbox/vpn/models/l2vpn.py:64 @@ -11001,11 +11092,11 @@ msgstr "L2VPN" #: netbox/netbox/navigation/menu.py:226 netbox/templates/vpn/l2vpn.html:56 #: netbox/templates/vpn/tunnel.html:72 netbox/vpn/tables/tunnels.py:58 msgid "Terminations" -msgstr "Припинення" +msgstr "Кінці" #: netbox/netbox/navigation/menu.py:232 msgid "IKE Proposals" -msgstr "Пропозиції IKE" +msgstr "Налаштування IKE" #: netbox/netbox/navigation/menu.py:233 #: netbox/templates/vpn/ikeproposal.html:41 @@ -11014,7 +11105,7 @@ msgstr "Політика IKE" #: netbox/netbox/navigation/menu.py:234 msgid "IPSec Proposals" -msgstr "Пропозиції IPsec" +msgstr "Налаштування IPsec" #: netbox/netbox/navigation/menu.py:235 #: netbox/templates/vpn/ipsecproposal.html:37 @@ -11026,17 +11117,12 @@ msgstr "Політика IPsec" msgid "IPSec Profiles" msgstr "Профілі IPsec" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "Віртуалізація" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "Віртуальні диски" @@ -11072,7 +11158,7 @@ msgstr "Провайдери" #: netbox/netbox/navigation/menu.py:283 #: netbox/templates/circuits/provider.html:51 msgid "Provider Accounts" -msgstr "Облікові записи постачальника" +msgstr "Облікові записи провайдера" #: netbox/netbox/navigation/menu.py:284 msgid "Provider Networks" @@ -11096,7 +11182,7 @@ msgstr "Конфігураційні шаблони" #: netbox/netbox/navigation/menu.py:319 netbox/netbox/navigation/menu.py:323 msgid "Customization" -msgstr "Налаштування" +msgstr "Персоналізація" #: netbox/netbox/navigation/menu.py:325 #: netbox/templates/dcim/device_edit.html:103 @@ -11160,7 +11246,7 @@ msgstr "Завдання" #: netbox/netbox/navigation/menu.py:371 msgid "Logging" -msgstr "Лісозаготівля" +msgstr "Ведення журналу" #: netbox/netbox/navigation/menu.py:373 msgid "Notification Groups" @@ -11198,7 +11284,7 @@ msgstr "Система" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11241,22 +11327,22 @@ msgid "" "{template_extension} is not a subclass of " "netbox.plugins.PluginTemplateExtension!" msgstr "" -"{template_extension} не є підкласом Netbox.Plugins.PluginTemplateExtension!" +"{template_extension} не є підкласом netbox.plugins.PluginTemplateExtension!" #: netbox/netbox/plugins/registration.py:51 #, python-brace-format msgid "{item} must be an instance of netbox.plugins.PluginMenuItem" -msgstr "{item} повинен бути екземпляром Netbox.Plugins.PluginMenuItem" +msgstr "{item} повинен бути екземпляром netbox.plugins.PluginMenuItem" #: netbox/netbox/plugins/registration.py:62 #, python-brace-format msgid "{menu_link} must be an instance of netbox.plugins.PluginMenuItem" -msgstr "{menu_link} повинен бути екземпляром Netbox.Plugins.PluginMenuItem" +msgstr "{menu_link} повинен бути екземпляром netbox.plugins.PluginMenuItem" #: netbox/netbox/plugins/registration.py:67 #, python-brace-format msgid "{button} must be an instance of netbox.plugins.PluginMenuButton" -msgstr "{button} повинен бути екземпляром Netbox.Plugins.PluginMenuButton" +msgstr "{button} повинен бути екземпляром netbox.plugins.PluginMenuButton" #: netbox/netbox/plugins/templates.py:37 msgid "extra_context must be a dictionary" @@ -11272,7 +11358,7 @@ msgstr "Увімкнути динамічну навігацію інтерфе #: netbox/netbox/preferences.py:26 msgid "Experimental feature" -msgstr "Експериментальна особливість" +msgstr "Експериментальна функція" #: netbox/netbox/preferences.py:29 msgid "Language" @@ -11292,7 +11378,7 @@ msgstr "Довжина сторінки" #: netbox/netbox/preferences.py:44 msgid "The default number of objects to display per page" -msgstr "Типова кількість об'єктів для відображення на сторінці" +msgstr "Кількість об'єктів за замовченням на сторінці для відображення" #: netbox/netbox/preferences.py:48 msgid "Paginator placement" @@ -11428,7 +11514,7 @@ msgstr "Значення" #: netbox/netbox/tests/dummy_plugin/navigation.py:29 msgid "Dummy Plugin" -msgstr "Фікменний плагін" +msgstr "Фіктивний плагін" #: netbox/netbox/views/generic/bulk_views.py:114 #, python-brace-format @@ -11444,19 +11530,19 @@ msgstr "" msgid "Row {i}: Object with ID {id} does not exist" msgstr "Ряд {i}: Об'єкт з ідентифікатором {id} не існує" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "Ні {object_type} були обрані." -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "Перейменовано {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "Видалено {count} {object_type}" @@ -11486,9 +11572,9 @@ msgstr "Синхронізовано {count} {object_type}" #: netbox/netbox/views/generic/object_views.py:108 #, python-brace-format msgid "{class_name} must implement get_children()" -msgstr "{class_name} повинен реалізувати get_children ()" +msgstr "{class_name} повинен реалізувати get_children()" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11642,7 +11728,7 @@ msgstr "Замовлення" #: netbox/templates/account/preferences.html:51 msgid "Columns" -msgstr "Колони" +msgstr "Колонки" #: netbox/templates/account/preferences.html:71 #: netbox/templates/dcim/cable_trace.html:113 @@ -11714,7 +11800,7 @@ msgstr "Призначені групи" #: netbox/templates/users/objectpermission.html:87 #: netbox/templates/users/user.html:58 netbox/templates/users/user.html:68 msgid "None" -msgstr "Жоден" +msgstr "Жодного" #: netbox/templates/account/profile.html:68 #: netbox/templates/users/user.html:78 @@ -11730,7 +11816,7 @@ msgstr "Мої жетони API" #: netbox/templates/account/token.html:19 netbox/templates/users/token.html:6 #: netbox/templates/users/token.html:14 netbox/users/forms/filtersets.py:120 msgid "Token" -msgstr "Токен" +msgstr "Жетон" #: netbox/templates/account/token.html:39 netbox/templates/users/token.html:31 #: netbox/users/forms/bulk_edit.py:107 @@ -11743,7 +11829,7 @@ msgstr "Востаннє використано" #: netbox/templates/account/token_list.html:12 msgid "Add a Token" -msgstr "Додати токен" +msgstr "Додати Жетон" #: netbox/templates/base/base.html:22 netbox/templates/home.html:27 msgid "Home" @@ -11798,7 +11884,7 @@ msgstr "Дата припинення" #: netbox/templates/circuits/circuit.html:70 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:15 msgid "Assign Group" -msgstr "Призначити групу" +msgstr "Призначити у групу" #: netbox/templates/circuits/circuit_terminations_swap.html:4 msgid "Swap Circuit Terminations" @@ -11807,7 +11893,7 @@ msgstr "Поміняти місцями кінці каналу зв'язку" #: netbox/templates/circuits/circuit_terminations_swap.html:8 #, python-format msgid "Swap these terminations for circuit %(circuit)s?" -msgstr "Поміняти місцями кінці для каналу зв'язку%(circuit)s?" +msgstr "Поміняти місцями кінці для каналу зв'язку %(circuit)s?" #: netbox/templates/circuits/circuit_terminations_swap.html:14 msgid "A side" @@ -11834,9 +11920,7 @@ msgid "Circuit Type" msgstr "Тип каналу зв'язку" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11847,7 +11931,6 @@ msgstr "Додати" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -11859,7 +11942,7 @@ msgstr "Редагувати" #: netbox/templates/circuits/inc/circuit_termination.html:18 msgid "Swap" -msgstr "Обмін" +msgstr "Поміняти місцями" #: netbox/templates/circuits/inc/circuit_termination_fields.html:19 #: netbox/templates/dcim/consoleport.html:59 @@ -12135,35 +12218,35 @@ msgstr "днів" msgid "Indefinite" msgstr "Невизначений" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "Не встановлено" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "Огляд" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "Встановити" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "Деталі плагіна" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" -msgstr "У підсумку" +msgstr "Підсумок" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "Ліцензія" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "Історія версій" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "Інструкції по локальній установці" @@ -12191,11 +12274,11 @@ msgstr "Зупинити" #: netbox/templates/core/rq_task.html:34 msgid "Requeue" -msgstr "Реквье" +msgstr "Повторно поставлено у чергу" #: netbox/templates/core/rq_task.html:39 msgid "Enqueue" -msgstr "Поставте в чергу" +msgstr "Поставлено у чергу" #: netbox/templates/core/rq_task.html:61 msgid "Queue" @@ -12203,7 +12286,7 @@ msgstr "Черга" #: netbox/templates/core/rq_task.html:65 msgid "Timeout" -msgstr "Тайм-аут" +msgstr "Час очікування" #: netbox/templates/core/rq_task.html:69 msgid "Result TTL" @@ -12242,9 +12325,7 @@ msgstr "Завдання у черзі" #, python-format msgid "" "Select all %(count)s %(object_type_plural)s matching query" -msgstr "" -"Вибрати усі %(count)s %(object_type_plural)s відповідний " -"запит" +msgstr "Вибрати усі %(count)s %(object_type_plural)s запити" #: netbox/templates/core/rq_worker.html:10 msgid "Worker Info" @@ -12300,7 +12381,7 @@ msgstr "Статус системи" #: netbox/templates/core/system.html:31 msgid "NetBox release" -msgstr "Випуск NetBox" +msgstr "NetBox реліз" #: netbox/templates/core/system.html:44 msgid "Django version" @@ -12401,7 +12482,7 @@ msgstr "Пункт призначення" #: netbox/templates/dcim/cable_trace.html:91 msgid "Segments" -msgstr "сегменти" +msgstr "Сегменти" #: netbox/templates/dcim/cable_trace.html:104 msgid "Incomplete" @@ -12450,13 +12531,13 @@ msgstr "Переглянути віртуальне шасі" #: netbox/templates/dcim/device.html:164 msgid "Create VDC" -msgstr "Створіть джерело живлення постійного струму " +msgstr "Створіть джерело живлення постійного струму" #: netbox/templates/dcim/device.html:175 #: netbox/templates/dcim/device_edit.html:64 #: netbox/virtualization/forms/model_forms.py:223 msgid "Management" -msgstr "Менеджмент" +msgstr "Керування" #: netbox/templates/dcim/device.html:195 netbox/templates/dcim/device.html:211 #: netbox/templates/dcim/device.html:227 @@ -12497,7 +12578,7 @@ msgstr "ВА" #: netbox/templates/dcim/device.html:280 msgctxt "Leg of a power feed" msgid "Leg" -msgstr "Нога" +msgstr "Гілка (електричного кола)" #: netbox/templates/dcim/device.html:306 #: netbox/templates/virtualization/virtualmachine.html:158 @@ -12507,8 +12588,8 @@ msgstr "Додати послугу" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12532,19 +12613,19 @@ msgstr "Додати передні порти" #: netbox/templates/dcim/device/inc/interface_table_controls.html:9 msgid "Hide Enabled" -msgstr "Приховати увімкнено" +msgstr "Приховати усе, що увімкнено" #: netbox/templates/dcim/device/inc/interface_table_controls.html:10 msgid "Hide Disabled" -msgstr "Приховати вимкнено" +msgstr "Приховати усе, що вимкнено" #: netbox/templates/dcim/device/inc/interface_table_controls.html:11 msgid "Hide Virtual" -msgstr "Приховати віртуальний" +msgstr "Приховати усе, що має віртуальне походження" #: netbox/templates/dcim/device/inc/interface_table_controls.html:12 msgid "Hide Disconnected" -msgstr "Приховати відключене" +msgstr "Приховати усе, що відключене" #: netbox/templates/dcim/device/interfaces.html:27 msgid "Add Interfaces" @@ -12574,36 +12655,40 @@ msgstr "Додати задні порти" #: netbox/templates/dcim/device/render_config.html:5 #: netbox/templates/virtualization/virtualmachine/render_config.html:5 msgid "Config" -msgstr "конфігурація" +msgstr "Конфігурація" #: netbox/templates/dcim/device/render_config.html:35 #: netbox/templates/virtualization/virtualmachine/render_config.html:35 msgid "Context Data" msgstr "Контекстні дані" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "Відтворена конфігурація" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "Завантажити" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "Не знайдено шаблону конфігурації" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" -msgstr "Батьківська бухта" +msgstr "Батьківський відсік" #: netbox/templates/dcim/device_edit.html:48 #: netbox/utilities/templates/form_helpers/render_field.html:22 msgid "Regenerate Slug" -msgstr "Відновити слимака" +msgstr "Відновити скорочення" #: netbox/templates/dcim/device_edit.html:49 #: netbox/templates/generic/bulk_remove.html:21 @@ -12616,7 +12701,6 @@ msgid "Local Config Context Data" msgstr "Контекстні дані локальної конфігурації" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12625,7 +12709,7 @@ msgstr "Перейменувати" #: netbox/templates/dcim/devicebay.html:17 msgid "Device Bay" -msgstr "Резервуар для пристроїв" +msgstr "Відсік для пристроїв" #: netbox/templates/dcim/devicebay.html:43 msgid "Installed Device" @@ -12647,11 +12731,11 @@ msgstr "" #: netbox/templates/dcim/devicebay_populate.html:13 msgid "Populate" -msgstr "Заселити" +msgstr "Заповнити" #: netbox/templates/dcim/devicebay_populate.html:22 msgid "Bay" -msgstr "затока" +msgstr "Відсік" #: netbox/templates/dcim/devicerole.html:14 #: netbox/templates/dcim/platform.html:17 @@ -12663,12 +12747,12 @@ msgid "VM Role" msgstr "Роль віртуальної машини" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "Назва моделі" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "Номер частини" @@ -12678,7 +12762,7 @@ msgstr "Виключити з використання" #: netbox/templates/dcim/devicetype.html:59 msgid "Parent/Child" -msgstr "Батька/Дитина" +msgstr "Батько/Дитина" #: netbox/templates/dcim/devicetype.html:71 msgid "Front Image" @@ -12686,11 +12770,11 @@ msgstr "Зображення спереду" #: netbox/templates/dcim/devicetype.html:83 msgid "Rear Image" -msgstr "Ззаднє зображення" +msgstr "Зображення ззаду" #: netbox/templates/dcim/frontport.html:54 msgid "Rear Port Position" -msgstr "Положення заднього порту" +msgstr "Положення порту ззаду" #: netbox/templates/dcim/frontport.html:72 #: netbox/templates/dcim/interface.html:144 @@ -12715,11 +12799,11 @@ msgstr "Сторона Б" #: netbox/templates/dcim/inc/cable_termination.html:65 msgid "No termination" -msgstr "Без припинення" +msgstr "Без кінця" #: netbox/templates/dcim/inc/cable_toggle_buttons.html:3 msgid "Mark Planned" -msgstr "Марк Планований" +msgstr "Позначка запланова" #: netbox/templates/dcim/inc/cable_toggle_buttons.html:6 msgid "Mark Installed" @@ -12749,13 +12833,13 @@ msgstr "Без позначки" #: netbox/templates/dcim/inc/interface_vlans_table.html:37 msgid "No VLANs Assigned" -msgstr "Не присвоєно VLAN" +msgstr "Не присвоєно VLAN'ів" #: netbox/templates/dcim/inc/interface_vlans_table.html:44 #: netbox/templates/ipam/prefix_list.html:16 #: netbox/templates/ipam/prefix_list.html:33 msgid "Clear" -msgstr "Прозорий" +msgstr "Очистити" #: netbox/templates/dcim/inc/interface_vlans_table.html:47 msgid "Clear All" @@ -12767,7 +12851,7 @@ msgstr "Глибина монтажу" #: netbox/templates/dcim/inc/panels/racktype_numbering.html:6 msgid "Starting Unit" -msgstr "Пусковий блок" +msgstr "Початковий юніт" #: netbox/templates/dcim/inc/panels/racktype_numbering.html:10 msgid "Descending Units" @@ -12805,16 +12889,16 @@ msgstr "MAC-адреса" #: netbox/templates/dcim/interface.html:151 msgid "Wireless Link" -msgstr "Бездротове посилання" +msgstr "Бездротове з'єднання" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "Мережевий сусід" #: netbox/templates/dcim/interface.html:230 #: netbox/templates/wireless/inc/wirelesslink_interface.html:26 msgid "Channel" -msgstr "канал" +msgstr "Канал" #: netbox/templates/dcim/interface.html:239 #: netbox/templates/wireless/inc/wirelesslink_interface.html:32 @@ -12874,7 +12958,7 @@ msgstr "Додати підпорядковане місцезнаходженн #: netbox/templates/dcim/location.html:77 msgid "Child Locations" -msgstr "Підпорядковані локації" +msgstr "Підпорядковані місцезнаходження" #: netbox/templates/dcim/location.html:81 netbox/templates/dcim/site.html:131 msgid "Add a Location" @@ -12882,7 +12966,7 @@ msgstr "Додати місцезнаходження" #: netbox/templates/dcim/location.html:94 netbox/templates/dcim/site.html:144 msgid "Add a Device" -msgstr "Додавання пристрою" +msgstr "Додати пристрою" #: netbox/templates/dcim/manufacturer.html:16 msgid "Add Device Type" @@ -12907,7 +12991,7 @@ msgstr "Електричні характеристики" #: netbox/templates/dcim/powerfeed.html:88 msgctxt "Abbreviation for volts" msgid "V" -msgstr "V" +msgstr "В" #: netbox/templates/dcim/powerfeed.html:92 msgctxt "Abbreviation for amperes" @@ -13052,7 +13136,7 @@ msgstr "Додати учасника" #: netbox/templates/dcim/virtualchassis_add.html:18 msgid "Member Devices" -msgstr "Пристрої членів" +msgstr "Учасника пристроїв" #: netbox/templates/dcim/virtualchassis_add_member.html:10 #, python-format @@ -13085,7 +13169,7 @@ msgstr "Стійка/юніт" #: netbox/templates/dcim/virtualchassis_remove_member.html:5 msgid "Remove Virtual Chassis Member" -msgstr "Вилучити віртуальний член шасі" +msgstr "Вилучити віртуального учасника шасі" #: netbox/templates/dcim/virtualchassis_remove_member.html:9 #, python-format @@ -13123,11 +13207,11 @@ msgid "" "of required packages." msgstr "" "У цій інсталяції NetBox може бути відсутній один або кілька необхідних " -"пакетів Python. Ці пакети перераховані в requirements.txt і " +"пакетів Python. Ці пакети перераховані в requirements.txt та " "local_requirements.txt, і зазвичай встановлюються як частина " "процесу встановлення або оновлення. Щоб перевірити встановлені пакети, " -"запустіть заморожування піп з консолі і порівняйте вихід зі " -"списком необхідних пакетів." +"запустіть pip freeze з консолі і порівняйте вихід зі списком " +"необхідних пакетів." #: netbox/templates/exceptions/import_error.html:20 msgid "WSGI service not restarted after upgrade" @@ -13170,8 +13254,8 @@ msgid "" "A database programming error was detected while processing this request. " "Common causes include the following:" msgstr "" -"Під час обробки цього запиту була виявлена помилка програмування бази даних." -" До поширених причин можна віднести наступне:" +"Під час обробки цього запиту була виявлена програмна помилка бази даних. До " +"поширених причин можна віднести наступне:" #: netbox/templates/exceptions/programming_error.html:10 msgid "Database migrations missing" @@ -13212,7 +13296,7 @@ msgstr "Файл даних, пов'язаний з цим об'єктом, ви #: netbox/templates/extras/configtemplate.html:46 #: netbox/templates/extras/exporttemplate.html:60 msgid "Data Synced" -msgstr "Синхронізовані дані" +msgstr "Дані синхронізовані" #: netbox/templates/extras/configcontext_list.html:7 #: netbox/templates/extras/configtemplate_list.html:7 @@ -13302,7 +13386,7 @@ msgid "" "This will remove all configured widgets and restore the " "default dashboard configuration." msgstr "" -"Це видалить усі налаштовані віджети та відновити " +"Це видалить усі налаштовані віджети та відновить " "конфігурацію інформаційної панелі за замовчуванням." #: netbox/templates/extras/dashboard/reset.html:13 @@ -13429,47 +13513,52 @@ msgstr "У вас немає дозволу на запуск скриптів" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "Запустити скрипт" #: netbox/templates/extras/script.html:51 #: netbox/templates/extras/script/source.html:10 msgid "Error loading script" -msgstr "Помилка завантаження сценарію" +msgstr "Помилка завантаження скрипту" #: netbox/templates/extras/script/jobs.html:16 msgid "Script no longer exists in the source file." msgstr "Скрипт більше не існує у вихідному файлі." -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "Останній запуск" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "Скрипт більше не присутній у вихідному файлі" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "Ніколи" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "Запустіть знову" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "Не вдалося завантажити скрипти з модуля %(module)s" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "Скриптів не знайдено" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " "an uploaded file or data source." msgstr "" "Почніть з створення сценарію з " -"завантаженого файлу або джерела даних." +"вивантаженого файлу або джерела даних." #: netbox/templates/extras/script_result.html:35 #: netbox/templates/generic/object_list.html:50 @@ -13523,7 +13612,7 @@ msgstr "Додаткові заголовки" #: netbox/templates/extras/webhook.html:70 msgid "Body Template" -msgstr "Шаблон тіла" +msgstr "Шаблон тіла (запросу)" #: netbox/templates/generic/bulk_add_component.html:29 msgid "Bulk Creation" @@ -13581,7 +13670,7 @@ msgstr "Прямий імпорт" #: netbox/templates/generic/bulk_import.html:30 msgid "Upload File" -msgstr "Завантажити файл" +msgstr "Вивантажити файл" #: netbox/templates/generic/bulk_import.html:58 #: netbox/templates/generic/bulk_import.html:80 @@ -13603,7 +13692,7 @@ msgstr "вибір" #: netbox/templates/generic/bulk_import.html:161 msgid "Import Value" -msgstr "Імпортна вартість" +msgstr "Імпорт вартості" #: netbox/templates/generic/bulk_import.html:181 msgid "Format: YYYY-MM-DD" @@ -13625,7 +13714,7 @@ msgid "" "%(example)s would identify a VRF by its route distinguisher." msgstr "" "Пов'язані об'єкти можуть посилатися будь-яким унікальним атрибутом. " -"Наприклад, %(example)s ідентифікує VRF за його визначником " +"Наприклад, %(example)s ідентифікує VRF за його розрізнювачем " "маршруту." #: netbox/templates/generic/bulk_remove.html:28 @@ -13702,7 +13791,7 @@ msgstr "Переглянути документацію моделі" #: netbox/templates/generic/object_edit.html:36 msgid "Help" -msgstr "Допоможіть" +msgstr "Підказка" #: netbox/templates/generic/object_edit.html:83 msgid "Create & Add Another" @@ -13723,7 +13812,7 @@ msgstr "" #: netbox/templates/home.html:15 msgid "New Release Available" -msgstr "Новий випуск доступний" +msgstr "Новий реліз доступний" #: netbox/templates/home.html:16 msgid "is available" @@ -13740,7 +13829,7 @@ msgstr "Розблокування інформаційної панелі" #: netbox/templates/home.html:49 msgid "Lock Dashboard" -msgstr "Блокування інформаційної панелі " +msgstr "Блокування інформаційної панелі" #: netbox/templates/home.html:60 msgid "Add Widget" @@ -13783,7 +13872,7 @@ msgstr "Усі повідомлення" msgid "Select" msgstr "Вибрати" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "Скинути" @@ -13802,7 +13891,7 @@ msgid "" "Before you can add a %(model)s you must first create a " "%(prerequisite_model)s." msgstr "" -"Перш ніж ви зможете додати %(model)s спочатку потрібно створити " +"Перш ніж ви зможете додати %(model)s, спочатку потрібно створити " "%(prerequisite_model)s." #: netbox/templates/inc/paginator.html:15 @@ -13812,7 +13901,7 @@ msgstr "Вибір сторінки" #: netbox/templates/inc/paginator.html:75 #, python-format msgid "Showing %(start)s-%(end)s of %(total)s" -msgstr "Показуючи %(start)s-%(end)s з %(total)s" +msgstr "Показ %(start)s-%(end)s із %(total)s" #: netbox/templates/inc/paginator.html:82 msgid "Pagination options" @@ -13856,7 +13945,7 @@ msgstr "Довідковий центр" #: netbox/templates/inc/user_menu.html:41 msgid "Django Admin" -msgstr "Джанго Адміністратор" +msgstr "Адміністратор Django" #: netbox/templates/inc/user_menu.html:61 msgid "Log Out" @@ -13969,7 +14058,7 @@ msgstr "Деталі адресації" #: netbox/templates/ipam/prefix.html:118 msgid "Child IPs" -msgstr "Дитячі IP-адреси" +msgstr "Підпорядковані IP-адреси" #: netbox/templates/ipam/prefix.html:126 msgid "Available IPs" @@ -13997,7 +14086,7 @@ msgstr "Маска підстановки" #: netbox/templates/ipam/prefix.html:197 msgid "Broadcast Address" -msgstr "Адреса трансляції" +msgstr "Широкомовна адреса" #: netbox/templates/ipam/prefix/ip_ranges.html:7 msgid "Add IP Range" @@ -14029,11 +14118,11 @@ msgstr "Експорт VRF" #: netbox/templates/ipam/routetarget.html:52 msgid "Importing L2VPNs" -msgstr "Імпорт L2VPN" +msgstr "Імпорт L2VPN'ів" #: netbox/templates/ipam/routetarget.html:58 msgid "Exporting L2VPNs" -msgstr "Експорт L2VPN" +msgstr "Експорт L2VPN'ів" #: netbox/templates/ipam/vlan.html:88 msgid "Add a Prefix" @@ -14045,7 +14134,7 @@ msgstr "Додати VLAN" #: netbox/templates/ipam/vrf.html:16 msgid "Route Distinguisher" -msgstr "Відмінник маршруту" +msgstr "Розрізнювач маршруту" #: netbox/templates/ipam/vrf.html:29 msgid "Unique IP Space" @@ -14067,11 +14156,11 @@ msgstr "Або" #: netbox/templates/media_failure.html:7 msgid "Static Media Failure - NetBox" -msgstr "Помилка статичного носія - NetBox" +msgstr "Помилка статичних медіа-файлів - NetBox" #: netbox/templates/media_failure.html:21 msgid "Static Media Failure" -msgstr "Помилка статичного носія" +msgstr "Помилка статичних медіа-файлів" #: netbox/templates/media_failure.html:23 msgid "The following static media file failed to load" @@ -14087,7 +14176,7 @@ msgid "" " This installs the most recent iteration of each static file into the static" " root path." msgstr "" -"manage.py колективстатичний було запущено під час останнього " +"manage.py collectstatic було запущено під час останнього " "оновлення. Це встановлює останню ітерацію кожного статичного файлу в " "статичний кореневий шлях." @@ -14267,6 +14356,10 @@ msgstr "Ресурси" msgid "Add Virtual Disk" msgstr "Додати віртуальний диск" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -14283,7 +14376,7 @@ msgstr "Попередньо спільний ключ" #: netbox/templates/vpn/ikepolicy.html:33 #: netbox/templates/wireless/inc/authentication_attrs.html:20 msgid "Show Secret" -msgstr "Показати Таємницю" +msgstr "Показати таємницю" #: netbox/templates/vpn/ikepolicy.html:57 #: netbox/templates/vpn/ipsecpolicy.html:45 @@ -14292,11 +14385,11 @@ msgstr "Показати Таємницю" #: netbox/vpn/forms/model_forms.py:316 netbox/vpn/forms/model_forms.py:352 #: netbox/vpn/tables/crypto.py:68 netbox/vpn/tables/crypto.py:134 msgid "Proposals" -msgstr "Пропозиції" +msgstr "Налаштування" #: netbox/templates/vpn/ikeproposal.html:10 msgid "IKE Proposal" -msgstr "Пропозиція IKE" +msgstr "Налаштування IKE" #: netbox/templates/vpn/ikeproposal.html:21 netbox/vpn/forms/bulk_edit.py:97 #: netbox/vpn/forms/bulk_import.py:145 netbox/vpn/forms/filtersets.py:101 @@ -14337,7 +14430,7 @@ msgstr "Політика IPsec" #: netbox/templates/vpn/ipsecpolicy.html:21 netbox/vpn/forms/bulk_edit.py:210 #: netbox/vpn/models/crypto.py:193 msgid "PFS group" -msgstr "Група ПФС" +msgstr "Група PFS" #: netbox/templates/vpn/ipsecprofile.html:10 #: netbox/vpn/forms/model_forms.py:54 @@ -14346,7 +14439,7 @@ msgstr "Профіль IPsec" #: netbox/templates/vpn/ipsecprofile.html:89 netbox/vpn/tables/crypto.py:137 msgid "PFS Group" -msgstr "Група ПФС" +msgstr "Група PFS" #: netbox/templates/vpn/ipsecproposal.html:10 msgid "IPSec Proposal" @@ -14364,11 +14457,11 @@ msgstr "L2VPN Атрибути" #: netbox/templates/vpn/l2vpn.html:60 netbox/templates/vpn/tunnel.html:76 msgid "Add a Termination" -msgstr "Додати припинення" +msgstr "Додати кінець" #: netbox/templates/vpn/tunnel.html:9 msgid "Add Termination" -msgstr "Додати припинення" +msgstr "Додати кінець" #: netbox/templates/vpn/tunnel.html:37 netbox/vpn/forms/bulk_edit.py:49 #: netbox/vpn/forms/bulk_import.py:48 netbox/vpn/forms/filtersets.py:57 @@ -14397,7 +14490,7 @@ msgstr "Тунельна група" #: netbox/templates/vpn/tunneltermination.html:10 msgid "Tunnel Termination" -msgstr "Закриття тунелю" +msgstr "Кінець тунелю" #: netbox/templates/vpn/tunneltermination.html:35 #: netbox/vpn/forms/bulk_import.py:107 netbox/vpn/forms/model_forms.py:102 @@ -14416,7 +14509,7 @@ msgstr "Шифр" #: netbox/templates/wireless/inc/authentication_attrs.html:16 msgid "PSK" -msgstr " Попередньо спільний ключ (PSK)" +msgstr "Попередньо спільний ключ (PSK)" #: netbox/templates/wireless/inc/wirelesslink_interface.html:35 #: netbox/templates/wireless/inc/wirelesslink_interface.html:45 @@ -14430,7 +14523,7 @@ msgstr "Прикріплені інтерфейси" #: netbox/templates/wireless/wirelesslangroup.html:17 msgid "Add Wireless LAN" -msgstr "Додати бездротову мережу" +msgstr "Додати бездротову локальну мережу" #: netbox/templates/wireless/wirelesslangroup.html:26 #: netbox/wireless/forms/model_forms.py:28 @@ -14458,7 +14551,7 @@ msgstr "Батьківська контактна група (ідентифік #: netbox/tenancy/filtersets.py:34 msgid "Parent contact group (slug)" -msgstr "Батьківська контактна група (скоречення)" +msgstr "Батьківська контактна група (скорочення)" #: netbox/tenancy/filtersets.py:40 netbox/tenancy/filtersets.py:67 #: netbox/tenancy/filtersets.py:110 @@ -14468,7 +14561,7 @@ msgstr "Контактна група (ідентифікатор)" #: netbox/tenancy/filtersets.py:47 netbox/tenancy/filtersets.py:74 #: netbox/tenancy/filtersets.py:117 msgid "Contact group (slug)" -msgstr "Контактна група (скоречення)" +msgstr "Контактна група (скорочення)" #: netbox/tenancy/filtersets.py:104 msgid "Contact (ID)" @@ -14480,7 +14573,7 @@ msgstr "Роль контакту (ідентифікатор)" #: netbox/tenancy/filtersets.py:127 msgid "Contact role (slug)" -msgstr "Контактна роль (скоречення)" +msgstr "Контактна роль (скорочення)" #: netbox/tenancy/filtersets.py:158 msgid "Contact group" @@ -14492,7 +14585,7 @@ msgstr "Батьківська група орендарів (ідентифік #: netbox/tenancy/filtersets.py:175 msgid "Parent tenant group (slug)" -msgstr "Батьківська група орендарів (скоречення)" +msgstr "Батьківська група орендарів (скорочення)" #: netbox/tenancy/filtersets.py:181 netbox/tenancy/filtersets.py:201 msgid "Tenant group (ID)" @@ -14504,7 +14597,7 @@ msgstr "Група орендарів (ідентифікатор)" #: netbox/tenancy/filtersets.py:241 msgid "Tenant Group (slug)" -msgstr "Група орендарів (скоречення)" +msgstr "Група орендарів (скорочення)" #: netbox/tenancy/forms/bulk_edit.py:66 msgid "Desciption" @@ -14556,11 +14649,11 @@ msgstr "контакти" #: netbox/tenancy/models/contacts.py:153 msgid "contact assignment" -msgstr "призначення контактів" +msgstr "призначення контакта" #: netbox/tenancy/models/contacts.py:154 msgid "contact assignments" -msgstr "контактні завдання" +msgstr "призначення контакта" #: netbox/tenancy/models/contacts.py:170 #, python-brace-format @@ -14581,7 +14674,7 @@ msgstr "Ім'я орендаря має бути унікальним для к #: netbox/tenancy/models/tenants.py:80 msgid "Tenant slug must be unique per group." -msgstr "Слимак орендаря повинен бути унікальним для кожної групи." +msgstr "Скоречення орендаря повинен бути унікальним для кожної групи." #: netbox/tenancy/models/tenants.py:88 msgid "tenant" @@ -14589,7 +14682,7 @@ msgstr "орендар" #: netbox/tenancy/models/tenants.py:89 msgid "tenants" -msgstr "орендарів" +msgstr "орендарі" #: netbox/tenancy/tables/contacts.py:112 msgid "Contact Title" @@ -14597,19 +14690,19 @@ msgstr "Назва контакту" #: netbox/tenancy/tables/contacts.py:116 msgid "Contact Phone" -msgstr "Контактний телефон" +msgstr "Телефон контакту" #: netbox/tenancy/tables/contacts.py:121 msgid "Contact Email" -msgstr "Контактна адреса електронної скриньки" +msgstr "Контактний Email" #: netbox/tenancy/tables/contacts.py:125 msgid "Contact Address" -msgstr "Контактна адреса" +msgstr "Адреса контакту" #: netbox/tenancy/tables/contacts.py:129 msgid "Contact Link" -msgstr "Посилання на контакт" +msgstr "Посилання контакту" #: netbox/tenancy/tables/contacts.py:133 msgid "Contact Description" @@ -14645,7 +14738,7 @@ msgstr "Якщо ключ не надано, він буде згенерова #: netbox/users/forms/filtersets.py:51 netbox/users/tables.py:42 msgid "Is Staff" -msgstr "Чи є персонал" +msgstr "Є персоналом" #: netbox/users/forms/filtersets.py:58 netbox/users/tables.py:45 msgid "Is Superuser" @@ -14688,8 +14781,8 @@ msgid "" "10.1.1.0/24,192.168.10.16/32,2001:db8:1::/64" msgstr "" "Дозволені мережі IPv4/IPv6, звідки можна використовувати токен. Залиште " -"порожнім без обмежень. Приклад: 10.1.1.0/24,192.168.10.16/32,2001: дб " -"8:1: :/64" +"порожнім без обмежень. Приклад: " +"10.1.1.0/24,192.168.10.16/32,2001:db8:1::/64" #: netbox/users/forms/model_forms.py:175 msgid "Confirm password" @@ -14803,11 +14896,11 @@ msgid "" msgstr "" "Дозволені мережі IPv4/IPv6, звідки можна використовувати жетон. Залиште " "порожнім без обмежень. Наприклад: \"10.1.1.0/24, 192.168.10.16/32, " -"2001:DB8:1: :/64\"" +"2001:DB8:1::/64\"" #: netbox/users/models/tokens.py:75 msgid "token" -msgstr "токен" +msgstr "жетон" #: netbox/users/models/tokens.py:76 msgid "tokens" @@ -14859,16 +14952,16 @@ msgstr "" #: netbox/utilities/choices.py:19 #, python-brace-format msgid "{name} has a key defined but CHOICES is not a list" -msgstr "{name} має визначений ключ, але CHOICES не є списком" +msgstr "{name} має визначений ключ, але ВИБІР не є списком" #: netbox/utilities/conversion.py:19 msgid "Weight must be a positive number" -msgstr "Вага повинна бути позитивним числом" +msgstr "Вага повинна бути додатним числом" #: netbox/utilities/conversion.py:21 #, python-brace-format msgid "Invalid value '{weight}' for weight (must be a number)" -msgstr "Невірне значення '{weight}'для ваги (має бути число)" +msgstr "Невірне значення '{weight}' для ваги (має бути число)" #: netbox/utilities/conversion.py:32 netbox/utilities/conversion.py:62 #, python-brace-format @@ -14882,7 +14975,7 @@ msgstr "Довжина повинна бути додатним числом" #: netbox/utilities/conversion.py:47 #, python-brace-format msgid "Invalid value '{length}' for length (must be a number)" -msgstr "Невірне значення '{length}'для довжини (має бути число)" +msgstr "Невірне значення '{length}' для довжини (має бути число)" #: netbox/utilities/error_handlers.py:31 #, python-brace-format @@ -14907,7 +15000,7 @@ msgid "" "%s(%r) is invalid. to_model parameter to CounterCacheField must be a string " "in the format 'app.model'" msgstr "" -"%s(%r) невырний. Параметр to_model до CounterCacheField повинен бути рядком " +"%s(%r) невірний. Параметр to_model до CounterCacheField повинен бути рядком " "у форматі 'app.model'" #: netbox/utilities/fields.py:169 @@ -14933,7 +15026,7 @@ msgstr "Символ, який розмежовує поля CSV. Застосо #: netbox/utilities/forms/bulk_import.py:51 msgid "Form data must be empty when uploading/selecting a file." -msgstr "Дані форми повинні бути порожніми під час завантаження/вибору файлу." +msgstr "Дані форми повинні бути порожніми під час вивантаження/вибору файлу." #: netbox/utilities/forms/bulk_import.py:80 #, python-brace-format @@ -15022,7 +15115,7 @@ msgid "" msgstr "" "Буквено-цифрові діапазони підтримуються для масового створення. Змішані " "відмінки і типи в межах одного діапазону не підтримуються (приклад: " -"[Ге, хе] -0/0/ [0-9])." +"[ge,xe]-0/0/[0-9])." #: netbox/utilities/forms/fields/expandable.py:46 msgid "" @@ -15030,7 +15123,7 @@ msgid "" "192.0.2.[1,5,100-254]/24" msgstr "" "Вкажіть числовий діапазон для створення декількох IP-адрес.
    Приклад: " -"192.0.2. [1,5100-254] /24" +"192.0.2.[1,5,100-254]/24" #: netbox/utilities/forms/fields/fields.py:31 #, python-brace-format @@ -15071,7 +15164,7 @@ msgstr "Нерозпізнаний заголовок: {name}" #: netbox/utilities/forms/forms.py:118 msgid "Available Columns" -msgstr "Доступні колонки" +msgstr "Доступні стовпці" #: netbox/utilities/forms/forms.py:126 msgid "Selected Columns" @@ -15125,7 +15218,8 @@ msgstr "Знайдено несподіваний заголовок стовп #, python-brace-format msgid "Column \"{field}\" is not a related object; cannot use dots" msgstr "" -"Колонка \"{field}\" не є спорідненим об'єктом; не може використовувати точки" +"Стовпчик \"{field}\" не є спорідненим об'єктом; не може використовувати " +"точки" #: netbox/utilities/forms/utils.py:276 #, python-brace-format @@ -15241,11 +15335,11 @@ msgstr "Копіювати в буфер обміну" #: netbox/utilities/templates/form_helpers/render_field.html:57 msgid "This field is required" -msgstr "Це поле обов'язкове для заповнення" +msgstr "Це обов'язкове поле для заповнення" #: netbox/utilities/templates/form_helpers/render_field.html:70 msgid "Set Null" -msgstr "Встановити нуль" +msgstr "Встановити нуль (Null)" #: netbox/utilities/templates/helpers/applied_filters.html:11 msgid "Clear all" @@ -15257,15 +15351,15 @@ msgstr "Налаштування таблиці" #: netbox/utilities/templates/helpers/table_config_form.html:31 msgid "Move Up" -msgstr "Рухатися вгору" +msgstr "Рухати угору" #: netbox/utilities/templates/helpers/table_config_form.html:34 msgid "Move Down" -msgstr "Рухатися вниз" +msgstr "Рухати вниз" #: netbox/utilities/templates/navigation/menu.html:14 msgid "Search…" -msgstr "Пошук..." +msgstr "Пошук…" #: netbox/utilities/templates/navigation/menu.html:14 msgid "Search NetBox" @@ -15297,7 +15391,7 @@ msgstr "" #: netbox/utilities/views.py:93 #, python-brace-format msgid "{class_name} must implement get_required_permission()" -msgstr "{class_name} повинен реалізувати get_required_permissions ()" +msgstr "{class_name} повинен реалізувати get_required_permissions()" #: netbox/utilities/views.py:117 #, python-brace-format @@ -15315,7 +15409,7 @@ msgstr "Батьківська група (ідентифікатор)" #: netbox/virtualization/filtersets.py:85 msgid "Parent group (slug)" -msgstr "Батьківська група (скоречення)" +msgstr "Батьківська група (скорочення)" #: netbox/virtualization/filtersets.py:89 #: netbox/virtualization/filtersets.py:141 @@ -15337,13 +15431,13 @@ msgid "Memory (MB)" msgstr "Пам'ять (МБ)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "Диск (ГБ)" +msgid "Disk (MB)" +msgstr "Диск (МБ)" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "Розмір (ГБ)" +msgid "Size (MB)" +msgstr "Розмір (МБ)" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15484,7 +15578,7 @@ msgstr "" #: netbox/virtualization/models/virtualmachines.py:229 #, python-brace-format msgid "Must be an IPv{family} address. ({ip} is an IPv{version} address.)" -msgstr "Повинен бути IPV{family} адреса. ({ip} є IPV{version} адреса.)" +msgstr "Повинен бути IPv{family} адреса. ({ip} є IPv{version} адреса.)" #: netbox/virtualization/models/virtualmachines.py:238 #, python-brace-format @@ -15531,68 +15625,80 @@ msgstr "віртуальний диск" msgid "virtual disks" msgstr "віртуальні диски" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" -msgstr "Додано {count} пристрої для кластеризації {cluster}" +msgstr "Додано {count} пристроїв для кластеризації {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" -msgstr "Вилучено {count} пристрої з кластера {cluster}" +msgstr "Вилучено {count} пристроїв з кластера {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPsec - Транспорт" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec - тунель" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" -msgstr "IP-адреси в IP" +msgstr "IP-в-IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" -msgstr "ГРЕ" +msgstr "GRE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "Хаб" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" -msgstr "говорив" +msgstr "Спиця (в колесі)" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" -msgstr "Агресивний" +msgstr "Агресивно" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "Головний" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "Попередньо спільні ключі" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "Сертифікати" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "Підписи RSA" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "Підписи DSA" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15601,23 +15707,27 @@ msgstr "Підписи DSA" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Група {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Приватна мережа Ethernet" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Віртуальна приватна локальна мережа Ethernet" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Приватне дерево Ethernet" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Віртуальне приватне дерево Ethernet" @@ -15627,7 +15737,7 @@ msgstr "Тунельна група (ідентифікатор)" #: netbox/vpn/filtersets.py:47 msgid "Tunnel group (slug)" -msgstr "Тунельна група (скоречення)" +msgstr "Тунельна група (скорочення)" #: netbox/vpn/filtersets.py:54 msgid "IPSec profile (ID)" @@ -15667,7 +15777,7 @@ msgstr "Політика IPsec (назва)" #: netbox/vpn/filtersets.py:348 msgid "L2VPN (slug)" -msgstr "L2VPN (скоречення)" +msgstr "L2VPN (скорочення)" #: netbox/vpn/filtersets.py:412 msgid "VM Interface (ID)" @@ -15727,15 +15837,15 @@ msgstr "Інтерфейс пристрою або віртуальної маш #: netbox/vpn/forms/bulk_import.py:183 msgid "IKE proposal(s)" -msgstr "Пропозиція (и) IKE" +msgstr "Пропозиція/iї IKE" #: netbox/vpn/forms/bulk_import.py:215 netbox/vpn/models/crypto.py:197 msgid "Diffie-Hellman group for Perfect Forward Secrecy" -msgstr "Група Діффі-Хеллмана для «Ідеальна таємниця вперед»" +msgstr "Група Діффі-Хеллмана для Perfect Forward Secrecy" #: netbox/vpn/forms/bulk_import.py:222 msgid "IPSec proposal(s)" -msgstr "Пропозиція (и) IPsec" +msgstr "Пропозиція/iї IPsec" #: netbox/vpn/forms/bulk_import.py:236 msgid "IPSec protocol" @@ -15791,15 +15901,15 @@ msgstr "Інтерфейс тунелю" #: netbox/vpn/forms/model_forms.py:150 msgid "First Termination" -msgstr "Перше припинення" +msgstr "Перший кінець" #: netbox/vpn/forms/model_forms.py:153 msgid "Second Termination" -msgstr "Друге припинення" +msgstr "Другий кінець" #: netbox/vpn/forms/model_forms.py:197 msgid "This parameter is required when defining a termination." -msgstr "Цей параметр обов'язковий при визначенні закінчення." +msgstr "Цей параметр обов'язковий при визначенні кінця." #: netbox/vpn/forms/model_forms.py:320 netbox/vpn/forms/model_forms.py:356 msgid "Policy" @@ -15807,13 +15917,12 @@ msgstr "Політика" #: netbox/vpn/forms/model_forms.py:487 msgid "A termination must specify an interface or VLAN." -msgstr "Припинення повинно вказувати інтерфейс або VLAN." +msgstr "Кінець повинен підключатися до інтерфейсу або VLAN." #: netbox/vpn/forms/model_forms.py:489 msgid "" "A termination can only have one terminating object (an interface or VLAN)." -msgstr "" -"Термінування може мати лише один кінцевий об'єкт (інтерфейс або VLAN)." +msgstr "Кінець може мати лише один кінцевий об'єкт (інтерфейс або VLAN)." #: netbox/vpn/models/crypto.py:33 msgid "encryption algorithm" @@ -15837,7 +15946,7 @@ msgstr "Пропозиція IKE" #: netbox/vpn/models/crypto.py:60 msgid "IKE proposals" -msgstr "Пропозиції IKE" +msgstr "Налаштування IKE" #: netbox/vpn/models/crypto.py:76 msgid "version" @@ -15845,7 +15954,7 @@ msgstr "версія" #: netbox/vpn/models/crypto.py:88 netbox/vpn/models/crypto.py:190 msgid "proposals" -msgstr "пропозиції" +msgstr "налаштування" #: netbox/vpn/models/crypto.py:91 netbox/wireless/models.py:39 msgid "pre-shared key" @@ -15901,16 +16010,16 @@ msgstr "Профілі IPsec" #: netbox/vpn/models/l2vpn.py:116 msgid "L2VPN termination" -msgstr "Припинення L2VPN" +msgstr "Кінець L2VPN" #: netbox/vpn/models/l2vpn.py:117 msgid "L2VPN terminations" -msgstr "Термінації L2VPN" +msgstr "Кінці L2VPN" #: netbox/vpn/models/l2vpn.py:135 #, python-brace-format msgid "L2VPN Termination already assigned ({assigned_object})" -msgstr "Припинення L2VPN вже призначено ({assigned_object})" +msgstr "Кінець L2VPN вже призначено ({assigned_object})" #: netbox/vpn/models/l2vpn.py:147 #, python-brace-format @@ -15918,7 +16027,7 @@ msgid "" "{l2vpn_type} L2VPNs cannot have more than two terminations; found " "{terminations_count} already defined." msgstr "" -"{l2vpn_type} L2VPN не може мати більше двох термінів; знайдено " +"{l2vpn_type} L2VPN не може мати більше двох кінців; знайдено " "{terminations_count} вже визначено." #: netbox/vpn/models/tunnels.py:26 @@ -15947,15 +16056,15 @@ msgstr "тунелі" #: netbox/vpn/models/tunnels.py:153 msgid "An object may be terminated to only one tunnel at a time." -msgstr "Об'єкт може бути завершений лише в одному тунелі одночасно." +msgstr "Об'єкт може бути кінцем лише в одному тунелі одночасно." #: netbox/vpn/models/tunnels.py:156 msgid "tunnel termination" -msgstr "закінчення тунелю" +msgstr "кинець тунелю" #: netbox/vpn/models/tunnels.py:157 msgid "tunnel terminations" -msgstr "закінчення тунелів" +msgstr "кінці тунелів" #: netbox/vpn/models/tunnels.py:174 #, python-brace-format @@ -15976,7 +16085,7 @@ msgstr "Алгоритм аутентифікації" #: netbox/vpn/tables/crypto.py:34 msgid "SA Lifetime" -msgstr "SA Термін служби" +msgstr "Тривалість життя SA" #: netbox/vpn/tables/crypto.py:71 msgid "Pre-shared Key" @@ -15984,11 +16093,11 @@ msgstr "Попередньо спільний ключ" #: netbox/vpn/tables/crypto.py:103 msgid "SA Lifetime (Seconds)" -msgstr "Термін служби SA (секунди)" +msgstr "Тривалість життя SA (секунди)" #: netbox/vpn/tables/crypto.py:106 msgid "SA Lifetime (KB)" -msgstr "Термін служби SA (КБ)" +msgstr "Тривалість життя SA (КБ)" #: netbox/vpn/tables/l2vpn.py:69 msgid "Object Parent" @@ -15996,7 +16105,7 @@ msgstr "Батьківський об'єкт" #: netbox/vpn/tables/l2vpn.py:74 msgid "Object Site" -msgstr "Сайт об'єкта" +msgstr "Тех. майданчик об'єкта" #: netbox/wireless/choices.py:11 msgid "Access point" @@ -16048,7 +16157,7 @@ msgstr "Інтерфейс A" #: netbox/wireless/forms/bulk_import.py:93 #: netbox/wireless/tables/wirelesslink.py:37 msgid "Interface B" -msgstr "Інтерфейс B" +msgstr "Інтерфейс Б" #: netbox/wireless/forms/model_forms.py:161 msgid "Side B" @@ -16076,7 +16185,7 @@ msgstr "інтерфейс А" #: netbox/wireless/models.py:151 msgid "interface B" -msgstr "інтерфейс B" +msgstr "інтерфейс Б" #: netbox/wireless/models.py:165 msgid "distance" @@ -16088,15 +16197,17 @@ msgstr "одиниця відстані" #: netbox/wireless/models.py:219 msgid "wireless link" -msgstr "бездротова зв'язок" +msgstr "бездротовий канал зв'язок" #: netbox/wireless/models.py:220 msgid "wireless links" -msgstr "бездротові зв'язки" +msgstr "бездротові канали зв'язку" #: netbox/wireless/models.py:236 msgid "Must specify a unit when setting a wireless distance" -msgstr "Необхідно вказати одиницю виміру при установці бездротової відстані" +msgstr "" +"Необхідно вказати одиницю виміру при установці відстані бездротового каналу " +"зв'язку" #: netbox/wireless/models.py:242 netbox/wireless/models.py:248 #, python-brace-format diff --git a/netbox/translations/zh/LC_MESSAGES/django.mo b/netbox/translations/zh/LC_MESSAGES/django.mo index 7affc8f55..52e676825 100644 Binary files a/netbox/translations/zh/LC_MESSAGES/django.mo and b/netbox/translations/zh/LC_MESSAGES/django.mo differ diff --git a/netbox/translations/zh/LC_MESSAGES/django.po b/netbox/translations/zh/LC_MESSAGES/django.po index 8de99d405..c5d1f3032 100644 --- a/netbox/translations/zh/LC_MESSAGES/django.po +++ b/netbox/translations/zh/LC_MESSAGES/django.po @@ -21,7 +21,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-12 05:02+0000\n" +"POT-Creation-Date: 2024-12-12 05:02+0000\n" "PO-Revision-Date: 2023-10-30 17:48+0000\n" "Last-Translator: Jeremy Stretch, 2024\n" "Language-Team: Chinese (https://app.transifex.com/netbox-community/teams/178115/zh/)\n" @@ -96,8 +96,8 @@ msgstr "您的密码已成功更改。" #: netbox/circuits/choices.py:21 netbox/dcim/choices.py:20 #: netbox/dcim/choices.py:102 netbox/dcim/choices.py:185 -#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1530 -#: netbox/dcim/choices.py:1606 netbox/dcim/choices.py:1656 +#: netbox/dcim/choices.py:237 netbox/dcim/choices.py:1532 +#: netbox/dcim/choices.py:1608 netbox/dcim/choices.py:1658 #: netbox/virtualization/choices.py:20 netbox/virtualization/choices.py:45 #: netbox/vpn/choices.py:18 msgid "Planned" @@ -110,7 +110,7 @@ msgstr "置备" #: netbox/circuits/choices.py:23 netbox/core/tables/tasks.py:22 #: netbox/dcim/choices.py:22 netbox/dcim/choices.py:103 #: netbox/dcim/choices.py:184 netbox/dcim/choices.py:236 -#: netbox/dcim/choices.py:1605 netbox/dcim/choices.py:1655 +#: netbox/dcim/choices.py:1607 netbox/dcim/choices.py:1657 #: netbox/extras/tables/tables.py:495 netbox/ipam/choices.py:31 #: netbox/ipam/choices.py:49 netbox/ipam/choices.py:69 #: netbox/ipam/choices.py:154 netbox/templates/extras/configcontext.html:25 @@ -121,8 +121,8 @@ msgid "Active" msgstr "在线" #: netbox/circuits/choices.py:24 netbox/dcim/choices.py:183 -#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1604 -#: netbox/dcim/choices.py:1657 netbox/virtualization/choices.py:24 +#: netbox/dcim/choices.py:235 netbox/dcim/choices.py:1606 +#: netbox/dcim/choices.py:1659 netbox/virtualization/choices.py:24 #: netbox/virtualization/choices.py:43 msgid "Offline" msgstr "离线" @@ -135,7 +135,7 @@ msgstr "预留" msgid "Decommissioned" msgstr "退役" -#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1617 +#: netbox/circuits/choices.py:90 netbox/dcim/choices.py:1619 #: netbox/tenancy/choices.py:17 msgid "Primary" msgstr "主要联系人" @@ -208,12 +208,12 @@ msgstr "站点组(缩写)" #: netbox/circuits/forms/filtersets.py:209 #: netbox/circuits/forms/model_forms.py:138 #: netbox/circuits/forms/model_forms.py:154 -#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:168 -#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:677 -#: netbox/dcim/forms/bulk_edit.py:873 netbox/dcim/forms/bulk_import.py:131 -#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:309 -#: netbox/dcim/forms/bulk_import.py:540 netbox/dcim/forms/bulk_import.py:1311 -#: netbox/dcim/forms/bulk_import.py:1339 netbox/dcim/forms/filtersets.py:87 +#: netbox/circuits/tables/circuits.py:113 netbox/dcim/forms/bulk_edit.py:169 +#: netbox/dcim/forms/bulk_edit.py:330 netbox/dcim/forms/bulk_edit.py:683 +#: netbox/dcim/forms/bulk_edit.py:888 netbox/dcim/forms/bulk_import.py:131 +#: netbox/dcim/forms/bulk_import.py:230 netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:562 netbox/dcim/forms/bulk_import.py:1333 +#: netbox/dcim/forms/bulk_import.py:1361 netbox/dcim/forms/filtersets.py:87 #: netbox/dcim/forms/filtersets.py:225 netbox/dcim/forms/filtersets.py:342 #: netbox/dcim/forms/filtersets.py:439 netbox/dcim/forms/filtersets.py:753 #: netbox/dcim/forms/filtersets.py:997 netbox/dcim/forms/filtersets.py:1021 @@ -222,18 +222,17 @@ msgstr "站点组(缩写)" #: netbox/dcim/forms/filtersets.py:1632 netbox/dcim/forms/model_forms.py:137 #: netbox/dcim/forms/model_forms.py:165 netbox/dcim/forms/model_forms.py:238 #: netbox/dcim/forms/model_forms.py:463 netbox/dcim/forms/model_forms.py:723 -#: netbox/dcim/forms/object_create.py:391 netbox/dcim/tables/devices.py:153 +#: netbox/dcim/forms/object_create.py:383 netbox/dcim/tables/devices.py:153 #: netbox/dcim/tables/power.py:26 netbox/dcim/tables/power.py:93 #: netbox/dcim/tables/racks.py:122 netbox/dcim/tables/racks.py:207 #: netbox/dcim/tables/sites.py:134 netbox/extras/filtersets.py:525 -#: netbox/ipam/forms/bulk_edit.py:217 netbox/ipam/forms/bulk_edit.py:284 -#: netbox/ipam/forms/bulk_edit.py:451 netbox/ipam/forms/bulk_edit.py:529 -#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:429 -#: netbox/ipam/forms/filtersets.py:153 netbox/ipam/forms/filtersets.py:231 -#: netbox/ipam/forms/filtersets.py:432 netbox/ipam/forms/filtersets.py:489 -#: netbox/ipam/forms/model_forms.py:205 netbox/ipam/forms/model_forms.py:636 -#: netbox/ipam/tables/ip.py:245 netbox/ipam/tables/vlans.py:118 -#: netbox/ipam/tables/vlans.py:221 +#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_edit.py:285 +#: netbox/ipam/forms/bulk_edit.py:484 netbox/ipam/forms/bulk_import.py:171 +#: netbox/ipam/forms/bulk_import.py:453 netbox/ipam/forms/filtersets.py:153 +#: netbox/ipam/forms/filtersets.py:231 netbox/ipam/forms/filtersets.py:432 +#: netbox/ipam/forms/filtersets.py:489 netbox/ipam/forms/model_forms.py:205 +#: netbox/ipam/forms/model_forms.py:669 netbox/ipam/tables/ip.py:245 +#: netbox/ipam/tables/vlans.py:118 netbox/ipam/tables/vlans.py:221 #: netbox/templates/circuits/inc/circuit_termination_fields.html:6 #: netbox/templates/dcim/device.html:22 #: netbox/templates/dcim/inc/cable_termination.html:8 @@ -341,10 +340,10 @@ msgstr "接入点A (ID)" #: netbox/extras/filtersets.py:348 netbox/extras/filtersets.py:391 #: netbox/extras/filtersets.py:438 netbox/extras/filtersets.py:498 #: netbox/extras/filtersets.py:657 netbox/extras/filtersets.py:703 -#: netbox/ipam/forms/model_forms.py:449 netbox/netbox/filtersets.py:282 +#: netbox/ipam/forms/model_forms.py:482 netbox/netbox/filtersets.py:282 #: netbox/netbox/forms/__init__.py:22 netbox/netbox/forms/base.py:167 #: netbox/templates/htmx/object_selector.html:28 -#: netbox/templates/inc/filter_list.html:45 +#: netbox/templates/inc/filter_list.html:46 #: netbox/templates/ipam/ipaddress_assign.html:29 #: netbox/templates/search.html:7 netbox/templates/search.html:26 #: netbox/tenancy/filtersets.py:99 netbox/users/filtersets.py:23 @@ -396,7 +395,7 @@ msgstr "电路组(slug)" #: netbox/circuits/forms/bulk_edit.py:30 #: netbox/circuits/forms/filtersets.py:56 #: netbox/circuits/forms/model_forms.py:29 -#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:128 +#: netbox/circuits/tables/providers.py:33 netbox/dcim/forms/bulk_edit.py:129 #: netbox/dcim/forms/filtersets.py:195 netbox/dcim/forms/model_forms.py:123 #: netbox/dcim/tables/sites.py:94 netbox/ipam/models/asns.py:126 #: netbox/ipam/tables/asn.py:27 netbox/ipam/views.py:213 @@ -411,33 +410,33 @@ msgstr "自治系统编号/AS编号" #: netbox/circuits/forms/bulk_edit.py:164 #: netbox/circuits/forms/bulk_edit.py:183 #: netbox/circuits/forms/bulk_edit.py:228 netbox/core/forms/bulk_edit.py:28 -#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:73 -#: netbox/dcim/forms/bulk_edit.py:92 netbox/dcim/forms/bulk_edit.py:151 -#: netbox/dcim/forms/bulk_edit.py:192 netbox/dcim/forms/bulk_edit.py:210 -#: netbox/dcim/forms/bulk_edit.py:288 netbox/dcim/forms/bulk_edit.py:432 -#: netbox/dcim/forms/bulk_edit.py:466 netbox/dcim/forms/bulk_edit.py:481 -#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 -#: netbox/dcim/forms/bulk_edit.py:618 netbox/dcim/forms/bulk_edit.py:642 -#: netbox/dcim/forms/bulk_edit.py:715 netbox/dcim/forms/bulk_edit.py:767 -#: netbox/dcim/forms/bulk_edit.py:819 netbox/dcim/forms/bulk_edit.py:842 -#: netbox/dcim/forms/bulk_edit.py:890 netbox/dcim/forms/bulk_edit.py:960 -#: netbox/dcim/forms/bulk_edit.py:1013 netbox/dcim/forms/bulk_edit.py:1048 -#: netbox/dcim/forms/bulk_edit.py:1088 netbox/dcim/forms/bulk_edit.py:1132 -#: netbox/dcim/forms/bulk_edit.py:1177 netbox/dcim/forms/bulk_edit.py:1204 -#: netbox/dcim/forms/bulk_edit.py:1222 netbox/dcim/forms/bulk_edit.py:1240 -#: netbox/dcim/forms/bulk_edit.py:1258 netbox/dcim/forms/bulk_edit.py:1682 +#: netbox/dcim/forms/bulk_create.py:35 netbox/dcim/forms/bulk_edit.py:74 +#: netbox/dcim/forms/bulk_edit.py:93 netbox/dcim/forms/bulk_edit.py:152 +#: netbox/dcim/forms/bulk_edit.py:193 netbox/dcim/forms/bulk_edit.py:211 +#: netbox/dcim/forms/bulk_edit.py:289 netbox/dcim/forms/bulk_edit.py:438 +#: netbox/dcim/forms/bulk_edit.py:472 netbox/dcim/forms/bulk_edit.py:487 +#: netbox/dcim/forms/bulk_edit.py:546 netbox/dcim/forms/bulk_edit.py:590 +#: netbox/dcim/forms/bulk_edit.py:624 netbox/dcim/forms/bulk_edit.py:648 +#: netbox/dcim/forms/bulk_edit.py:721 netbox/dcim/forms/bulk_edit.py:782 +#: netbox/dcim/forms/bulk_edit.py:834 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_edit.py:975 +#: netbox/dcim/forms/bulk_edit.py:1028 netbox/dcim/forms/bulk_edit.py:1063 +#: netbox/dcim/forms/bulk_edit.py:1103 netbox/dcim/forms/bulk_edit.py:1147 +#: netbox/dcim/forms/bulk_edit.py:1192 netbox/dcim/forms/bulk_edit.py:1219 +#: netbox/dcim/forms/bulk_edit.py:1237 netbox/dcim/forms/bulk_edit.py:1255 +#: netbox/dcim/forms/bulk_edit.py:1273 netbox/dcim/forms/bulk_edit.py:1725 #: netbox/extras/forms/bulk_edit.py:39 netbox/extras/forms/bulk_edit.py:149 #: netbox/extras/forms/bulk_edit.py:178 netbox/extras/forms/bulk_edit.py:208 #: netbox/extras/forms/bulk_edit.py:256 netbox/extras/forms/bulk_edit.py:274 #: netbox/extras/forms/bulk_edit.py:298 netbox/extras/forms/bulk_edit.py:312 #: netbox/extras/forms/bulk_edit.py:339 netbox/extras/tables/tables.py:79 -#: netbox/ipam/forms/bulk_edit.py:52 netbox/ipam/forms/bulk_edit.py:72 -#: netbox/ipam/forms/bulk_edit.py:92 netbox/ipam/forms/bulk_edit.py:116 -#: netbox/ipam/forms/bulk_edit.py:145 netbox/ipam/forms/bulk_edit.py:174 -#: netbox/ipam/forms/bulk_edit.py:193 netbox/ipam/forms/bulk_edit.py:275 -#: netbox/ipam/forms/bulk_edit.py:320 netbox/ipam/forms/bulk_edit.py:368 -#: netbox/ipam/forms/bulk_edit.py:411 netbox/ipam/forms/bulk_edit.py:427 -#: netbox/ipam/forms/bulk_edit.py:561 netbox/ipam/forms/bulk_edit.py:592 +#: netbox/ipam/forms/bulk_edit.py:53 netbox/ipam/forms/bulk_edit.py:73 +#: netbox/ipam/forms/bulk_edit.py:93 netbox/ipam/forms/bulk_edit.py:117 +#: netbox/ipam/forms/bulk_edit.py:146 netbox/ipam/forms/bulk_edit.py:175 +#: netbox/ipam/forms/bulk_edit.py:194 netbox/ipam/forms/bulk_edit.py:276 +#: netbox/ipam/forms/bulk_edit.py:321 netbox/ipam/forms/bulk_edit.py:369 +#: netbox/ipam/forms/bulk_edit.py:412 netbox/ipam/forms/bulk_edit.py:428 +#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_edit.py:547 #: netbox/templates/account/token.html:35 #: netbox/templates/circuits/circuit.html:59 #: netbox/templates/circuits/circuitgroup.html:32 @@ -446,7 +445,7 @@ msgstr "自治系统编号/AS编号" #: netbox/templates/circuits/provider.html:33 #: netbox/templates/circuits/providernetwork.html:32 #: netbox/templates/core/datasource.html:54 -#: netbox/templates/core/plugin.html:79 netbox/templates/dcim/cable.html:36 +#: netbox/templates/core/plugin.html:80 netbox/templates/dcim/cable.html:36 #: netbox/templates/dcim/consoleport.html:44 #: netbox/templates/dcim/consoleserverport.html:44 #: netbox/templates/dcim/device.html:94 @@ -461,7 +460,7 @@ msgstr "自治系统编号/AS编号" #: netbox/templates/dcim/manufacturer.html:40 #: netbox/templates/dcim/module.html:73 #: netbox/templates/dcim/modulebay.html:42 -#: netbox/templates/dcim/moduletype.html:26 +#: netbox/templates/dcim/moduletype.html:37 #: netbox/templates/dcim/platform.html:33 #: netbox/templates/dcim/powerfeed.html:40 #: netbox/templates/dcim/poweroutlet.html:40 @@ -481,7 +480,7 @@ msgstr "自治系统编号/AS编号" #: netbox/templates/extras/exporttemplate.html:19 #: netbox/templates/extras/notificationgroup.html:20 #: netbox/templates/extras/savedfilter.html:17 -#: netbox/templates/extras/script_list.html:45 +#: netbox/templates/extras/script_list.html:46 #: netbox/templates/extras/tag.html:20 netbox/templates/extras/webhook.html:17 #: netbox/templates/generic/bulk_import.html:120 #: netbox/templates/ipam/aggregate.html:43 netbox/templates/ipam/asn.html:42 @@ -574,10 +573,10 @@ msgid "Service ID" msgstr "服务ID" #: netbox/circuits/forms/bulk_edit.py:100 -#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:206 -#: netbox/dcim/forms/bulk_edit.py:604 netbox/dcim/forms/bulk_edit.py:804 -#: netbox/dcim/forms/bulk_edit.py:1173 netbox/dcim/forms/bulk_edit.py:1200 -#: netbox/dcim/forms/bulk_edit.py:1678 netbox/dcim/forms/filtersets.py:1064 +#: netbox/circuits/forms/filtersets.py:107 netbox/dcim/forms/bulk_edit.py:207 +#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/forms/bulk_edit.py:819 +#: netbox/dcim/forms/bulk_edit.py:1188 netbox/dcim/forms/bulk_edit.py:1215 +#: netbox/dcim/forms/bulk_edit.py:1721 netbox/dcim/forms/filtersets.py:1064 #: netbox/dcim/forms/filtersets.py:1455 netbox/dcim/forms/filtersets.py:1479 #: netbox/dcim/tables/devices.py:704 netbox/dcim/tables/devices.py:761 #: netbox/dcim/tables/devices.py:1003 netbox/dcim/tables/devicetypes.py:249 @@ -598,16 +597,16 @@ msgstr "颜色" #: netbox/circuits/forms/filtersets.py:126 netbox/core/forms/bulk_edit.py:18 #: netbox/core/forms/filtersets.py:33 netbox/core/tables/change_logging.py:32 #: netbox/core/tables/data.py:20 netbox/core/tables/jobs.py:18 -#: netbox/dcim/forms/bulk_edit.py:782 netbox/dcim/forms/bulk_edit.py:921 -#: netbox/dcim/forms/bulk_edit.py:989 netbox/dcim/forms/bulk_edit.py:1008 -#: netbox/dcim/forms/bulk_edit.py:1031 netbox/dcim/forms/bulk_edit.py:1073 -#: netbox/dcim/forms/bulk_edit.py:1117 netbox/dcim/forms/bulk_edit.py:1168 -#: netbox/dcim/forms/bulk_edit.py:1195 netbox/dcim/forms/bulk_import.py:188 -#: netbox/dcim/forms/bulk_import.py:260 netbox/dcim/forms/bulk_import.py:708 -#: netbox/dcim/forms/bulk_import.py:734 netbox/dcim/forms/bulk_import.py:760 -#: netbox/dcim/forms/bulk_import.py:780 netbox/dcim/forms/bulk_import.py:863 -#: netbox/dcim/forms/bulk_import.py:957 netbox/dcim/forms/bulk_import.py:999 -#: netbox/dcim/forms/bulk_import.py:1213 netbox/dcim/forms/bulk_import.py:1376 +#: netbox/dcim/forms/bulk_edit.py:797 netbox/dcim/forms/bulk_edit.py:936 +#: netbox/dcim/forms/bulk_edit.py:1004 netbox/dcim/forms/bulk_edit.py:1023 +#: netbox/dcim/forms/bulk_edit.py:1046 netbox/dcim/forms/bulk_edit.py:1088 +#: netbox/dcim/forms/bulk_edit.py:1132 netbox/dcim/forms/bulk_edit.py:1183 +#: netbox/dcim/forms/bulk_edit.py:1210 netbox/dcim/forms/bulk_import.py:188 +#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:730 +#: netbox/dcim/forms/bulk_import.py:756 netbox/dcim/forms/bulk_import.py:782 +#: netbox/dcim/forms/bulk_import.py:802 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_import.py:979 netbox/dcim/forms/bulk_import.py:1021 +#: netbox/dcim/forms/bulk_import.py:1235 netbox/dcim/forms/bulk_import.py:1398 #: netbox/dcim/forms/filtersets.py:955 netbox/dcim/forms/filtersets.py:1054 #: netbox/dcim/forms/filtersets.py:1175 netbox/dcim/forms/filtersets.py:1247 #: netbox/dcim/forms/filtersets.py:1272 netbox/dcim/forms/filtersets.py:1296 @@ -662,14 +661,14 @@ msgstr "运营商账户" #: netbox/circuits/forms/filtersets.py:150 netbox/core/forms/filtersets.py:38 #: netbox/core/forms/filtersets.py:79 netbox/core/tables/data.py:23 #: netbox/core/tables/jobs.py:26 netbox/core/tables/tasks.py:88 -#: netbox/dcim/forms/bulk_edit.py:106 netbox/dcim/forms/bulk_edit.py:181 -#: netbox/dcim/forms/bulk_edit.py:351 netbox/dcim/forms/bulk_edit.py:700 -#: netbox/dcim/forms/bulk_edit.py:756 netbox/dcim/forms/bulk_edit.py:788 -#: netbox/dcim/forms/bulk_edit.py:915 netbox/dcim/forms/bulk_edit.py:1701 +#: netbox/dcim/forms/bulk_edit.py:107 netbox/dcim/forms/bulk_edit.py:182 +#: netbox/dcim/forms/bulk_edit.py:352 netbox/dcim/forms/bulk_edit.py:706 +#: netbox/dcim/forms/bulk_edit.py:771 netbox/dcim/forms/bulk_edit.py:803 +#: netbox/dcim/forms/bulk_edit.py:930 netbox/dcim/forms/bulk_edit.py:1744 #: netbox/dcim/forms/bulk_import.py:88 netbox/dcim/forms/bulk_import.py:147 -#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:505 -#: netbox/dcim/forms/bulk_import.py:659 netbox/dcim/forms/bulk_import.py:1207 -#: netbox/dcim/forms/bulk_import.py:1371 netbox/dcim/forms/bulk_import.py:1435 +#: netbox/dcim/forms/bulk_import.py:248 netbox/dcim/forms/bulk_import.py:527 +#: netbox/dcim/forms/bulk_import.py:681 netbox/dcim/forms/bulk_import.py:1229 +#: netbox/dcim/forms/bulk_import.py:1393 netbox/dcim/forms/bulk_import.py:1457 #: netbox/dcim/forms/filtersets.py:178 netbox/dcim/forms/filtersets.py:237 #: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:799 #: netbox/dcim/forms/filtersets.py:924 netbox/dcim/forms/filtersets.py:958 @@ -678,13 +677,13 @@ msgstr "运营商账户" #: netbox/dcim/tables/devices.py:1063 netbox/dcim/tables/modules.py:69 #: netbox/dcim/tables/power.py:74 netbox/dcim/tables/racks.py:126 #: netbox/dcim/tables/sites.py:82 netbox/dcim/tables/sites.py:138 -#: netbox/ipam/forms/bulk_edit.py:255 netbox/ipam/forms/bulk_edit.py:305 -#: netbox/ipam/forms/bulk_edit.py:353 netbox/ipam/forms/bulk_edit.py:551 +#: netbox/ipam/forms/bulk_edit.py:256 netbox/ipam/forms/bulk_edit.py:306 +#: netbox/ipam/forms/bulk_edit.py:354 netbox/ipam/forms/bulk_edit.py:506 #: netbox/ipam/forms/bulk_import.py:192 netbox/ipam/forms/bulk_import.py:257 -#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:450 +#: netbox/ipam/forms/bulk_import.py:293 netbox/ipam/forms/bulk_import.py:474 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:281 #: netbox/ipam/forms/filtersets.py:355 netbox/ipam/forms/filtersets.py:501 -#: netbox/ipam/forms/model_forms.py:468 netbox/ipam/tables/ip.py:237 +#: netbox/ipam/forms/model_forms.py:501 netbox/ipam/tables/ip.py:237 #: netbox/ipam/tables/ip.py:312 netbox/ipam/tables/ip.py:363 #: netbox/ipam/tables/ip.py:426 netbox/ipam/tables/ip.py:453 #: netbox/ipam/tables/vlans.py:126 netbox/ipam/tables/vlans.py:232 @@ -695,7 +694,7 @@ msgstr "运营商账户" #: netbox/templates/dcim/location.html:45 netbox/templates/dcim/module.html:69 #: netbox/templates/dcim/powerfeed.html:36 netbox/templates/dcim/rack.html:41 #: netbox/templates/dcim/site.html:43 -#: netbox/templates/extras/script_list.html:47 +#: netbox/templates/extras/script_list.html:48 #: netbox/templates/ipam/ipaddress.html:37 #: netbox/templates/ipam/iprange.html:54 netbox/templates/ipam/prefix.html:73 #: netbox/templates/ipam/vlan.html:48 @@ -731,30 +730,30 @@ msgstr "状态" #: netbox/circuits/forms/bulk_import.py:98 #: netbox/circuits/forms/bulk_import.py:158 #: netbox/circuits/forms/filtersets.py:119 -#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:122 -#: netbox/dcim/forms/bulk_edit.py:187 netbox/dcim/forms/bulk_edit.py:346 -#: netbox/dcim/forms/bulk_edit.py:461 netbox/dcim/forms/bulk_edit.py:690 -#: netbox/dcim/forms/bulk_edit.py:794 netbox/dcim/forms/bulk_edit.py:1706 +#: netbox/circuits/forms/filtersets.py:241 netbox/dcim/forms/bulk_edit.py:123 +#: netbox/dcim/forms/bulk_edit.py:188 netbox/dcim/forms/bulk_edit.py:347 +#: netbox/dcim/forms/bulk_edit.py:467 netbox/dcim/forms/bulk_edit.py:696 +#: netbox/dcim/forms/bulk_edit.py:809 netbox/dcim/forms/bulk_edit.py:1749 #: netbox/dcim/forms/bulk_import.py:107 netbox/dcim/forms/bulk_import.py:152 -#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:334 -#: netbox/dcim/forms/bulk_import.py:479 netbox/dcim/forms/bulk_import.py:1219 -#: netbox/dcim/forms/bulk_import.py:1428 netbox/dcim/forms/filtersets.py:173 +#: netbox/dcim/forms/bulk_import.py:241 netbox/dcim/forms/bulk_import.py:356 +#: netbox/dcim/forms/bulk_import.py:501 netbox/dcim/forms/bulk_import.py:1241 +#: netbox/dcim/forms/bulk_import.py:1450 netbox/dcim/forms/filtersets.py:173 #: netbox/dcim/forms/filtersets.py:205 netbox/dcim/forms/filtersets.py:323 #: netbox/dcim/forms/filtersets.py:399 netbox/dcim/forms/filtersets.py:420 #: netbox/dcim/forms/filtersets.py:722 netbox/dcim/forms/filtersets.py:916 #: netbox/dcim/forms/filtersets.py:978 netbox/dcim/forms/filtersets.py:1008 #: netbox/dcim/forms/filtersets.py:1130 netbox/dcim/tables/power.py:88 #: netbox/extras/filtersets.py:612 netbox/extras/forms/filtersets.py:323 -#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:42 -#: netbox/ipam/forms/bulk_edit.py:67 netbox/ipam/forms/bulk_edit.py:111 -#: netbox/ipam/forms/bulk_edit.py:140 netbox/ipam/forms/bulk_edit.py:165 -#: netbox/ipam/forms/bulk_edit.py:250 netbox/ipam/forms/bulk_edit.py:300 -#: netbox/ipam/forms/bulk_edit.py:348 netbox/ipam/forms/bulk_edit.py:546 +#: netbox/extras/forms/filtersets.py:396 netbox/ipam/forms/bulk_edit.py:43 +#: netbox/ipam/forms/bulk_edit.py:68 netbox/ipam/forms/bulk_edit.py:112 +#: netbox/ipam/forms/bulk_edit.py:141 netbox/ipam/forms/bulk_edit.py:166 +#: netbox/ipam/forms/bulk_edit.py:251 netbox/ipam/forms/bulk_edit.py:301 +#: netbox/ipam/forms/bulk_edit.py:349 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_import.py:38 netbox/ipam/forms/bulk_import.py:67 #: netbox/ipam/forms/bulk_import.py:95 netbox/ipam/forms/bulk_import.py:115 #: netbox/ipam/forms/bulk_import.py:135 netbox/ipam/forms/bulk_import.py:164 #: netbox/ipam/forms/bulk_import.py:250 netbox/ipam/forms/bulk_import.py:286 -#: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/filtersets.py:48 +#: netbox/ipam/forms/bulk_import.py:467 netbox/ipam/forms/filtersets.py:48 #: netbox/ipam/forms/filtersets.py:68 netbox/ipam/forms/filtersets.py:100 #: netbox/ipam/forms/filtersets.py:120 netbox/ipam/forms/filtersets.py:143 #: netbox/ipam/forms/filtersets.py:174 netbox/ipam/forms/filtersets.py:267 @@ -824,11 +823,11 @@ msgstr "服务参数" #: netbox/circuits/forms/model_forms.py:183 #: netbox/dcim/forms/model_forms.py:139 netbox/dcim/forms/model_forms.py:181 #: netbox/dcim/forms/model_forms.py:266 netbox/dcim/forms/model_forms.py:323 -#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1692 +#: netbox/dcim/forms/model_forms.py:768 netbox/dcim/forms/model_forms.py:1699 #: netbox/ipam/forms/model_forms.py:64 netbox/ipam/forms/model_forms.py:81 #: netbox/ipam/forms/model_forms.py:115 netbox/ipam/forms/model_forms.py:136 #: netbox/ipam/forms/model_forms.py:160 netbox/ipam/forms/model_forms.py:232 -#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:316 +#: netbox/ipam/forms/model_forms.py:261 netbox/ipam/forms/model_forms.py:320 #: netbox/netbox/navigation/menu.py:24 #: netbox/templates/dcim/device_edit.html:85 #: netbox/templates/dcim/htmx/cable_edit.html:72 @@ -860,11 +859,11 @@ msgstr "端口速度 (Kbps)" msgid "Upstream speed (Kbps)" msgstr "上行速度 (Kbps)" -#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:951 -#: netbox/dcim/forms/bulk_edit.py:1315 netbox/dcim/forms/bulk_edit.py:1332 -#: netbox/dcim/forms/bulk_edit.py:1349 netbox/dcim/forms/bulk_edit.py:1367 -#: netbox/dcim/forms/bulk_edit.py:1455 netbox/dcim/forms/bulk_edit.py:1594 -#: netbox/dcim/forms/bulk_edit.py:1611 +#: netbox/circuits/forms/bulk_edit.py:206 netbox/dcim/forms/bulk_edit.py:966 +#: netbox/dcim/forms/bulk_edit.py:1330 netbox/dcim/forms/bulk_edit.py:1347 +#: netbox/dcim/forms/bulk_edit.py:1364 netbox/dcim/forms/bulk_edit.py:1382 +#: netbox/dcim/forms/bulk_edit.py:1477 netbox/dcim/forms/bulk_edit.py:1637 +#: netbox/dcim/forms/bulk_edit.py:1654 msgid "Mark connected" msgstr "标记已连接" @@ -911,10 +910,10 @@ msgstr "线路类型" #: netbox/circuits/forms/bulk_import.py:95 netbox/dcim/forms/bulk_import.py:90 #: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:250 -#: netbox/dcim/forms/bulk_import.py:507 netbox/dcim/forms/bulk_import.py:661 -#: netbox/dcim/forms/bulk_import.py:1373 netbox/ipam/forms/bulk_import.py:194 +#: netbox/dcim/forms/bulk_import.py:529 netbox/dcim/forms/bulk_import.py:683 +#: netbox/dcim/forms/bulk_import.py:1395 netbox/ipam/forms/bulk_import.py:194 #: netbox/ipam/forms/bulk_import.py:259 netbox/ipam/forms/bulk_import.py:295 -#: netbox/ipam/forms/bulk_import.py:452 +#: netbox/ipam/forms/bulk_import.py:476 #: netbox/virtualization/forms/bulk_import.py:56 #: netbox/virtualization/forms/bulk_import.py:82 #: netbox/vpn/forms/bulk_import.py:39 netbox/wireless/forms/bulk_import.py:45 @@ -924,13 +923,13 @@ msgstr "运行状态" #: netbox/circuits/forms/bulk_import.py:102 #: netbox/circuits/forms/bulk_import.py:162 #: netbox/dcim/forms/bulk_import.py:111 netbox/dcim/forms/bulk_import.py:156 -#: netbox/dcim/forms/bulk_import.py:338 netbox/dcim/forms/bulk_import.py:483 -#: netbox/dcim/forms/bulk_import.py:1223 netbox/dcim/forms/bulk_import.py:1368 -#: netbox/dcim/forms/bulk_import.py:1432 netbox/ipam/forms/bulk_import.py:42 +#: netbox/dcim/forms/bulk_import.py:360 netbox/dcim/forms/bulk_import.py:505 +#: netbox/dcim/forms/bulk_import.py:1245 netbox/dcim/forms/bulk_import.py:1390 +#: netbox/dcim/forms/bulk_import.py:1454 netbox/ipam/forms/bulk_import.py:42 #: netbox/ipam/forms/bulk_import.py:71 netbox/ipam/forms/bulk_import.py:99 #: netbox/ipam/forms/bulk_import.py:119 netbox/ipam/forms/bulk_import.py:139 #: netbox/ipam/forms/bulk_import.py:168 netbox/ipam/forms/bulk_import.py:254 -#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:447 +#: netbox/ipam/forms/bulk_import.py:290 netbox/ipam/forms/bulk_import.py:471 #: netbox/virtualization/forms/bulk_import.py:70 #: netbox/virtualization/forms/bulk_import.py:119 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:59 @@ -955,12 +954,12 @@ msgstr "运营商网络" #: netbox/circuits/forms/filtersets.py:30 #: netbox/circuits/forms/filtersets.py:118 -#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:338 -#: netbox/dcim/forms/bulk_edit.py:441 netbox/dcim/forms/bulk_edit.py:682 -#: netbox/dcim/forms/bulk_edit.py:729 netbox/dcim/forms/bulk_edit.py:882 -#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:315 -#: netbox/dcim/forms/bulk_import.py:546 netbox/dcim/forms/bulk_import.py:1317 -#: netbox/dcim/forms/bulk_import.py:1351 netbox/dcim/forms/filtersets.py:95 +#: netbox/circuits/forms/filtersets.py:200 netbox/dcim/forms/bulk_edit.py:339 +#: netbox/dcim/forms/bulk_edit.py:447 netbox/dcim/forms/bulk_edit.py:688 +#: netbox/dcim/forms/bulk_edit.py:743 netbox/dcim/forms/bulk_edit.py:897 +#: netbox/dcim/forms/bulk_import.py:235 netbox/dcim/forms/bulk_import.py:337 +#: netbox/dcim/forms/bulk_import.py:568 netbox/dcim/forms/bulk_import.py:1339 +#: netbox/dcim/forms/bulk_import.py:1373 netbox/dcim/forms/filtersets.py:95 #: netbox/dcim/forms/filtersets.py:322 netbox/dcim/forms/filtersets.py:356 #: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:447 #: netbox/dcim/forms/filtersets.py:719 netbox/dcim/forms/filtersets.py:762 @@ -977,9 +976,9 @@ msgstr "运营商网络" #: netbox/dcim/tables/devices.py:157 netbox/dcim/tables/power.py:30 #: netbox/dcim/tables/racks.py:118 netbox/dcim/tables/racks.py:212 #: netbox/extras/filtersets.py:536 netbox/extras/forms/filtersets.py:320 -#: netbox/ipam/forms/bulk_edit.py:460 netbox/ipam/forms/filtersets.py:173 -#: netbox/ipam/forms/filtersets.py:414 netbox/ipam/forms/filtersets.py:437 -#: netbox/ipam/forms/filtersets.py:467 netbox/templates/dcim/device.html:26 +#: netbox/ipam/forms/filtersets.py:173 netbox/ipam/forms/filtersets.py:414 +#: netbox/ipam/forms/filtersets.py:437 netbox/ipam/forms/filtersets.py:467 +#: netbox/templates/dcim/device.html:26 #: netbox/templates/dcim/device_edit.html:30 #: netbox/templates/dcim/inc/cable_termination.html:12 #: netbox/templates/dcim/location.html:26 @@ -1008,8 +1007,8 @@ msgid "Contacts" msgstr "联系" #: netbox/circuits/forms/filtersets.py:37 -#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:112 -#: netbox/dcim/forms/bulk_edit.py:313 netbox/dcim/forms/bulk_edit.py:857 +#: netbox/circuits/forms/filtersets.py:157 netbox/dcim/forms/bulk_edit.py:113 +#: netbox/dcim/forms/bulk_edit.py:314 netbox/dcim/forms/bulk_edit.py:872 #: netbox/dcim/forms/bulk_import.py:93 netbox/dcim/forms/filtersets.py:73 #: netbox/dcim/forms/filtersets.py:185 netbox/dcim/forms/filtersets.py:211 #: netbox/dcim/forms/filtersets.py:334 netbox/dcim/forms/filtersets.py:425 @@ -1017,13 +1016,12 @@ msgstr "联系" #: netbox/dcim/forms/filtersets.py:1013 netbox/dcim/forms/filtersets.py:1097 #: netbox/dcim/forms/filtersets.py:1136 netbox/dcim/forms/filtersets.py:1576 #: netbox/dcim/forms/filtersets.py:1600 netbox/dcim/forms/filtersets.py:1624 -#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:375 +#: netbox/dcim/forms/model_forms.py:112 netbox/dcim/forms/object_create.py:367 #: netbox/dcim/tables/devices.py:143 netbox/dcim/tables/sites.py:85 -#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:207 -#: netbox/ipam/forms/bulk_edit.py:441 netbox/ipam/forms/bulk_edit.py:519 -#: netbox/ipam/forms/filtersets.py:217 netbox/ipam/forms/filtersets.py:422 -#: netbox/ipam/forms/filtersets.py:475 netbox/templates/dcim/device.html:18 -#: netbox/templates/dcim/rack.html:16 +#: netbox/extras/filtersets.py:503 netbox/ipam/forms/bulk_edit.py:208 +#: netbox/ipam/forms/bulk_edit.py:474 netbox/ipam/forms/filtersets.py:217 +#: netbox/ipam/forms/filtersets.py:422 netbox/ipam/forms/filtersets.py:475 +#: netbox/templates/dcim/device.html:18 netbox/templates/dcim/rack.html:16 #: netbox/templates/dcim/rackreservation.html:22 #: netbox/templates/dcim/region.html:26 netbox/templates/dcim/site.html:31 #: netbox/templates/ipam/prefix.html:49 netbox/templates/ipam/vlan.html:16 @@ -1036,16 +1034,16 @@ msgid "Region" msgstr "地区" #: netbox/circuits/forms/filtersets.py:42 -#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:321 -#: netbox/dcim/forms/bulk_edit.py:865 netbox/dcim/forms/filtersets.py:78 +#: netbox/circuits/forms/filtersets.py:162 netbox/dcim/forms/bulk_edit.py:322 +#: netbox/dcim/forms/bulk_edit.py:880 netbox/dcim/forms/filtersets.py:78 #: netbox/dcim/forms/filtersets.py:190 netbox/dcim/forms/filtersets.py:216 #: netbox/dcim/forms/filtersets.py:347 netbox/dcim/forms/filtersets.py:430 #: netbox/dcim/forms/filtersets.py:744 netbox/dcim/forms/filtersets.py:988 #: netbox/dcim/forms/filtersets.py:1102 netbox/dcim/forms/filtersets.py:1141 -#: netbox/dcim/forms/object_create.py:383 netbox/extras/filtersets.py:520 -#: netbox/ipam/forms/bulk_edit.py:212 netbox/ipam/forms/bulk_edit.py:448 -#: netbox/ipam/forms/bulk_edit.py:524 netbox/ipam/forms/filtersets.py:222 -#: netbox/ipam/forms/filtersets.py:427 netbox/ipam/forms/filtersets.py:480 +#: netbox/dcim/forms/object_create.py:375 netbox/extras/filtersets.py:520 +#: netbox/ipam/forms/bulk_edit.py:213 netbox/ipam/forms/bulk_edit.py:479 +#: netbox/ipam/forms/filtersets.py:222 netbox/ipam/forms/filtersets.py:427 +#: netbox/ipam/forms/filtersets.py:480 #: netbox/virtualization/forms/bulk_edit.py:86 #: netbox/virtualization/forms/filtersets.py:69 #: netbox/virtualization/forms/filtersets.py:138 @@ -1057,7 +1055,7 @@ msgstr "站点组" #: netbox/circuits/forms/filtersets.py:83 #: netbox/circuits/forms/filtersets.py:102 #: netbox/circuits/forms/filtersets.py:117 netbox/core/forms/filtersets.py:67 -#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:828 +#: netbox/core/forms/filtersets.py:135 netbox/dcim/forms/bulk_edit.py:843 #: netbox/dcim/forms/filtersets.py:172 netbox/dcim/forms/filtersets.py:204 #: netbox/dcim/forms/filtersets.py:915 netbox/dcim/forms/filtersets.py:1007 #: netbox/dcim/forms/filtersets.py:1131 netbox/dcim/forms/filtersets.py:1239 @@ -1096,9 +1094,9 @@ msgstr "账户" msgid "Term Side" msgstr "线路终端侧" -#: netbox/circuits/forms/filtersets.py:250 +#: netbox/circuits/forms/filtersets.py:250 netbox/dcim/forms/bulk_edit.py:1557 #: netbox/extras/forms/model_forms.py:582 netbox/ipam/forms/filtersets.py:142 -#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/filtersets.py:546 netbox/ipam/forms/model_forms.py:327 #: netbox/templates/extras/configcontext.html:60 #: netbox/templates/ipam/ipaddress.html:59 #: netbox/templates/ipam/vlan_edit.html:30 @@ -1108,11 +1106,11 @@ msgstr "分配" #: netbox/circuits/forms/filtersets.py:265 #: netbox/circuits/forms/model_forms.py:195 -#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:117 +#: netbox/circuits/tables/circuits.py:155 netbox/dcim/forms/bulk_edit.py:118 #: netbox/dcim/forms/bulk_import.py:100 netbox/dcim/forms/model_forms.py:117 #: netbox/dcim/tables/sites.py:89 netbox/extras/forms/filtersets.py:480 -#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:538 -#: netbox/ipam/forms/bulk_import.py:436 netbox/ipam/forms/model_forms.py:528 +#: netbox/ipam/filtersets.py:999 netbox/ipam/forms/bulk_edit.py:493 +#: netbox/ipam/forms/bulk_import.py:460 netbox/ipam/forms/model_forms.py:561 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:122 #: netbox/ipam/tables/vlans.py:226 #: netbox/templates/circuits/circuitgroupassignment.html:22 @@ -1184,20 +1182,20 @@ msgid "Unique circuit ID" msgstr "唯一线路 ID" #: netbox/circuits/models/circuits.py:69 netbox/core/models/data.py:52 -#: netbox/core/models/jobs.py:84 netbox/dcim/models/cables.py:49 +#: netbox/core/models/jobs.py:85 netbox/dcim/models/cables.py:49 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:1173 -#: netbox/dcim/models/devices.py:1399 netbox/dcim/models/power.py:96 +#: netbox/dcim/models/devices.py:1404 netbox/dcim/models/power.py:96 #: netbox/dcim/models/racks.py:297 netbox/dcim/models/sites.py:154 #: netbox/dcim/models/sites.py:266 netbox/ipam/models/ip.py:253 #: netbox/ipam/models/ip.py:522 netbox/ipam/models/ip.py:730 -#: netbox/ipam/models/vlans.py:195 netbox/virtualization/models/clusters.py:74 +#: netbox/ipam/models/vlans.py:211 netbox/virtualization/models/clusters.py:74 #: netbox/virtualization/models/virtualmachines.py:84 #: netbox/vpn/models/tunnels.py:40 netbox/wireless/models.py:95 #: netbox/wireless/models.py:159 msgid "status" msgstr "状态" -#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:19 +#: netbox/circuits/models/circuits.py:84 netbox/templates/core/plugin.html:20 msgid "installed" msgstr "安装时间" @@ -1315,11 +1313,11 @@ msgstr "线路终结不能同时连接到站点和运营商网络。" #: netbox/circuits/models/providers.py:22 #: netbox/circuits/models/providers.py:66 #: netbox/circuits/models/providers.py:104 netbox/core/models/data.py:39 -#: netbox/core/models/jobs.py:45 +#: netbox/core/models/jobs.py:46 #: netbox/dcim/models/device_component_templates.py:43 #: netbox/dcim/models/device_components.py:53 -#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1330 -#: netbox/dcim/models/devices.py:1395 netbox/dcim/models/power.py:39 +#: netbox/dcim/models/devices.py:593 netbox/dcim/models/devices.py:1335 +#: netbox/dcim/models/devices.py:1400 netbox/dcim/models/power.py:39 #: netbox/dcim/models/power.py:92 netbox/dcim/models/racks.py:262 #: netbox/dcim/models/sites.py:138 netbox/extras/models/configs.py:36 #: netbox/extras/models/configs.py:215 netbox/extras/models/customfields.py:92 @@ -1330,7 +1328,7 @@ msgstr "线路终结不能同时连接到站点和运营商网络。" #: netbox/extras/models/scripts.py:30 netbox/extras/models/staging.py:26 #: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:25 #: netbox/ipam/models/services.py:52 netbox/ipam/models/services.py:88 -#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:184 +#: netbox/ipam/models/vlans.py:36 netbox/ipam/models/vlans.py:200 #: netbox/ipam/models/vrfs.py:22 netbox/ipam/models/vrfs.py:79 #: netbox/netbox/models/__init__.py:137 netbox/netbox/models/__init__.py:181 #: netbox/tenancy/models/contacts.py:64 netbox/tenancy/models/tenants.py:20 @@ -1418,7 +1416,7 @@ msgstr "运营商网络" #: netbox/extras/tables/tables.py:361 netbox/extras/tables/tables.py:378 #: netbox/extras/tables/tables.py:401 netbox/extras/tables/tables.py:439 #: netbox/extras/tables/tables.py:491 netbox/extras/tables/tables.py:514 -#: netbox/ipam/forms/bulk_edit.py:406 netbox/ipam/forms/filtersets.py:386 +#: netbox/ipam/forms/bulk_edit.py:407 netbox/ipam/forms/filtersets.py:386 #: netbox/ipam/tables/asn.py:16 netbox/ipam/tables/ip.py:85 #: netbox/ipam/tables/ip.py:160 netbox/ipam/tables/services.py:15 #: netbox/ipam/tables/services.py:40 netbox/ipam/tables/vlans.py:64 @@ -1429,7 +1427,7 @@ msgstr "运营商网络" #: netbox/templates/circuits/provideraccount.html:28 #: netbox/templates/circuits/providernetwork.html:24 #: netbox/templates/core/datasource.html:34 netbox/templates/core/job.html:44 -#: netbox/templates/core/plugin.html:53 +#: netbox/templates/core/plugin.html:54 #: netbox/templates/core/rq_worker.html:43 #: netbox/templates/dcim/consoleport.html:28 #: netbox/templates/dcim/consoleserverport.html:28 @@ -1460,7 +1458,7 @@ msgstr "运营商网络" #: netbox/templates/extras/exporttemplate.html:15 #: netbox/templates/extras/notificationgroup.html:14 #: netbox/templates/extras/savedfilter.html:13 -#: netbox/templates/extras/script_list.html:44 +#: netbox/templates/extras/script_list.html:45 #: netbox/templates/extras/tag.html:14 netbox/templates/extras/webhook.html:13 #: netbox/templates/ipam/asnrange.html:15 #: netbox/templates/ipam/fhrpgroup.html:30 netbox/templates/ipam/rir.html:22 @@ -1624,7 +1622,7 @@ msgstr "完成" #: netbox/core/choices.py:22 netbox/core/choices.py:59 #: netbox/core/constants.py:20 netbox/core/tables/tasks.py:34 #: netbox/dcim/choices.py:187 netbox/dcim/choices.py:239 -#: netbox/dcim/choices.py:1607 netbox/virtualization/choices.py:47 +#: netbox/dcim/choices.py:1609 netbox/virtualization/choices.py:47 msgid "Failed" msgstr "故障" @@ -1691,7 +1689,7 @@ msgid "Cancelled" msgstr "已取消" #: netbox/core/data_backends.py:32 netbox/core/tables/plugins.py:51 -#: netbox/templates/core/plugin.html:87 +#: netbox/templates/core/plugin.html:88 #: netbox/templates/dcim/interface.html:216 msgid "Local" msgstr "本地" @@ -1778,8 +1776,8 @@ msgid "User name" msgstr "用户名" #: netbox/core/forms/bulk_edit.py:25 netbox/core/forms/filtersets.py:43 -#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1122 -#: netbox/dcim/forms/bulk_edit.py:1400 netbox/dcim/forms/filtersets.py:1370 +#: netbox/core/tables/data.py:26 netbox/dcim/forms/bulk_edit.py:1137 +#: netbox/dcim/forms/bulk_edit.py:1415 netbox/dcim/forms/filtersets.py:1370 #: netbox/dcim/tables/devices.py:553 netbox/dcim/tables/devicetypes.py:224 #: netbox/extras/forms/bulk_edit.py:123 netbox/extras/forms/bulk_edit.py:187 #: netbox/extras/forms/bulk_edit.py:246 netbox/extras/forms/filtersets.py:142 @@ -1883,7 +1881,7 @@ msgid "Completed before" msgstr "完成后" #: netbox/core/forms/filtersets.py:126 netbox/core/forms/filtersets.py:155 -#: netbox/dcim/forms/bulk_edit.py:456 netbox/dcim/forms/filtersets.py:418 +#: netbox/dcim/forms/bulk_edit.py:462 netbox/dcim/forms/filtersets.py:418 #: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/model_forms.py:316 #: netbox/extras/forms/filtersets.py:456 netbox/extras/forms/filtersets.py:475 #: netbox/extras/tables/tables.py:302 netbox/extras/tables/tables.py:342 @@ -1948,9 +1946,9 @@ msgstr "必须上传文件或选择数据文件进行同步" msgid "Rack Elevations" msgstr "机柜立面图" -#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1518 -#: netbox/dcim/forms/bulk_edit.py:969 netbox/dcim/forms/bulk_edit.py:1357 -#: netbox/dcim/forms/bulk_edit.py:1375 netbox/dcim/tables/racks.py:158 +#: netbox/core/forms/model_forms.py:157 netbox/dcim/choices.py:1520 +#: netbox/dcim/forms/bulk_edit.py:984 netbox/dcim/forms/bulk_edit.py:1372 +#: netbox/dcim/forms/bulk_edit.py:1390 netbox/dcim/tables/racks.py:158 #: netbox/netbox/navigation/menu.py:291 netbox/netbox/navigation/menu.py:295 msgid "Power" msgstr "电源" @@ -2050,7 +2048,7 @@ msgid "Change logging is not supported for this object type ({type})." msgstr "此对象类型 ({type}) 不支持更改日志记录。" #: netbox/core/models/config.py:18 netbox/core/models/data.py:266 -#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:49 +#: netbox/core/models/files.py:27 netbox/core/models/jobs.py:50 #: netbox/extras/models/models.py:730 netbox/extras/models/notifications.py:39 #: netbox/extras/models/notifications.py:186 #: netbox/netbox/models/features.py:53 netbox/users/models/tokens.py:32 @@ -2110,7 +2108,7 @@ msgstr "类型" #: netbox/core/models/data.py:49 netbox/extras/choices.py:37 #: netbox/extras/models/models.py:164 netbox/extras/tables/tables.py:656 #: netbox/templates/core/datasource.html:58 -#: netbox/templates/core/plugin.html:65 +#: netbox/templates/core/plugin.html:66 msgid "URL" msgstr "URL" @@ -2226,58 +2224,58 @@ msgstr "托管文件" msgid "managed files" msgstr "托管文件" -#: netbox/core/models/jobs.py:53 +#: netbox/core/models/jobs.py:54 msgid "scheduled" msgstr "计划" -#: netbox/core/models/jobs.py:58 +#: netbox/core/models/jobs.py:59 msgid "interval" msgstr "间隔" -#: netbox/core/models/jobs.py:64 +#: netbox/core/models/jobs.py:65 msgid "Recurrence interval (in minutes)" msgstr "重复间隔(以分钟为单位)" -#: netbox/core/models/jobs.py:67 +#: netbox/core/models/jobs.py:68 msgid "started" msgstr "已经开始" -#: netbox/core/models/jobs.py:72 +#: netbox/core/models/jobs.py:73 msgid "completed" msgstr "已经完成" -#: netbox/core/models/jobs.py:90 netbox/extras/models/models.py:101 +#: netbox/core/models/jobs.py:91 netbox/extras/models/models.py:101 #: netbox/extras/models/staging.py:87 msgid "data" msgstr "数据" -#: netbox/core/models/jobs.py:95 +#: netbox/core/models/jobs.py:96 msgid "error" msgstr "错误" -#: netbox/core/models/jobs.py:100 +#: netbox/core/models/jobs.py:101 msgid "job ID" msgstr "任务ID" -#: netbox/core/models/jobs.py:111 +#: netbox/core/models/jobs.py:112 msgid "job" msgstr "任务" -#: netbox/core/models/jobs.py:112 +#: netbox/core/models/jobs.py:113 msgid "jobs" msgstr "任务" -#: netbox/core/models/jobs.py:135 +#: netbox/core/models/jobs.py:136 #, python-brace-format msgid "Jobs cannot be assigned to this object type ({type})." msgstr "任务不能分配给此对象类型 ({type})" -#: netbox/core/models/jobs.py:185 +#: netbox/core/models/jobs.py:190 #, python-brace-format msgid "Invalid status for job termination. Choices are: {choices}" msgstr "作业终止状态无效。选项有:{choices}" -#: netbox/core/models/jobs.py:216 +#: netbox/core/models/jobs.py:221 msgid "" "enqueue() cannot be called with values for both schedule_at and immediate." msgstr "不能使用 schedule_at 和 immediate 的值调用 enqueue ()。" @@ -2360,7 +2358,7 @@ msgstr "Netbox 最高版本" msgid "No plugin data found" msgstr "未找到插件数据" -#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:61 +#: netbox/core/tables/plugins.py:48 netbox/templates/core/plugin.html:62 msgid "Author" msgstr "作者" @@ -2368,7 +2366,7 @@ msgstr "作者" msgid "Installed" msgstr "已安装" -#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:83 +#: netbox/core/tables/plugins.py:57 netbox/templates/core/plugin.html:84 msgid "Certified" msgstr "已认证" @@ -2494,11 +2492,11 @@ msgstr "工作 {id} 已停止。" msgid "Failed to stop job {id}" msgstr "无法停止作业 {id}" -#: netbox/core/views.py:678 +#: netbox/core/views.py:674 msgid "Plugins catalog could not be loaded" msgstr "无法加载插件目录" -#: netbox/core/views.py:712 +#: netbox/core/views.py:708 #, python-brace-format msgid "Plugin {name} not found" msgstr "插件 {name} 未找到" @@ -2518,7 +2516,7 @@ msgid "Staging" msgstr "暂存" #: netbox/dcim/choices.py:23 netbox/dcim/choices.py:189 -#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1531 +#: netbox/dcim/choices.py:240 netbox/dcim/choices.py:1533 #: netbox/virtualization/choices.py:23 netbox/virtualization/choices.py:48 msgid "Decommissioning" msgstr "报废" @@ -2582,7 +2580,7 @@ msgstr "已弃用" msgid "Millimeters" msgstr "毫米" -#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1553 +#: netbox/dcim/choices.py:115 netbox/dcim/choices.py:1555 msgid "Inches" msgstr "英寸" @@ -2596,15 +2594,15 @@ msgstr "从前向后" msgid "Rear to front" msgstr "从后向前" -#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:68 -#: netbox/dcim/forms/bulk_edit.py:87 netbox/dcim/forms/bulk_edit.py:173 -#: netbox/dcim/forms/bulk_edit.py:1405 netbox/dcim/forms/bulk_import.py:60 +#: netbox/dcim/choices.py:151 netbox/dcim/forms/bulk_edit.py:69 +#: netbox/dcim/forms/bulk_edit.py:88 netbox/dcim/forms/bulk_edit.py:174 +#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/forms/bulk_import.py:60 #: netbox/dcim/forms/bulk_import.py:74 netbox/dcim/forms/bulk_import.py:137 -#: netbox/dcim/forms/bulk_import.py:566 netbox/dcim/forms/bulk_import.py:833 -#: netbox/dcim/forms/bulk_import.py:1088 netbox/dcim/forms/filtersets.py:234 +#: netbox/dcim/forms/bulk_import.py:588 netbox/dcim/forms/bulk_import.py:855 +#: netbox/dcim/forms/bulk_import.py:1110 netbox/dcim/forms/filtersets.py:234 #: netbox/dcim/forms/model_forms.py:74 netbox/dcim/forms/model_forms.py:93 -#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1062 -#: netbox/dcim/forms/model_forms.py:1502 +#: netbox/dcim/forms/model_forms.py:170 netbox/dcim/forms/model_forms.py:1069 +#: netbox/dcim/forms/model_forms.py:1509 #: netbox/dcim/forms/object_import.py:176 netbox/dcim/tables/devices.py:656 #: netbox/dcim/tables/devices.py:869 netbox/dcim/tables/devices.py:954 #: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59 @@ -2684,7 +2682,7 @@ msgid "Top to bottom" msgstr "从上到下" #: netbox/dcim/choices.py:215 netbox/dcim/choices.py:259 -#: netbox/dcim/choices.py:1303 +#: netbox/dcim/choices.py:1305 msgid "Passive" msgstr "被动" @@ -2713,8 +2711,8 @@ msgid "Proprietary" msgstr "专用规格" #: netbox/dcim/choices.py:581 netbox/dcim/choices.py:824 -#: netbox/dcim/choices.py:1219 netbox/dcim/choices.py:1221 -#: netbox/dcim/choices.py:1447 netbox/dcim/choices.py:1449 +#: netbox/dcim/choices.py:1221 netbox/dcim/choices.py:1223 +#: netbox/dcim/choices.py:1449 netbox/dcim/choices.py:1451 #: netbox/netbox/navigation/menu.py:200 msgid "Other" msgstr "其他" @@ -2727,24 +2725,24 @@ msgstr "ITA/国际通用标准" msgid "Physical" msgstr "物理" -#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1023 +#: netbox/dcim/choices.py:855 netbox/dcim/choices.py:1024 msgid "Virtual" msgstr "虚拟" -#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1097 -#: netbox/dcim/forms/bulk_edit.py:1515 netbox/dcim/forms/filtersets.py:1330 -#: netbox/dcim/forms/model_forms.py:988 netbox/dcim/forms/model_forms.py:1397 +#: netbox/dcim/choices.py:856 netbox/dcim/choices.py:1099 +#: netbox/dcim/forms/bulk_edit.py:1563 netbox/dcim/forms/filtersets.py:1330 +#: netbox/dcim/forms/model_forms.py:995 netbox/dcim/forms/model_forms.py:1404 #: netbox/netbox/navigation/menu.py:140 netbox/netbox/navigation/menu.py:144 #: netbox/templates/dcim/interface.html:210 msgid "Wireless" msgstr "无线" -#: netbox/dcim/choices.py:1021 +#: netbox/dcim/choices.py:1022 msgid "Virtual interfaces" msgstr "虚拟接口" -#: netbox/dcim/choices.py:1024 netbox/dcim/forms/bulk_edit.py:1410 -#: netbox/dcim/forms/bulk_import.py:840 netbox/dcim/forms/model_forms.py:974 +#: netbox/dcim/choices.py:1025 netbox/dcim/forms/bulk_edit.py:1428 +#: netbox/dcim/forms/bulk_import.py:862 netbox/dcim/forms/model_forms.py:981 #: netbox/dcim/tables/devices.py:660 netbox/templates/dcim/interface.html:106 #: netbox/templates/virtualization/vminterface.html:43 #: netbox/virtualization/forms/bulk_edit.py:212 @@ -2753,27 +2751,27 @@ msgstr "虚拟接口" msgid "Bridge" msgstr "桥接" -#: netbox/dcim/choices.py:1025 +#: netbox/dcim/choices.py:1026 msgid "Link Aggregation Group (LAG)" msgstr "链路聚合组(LAG)" -#: netbox/dcim/choices.py:1029 +#: netbox/dcim/choices.py:1030 msgid "Ethernet (fixed)" msgstr "以太网(固定类型)" -#: netbox/dcim/choices.py:1044 +#: netbox/dcim/choices.py:1046 msgid "Ethernet (modular)" msgstr "以太网(模块)" -#: netbox/dcim/choices.py:1081 +#: netbox/dcim/choices.py:1083 msgid "Ethernet (backplane)" msgstr "以太网(背板)" -#: netbox/dcim/choices.py:1113 +#: netbox/dcim/choices.py:1115 msgid "Cellular" msgstr "蜂窝网络" -#: netbox/dcim/choices.py:1165 netbox/dcim/forms/filtersets.py:383 +#: netbox/dcim/choices.py:1167 netbox/dcim/forms/filtersets.py:383 #: netbox/dcim/forms/filtersets.py:809 netbox/dcim/forms/filtersets.py:963 #: netbox/dcim/forms/filtersets.py:1542 #: netbox/templates/dcim/inventoryitem.html:52 @@ -2781,130 +2779,130 @@ msgstr "蜂窝网络" msgid "Serial" msgstr "串口" -#: netbox/dcim/choices.py:1180 +#: netbox/dcim/choices.py:1182 msgid "Coaxial" msgstr "同轴电缆接口" -#: netbox/dcim/choices.py:1200 +#: netbox/dcim/choices.py:1202 msgid "Stacking" msgstr "堆叠" -#: netbox/dcim/choices.py:1250 +#: netbox/dcim/choices.py:1252 msgid "Half" msgstr "半双工" -#: netbox/dcim/choices.py:1251 +#: netbox/dcim/choices.py:1253 msgid "Full" msgstr "全双工" -#: netbox/dcim/choices.py:1252 netbox/netbox/preferences.py:31 +#: netbox/dcim/choices.py:1254 netbox/netbox/preferences.py:31 #: netbox/wireless/choices.py:480 msgid "Auto" msgstr "自动" -#: netbox/dcim/choices.py:1263 +#: netbox/dcim/choices.py:1265 msgid "Access" msgstr "接入" -#: netbox/dcim/choices.py:1264 netbox/ipam/tables/vlans.py:172 +#: netbox/dcim/choices.py:1266 netbox/ipam/tables/vlans.py:172 #: netbox/ipam/tables/vlans.py:217 #: netbox/templates/dcim/inc/interface_vlans_table.html:7 msgid "Tagged" msgstr "Trunk口" -#: netbox/dcim/choices.py:1265 +#: netbox/dcim/choices.py:1267 msgid "Tagged (All)" msgstr "Trunk口(允许所有VLAN)" -#: netbox/dcim/choices.py:1294 +#: netbox/dcim/choices.py:1296 msgid "IEEE Standard" msgstr "IEEE标准" -#: netbox/dcim/choices.py:1305 +#: netbox/dcim/choices.py:1307 msgid "Passive 24V (2-pair)" msgstr "24V(2对供电)" -#: netbox/dcim/choices.py:1306 +#: netbox/dcim/choices.py:1308 msgid "Passive 24V (4-pair)" msgstr "24V(4对供电)" -#: netbox/dcim/choices.py:1307 +#: netbox/dcim/choices.py:1309 msgid "Passive 48V (2-pair)" msgstr "48V(2对供电)" -#: netbox/dcim/choices.py:1308 +#: netbox/dcim/choices.py:1310 msgid "Passive 48V (4-pair)" msgstr "48V(4对供电)" -#: netbox/dcim/choices.py:1378 netbox/dcim/choices.py:1488 +#: netbox/dcim/choices.py:1380 netbox/dcim/choices.py:1490 msgid "Copper" msgstr "铜缆" -#: netbox/dcim/choices.py:1401 +#: netbox/dcim/choices.py:1403 msgid "Fiber Optic" msgstr "光纤" -#: netbox/dcim/choices.py:1434 netbox/dcim/choices.py:1517 +#: netbox/dcim/choices.py:1436 netbox/dcim/choices.py:1519 msgid "USB" msgstr "USB" -#: netbox/dcim/choices.py:1504 +#: netbox/dcim/choices.py:1506 msgid "Fiber" msgstr "光纤" -#: netbox/dcim/choices.py:1529 netbox/dcim/forms/filtersets.py:1227 +#: netbox/dcim/choices.py:1531 netbox/dcim/forms/filtersets.py:1227 msgid "Connected" msgstr "已连接" -#: netbox/dcim/choices.py:1548 netbox/wireless/choices.py:497 +#: netbox/dcim/choices.py:1550 netbox/wireless/choices.py:497 msgid "Kilometers" msgstr "公里" -#: netbox/dcim/choices.py:1549 netbox/templates/dcim/cable_trace.html:65 +#: netbox/dcim/choices.py:1551 netbox/templates/dcim/cable_trace.html:65 #: netbox/wireless/choices.py:498 msgid "Meters" msgstr "米" -#: netbox/dcim/choices.py:1550 +#: netbox/dcim/choices.py:1552 msgid "Centimeters" msgstr "厘米" -#: netbox/dcim/choices.py:1551 netbox/wireless/choices.py:499 +#: netbox/dcim/choices.py:1553 netbox/wireless/choices.py:499 msgid "Miles" msgstr "英里" -#: netbox/dcim/choices.py:1552 netbox/templates/dcim/cable_trace.html:66 +#: netbox/dcim/choices.py:1554 netbox/templates/dcim/cable_trace.html:66 #: netbox/wireless/choices.py:500 msgid "Feet" msgstr "英尺" -#: netbox/dcim/choices.py:1568 netbox/templates/dcim/device.html:327 +#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:327 #: netbox/templates/dcim/rack.html:107 msgid "Kilograms" msgstr "千克" -#: netbox/dcim/choices.py:1569 +#: netbox/dcim/choices.py:1571 msgid "Grams" msgstr "克" -#: netbox/dcim/choices.py:1570 netbox/templates/dcim/device.html:328 +#: netbox/dcim/choices.py:1572 netbox/templates/dcim/device.html:328 #: netbox/templates/dcim/rack.html:108 msgid "Pounds" msgstr "磅" -#: netbox/dcim/choices.py:1571 +#: netbox/dcim/choices.py:1573 msgid "Ounces" msgstr "盎司" -#: netbox/dcim/choices.py:1618 +#: netbox/dcim/choices.py:1620 msgid "Redundant" msgstr "冗余" -#: netbox/dcim/choices.py:1639 +#: netbox/dcim/choices.py:1641 msgid "Single phase" msgstr "单相电" -#: netbox/dcim/choices.py:1640 +#: netbox/dcim/choices.py:1642 msgid "Three-phase" msgstr "三相" @@ -3150,7 +3148,7 @@ msgstr "集群组(ID)" msgid "Device model (slug)" msgstr "设备模块(缩写)" -#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:516 +#: netbox/dcim/filtersets.py:1099 netbox/dcim/forms/bulk_edit.py:522 msgid "Is full depth" msgstr "是否全尺寸" @@ -3272,21 +3270,21 @@ msgstr "指定VLAN" msgid "Assigned VID" msgstr "指定VID" -#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1489 -#: netbox/dcim/forms/bulk_import.py:891 netbox/dcim/forms/filtersets.py:1428 -#: netbox/dcim/forms/model_forms.py:1378 +#: netbox/dcim/filtersets.py:1613 netbox/dcim/forms/bulk_edit.py:1531 +#: netbox/dcim/forms/bulk_import.py:913 netbox/dcim/forms/filtersets.py:1428 +#: netbox/dcim/forms/model_forms.py:1385 #: netbox/dcim/models/device_components.py:711 #: netbox/dcim/tables/devices.py:626 netbox/ipam/filtersets.py:316 #: netbox/ipam/filtersets.py:327 netbox/ipam/filtersets.py:483 #: netbox/ipam/filtersets.py:584 netbox/ipam/filtersets.py:595 -#: netbox/ipam/forms/bulk_edit.py:241 netbox/ipam/forms/bulk_edit.py:297 -#: netbox/ipam/forms/bulk_edit.py:339 netbox/ipam/forms/bulk_import.py:157 +#: netbox/ipam/forms/bulk_edit.py:242 netbox/ipam/forms/bulk_edit.py:298 +#: netbox/ipam/forms/bulk_edit.py:340 netbox/ipam/forms/bulk_import.py:157 #: netbox/ipam/forms/bulk_import.py:243 netbox/ipam/forms/bulk_import.py:279 #: netbox/ipam/forms/filtersets.py:67 netbox/ipam/forms/filtersets.py:172 #: netbox/ipam/forms/filtersets.py:309 netbox/ipam/forms/model_forms.py:62 #: netbox/ipam/forms/model_forms.py:202 netbox/ipam/forms/model_forms.py:247 -#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:431 -#: netbox/ipam/forms/model_forms.py:445 netbox/ipam/forms/model_forms.py:459 +#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/forms/model_forms.py:464 +#: netbox/ipam/forms/model_forms.py:478 netbox/ipam/forms/model_forms.py:492 #: netbox/ipam/models/ip.py:233 netbox/ipam/models/ip.py:512 #: netbox/ipam/models/ip.py:720 netbox/ipam/models/vrfs.py:62 #: netbox/ipam/tables/ip.py:242 netbox/ipam/tables/ip.py:309 @@ -3353,7 +3351,7 @@ msgid "LAG interface (ID)" msgstr "链路聚合接口(ID)" #: netbox/dcim/filtersets.py:1713 netbox/dcim/filtersets.py:1725 -#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1690 +#: netbox/dcim/forms/filtersets.py:1345 netbox/dcim/forms/model_forms.py:1697 #: netbox/templates/dcim/virtualdevicecontext.html:15 msgid "Virtual Device Context" msgstr "虚拟设备上下文" @@ -3427,7 +3425,7 @@ msgstr "标签" #: netbox/dcim/forms/bulk_create.py:112 netbox/dcim/forms/filtersets.py:1498 #: netbox/dcim/forms/model_forms.py:488 netbox/dcim/forms/model_forms.py:546 #: netbox/dcim/forms/object_create.py:197 -#: netbox/dcim/forms/object_create.py:353 netbox/dcim/tables/devices.py:165 +#: netbox/dcim/forms/object_create.py:345 netbox/dcim/tables/devices.py:165 #: netbox/dcim/tables/devices.py:707 netbox/dcim/tables/devicetypes.py:246 #: netbox/templates/dcim/device.html:43 netbox/templates/dcim/device.html:131 #: netbox/templates/dcim/modulebay.html:38 @@ -3442,38 +3440,38 @@ msgid "" "created.)" msgstr "支持字母和数字。(必须与正在创建的名称数相匹配)" -#: netbox/dcim/forms/bulk_edit.py:132 +#: netbox/dcim/forms/bulk_edit.py:133 msgid "Contact name" msgstr "联系人名字" -#: netbox/dcim/forms/bulk_edit.py:137 +#: netbox/dcim/forms/bulk_edit.py:138 msgid "Contact phone" msgstr "联系人手机" -#: netbox/dcim/forms/bulk_edit.py:143 +#: netbox/dcim/forms/bulk_edit.py:144 msgid "Contact E-mail" msgstr "联系人电子邮箱" -#: netbox/dcim/forms/bulk_edit.py:146 netbox/dcim/forms/bulk_import.py:123 +#: netbox/dcim/forms/bulk_edit.py:147 netbox/dcim/forms/bulk_import.py:123 #: netbox/dcim/forms/model_forms.py:128 msgid "Time zone" msgstr "时区" -#: netbox/dcim/forms/bulk_edit.py:224 netbox/dcim/forms/bulk_edit.py:495 -#: netbox/dcim/forms/bulk_edit.py:559 netbox/dcim/forms/bulk_edit.py:632 -#: netbox/dcim/forms/bulk_edit.py:656 netbox/dcim/forms/bulk_edit.py:740 -#: netbox/dcim/forms/bulk_edit.py:1267 netbox/dcim/forms/bulk_edit.py:1660 -#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:371 -#: netbox/dcim/forms/bulk_import.py:405 netbox/dcim/forms/bulk_import.py:450 -#: netbox/dcim/forms/bulk_import.py:486 netbox/dcim/forms/bulk_import.py:1082 +#: netbox/dcim/forms/bulk_edit.py:225 netbox/dcim/forms/bulk_edit.py:501 +#: netbox/dcim/forms/bulk_edit.py:565 netbox/dcim/forms/bulk_edit.py:638 +#: netbox/dcim/forms/bulk_edit.py:662 netbox/dcim/forms/bulk_edit.py:755 +#: netbox/dcim/forms/bulk_edit.py:1282 netbox/dcim/forms/bulk_edit.py:1703 +#: netbox/dcim/forms/bulk_import.py:182 netbox/dcim/forms/bulk_import.py:393 +#: netbox/dcim/forms/bulk_import.py:427 netbox/dcim/forms/bulk_import.py:472 +#: netbox/dcim/forms/bulk_import.py:508 netbox/dcim/forms/bulk_import.py:1104 #: netbox/dcim/forms/filtersets.py:313 netbox/dcim/forms/filtersets.py:372 #: netbox/dcim/forms/filtersets.py:494 netbox/dcim/forms/filtersets.py:619 #: netbox/dcim/forms/filtersets.py:700 netbox/dcim/forms/filtersets.py:782 #: netbox/dcim/forms/filtersets.py:947 netbox/dcim/forms/filtersets.py:1539 #: netbox/dcim/forms/model_forms.py:207 netbox/dcim/forms/model_forms.py:337 #: netbox/dcim/forms/model_forms.py:349 netbox/dcim/forms/model_forms.py:395 -#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1075 -#: netbox/dcim/forms/model_forms.py:1515 +#: netbox/dcim/forms/model_forms.py:436 netbox/dcim/forms/model_forms.py:1082 +#: netbox/dcim/forms/model_forms.py:1522 #: netbox/dcim/forms/object_import.py:187 netbox/dcim/tables/devices.py:96 #: netbox/dcim/tables/devices.py:172 netbox/dcim/tables/devices.py:940 #: netbox/dcim/tables/devicetypes.py:80 netbox/dcim/tables/devicetypes.py:308 @@ -3483,58 +3481,59 @@ msgstr "时区" #: netbox/templates/dcim/inventoryitem.html:44 #: netbox/templates/dcim/manufacturer.html:33 #: netbox/templates/dcim/modulebay.html:62 -#: netbox/templates/dcim/moduletype.html:14 +#: netbox/templates/dcim/moduletype.html:25 #: netbox/templates/dcim/platform.html:37 #: netbox/templates/dcim/racktype.html:16 msgid "Manufacturer" msgstr "厂商" -#: netbox/dcim/forms/bulk_edit.py:229 netbox/dcim/forms/bulk_edit.py:372 -#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:263 +#: netbox/dcim/forms/bulk_edit.py:230 netbox/dcim/forms/bulk_edit.py:378 +#: netbox/dcim/forms/bulk_import.py:191 netbox/dcim/forms/bulk_import.py:270 #: netbox/dcim/forms/filtersets.py:255 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:6 msgid "Form factor" msgstr "外形规格" -#: netbox/dcim/forms/bulk_edit.py:234 netbox/dcim/forms/bulk_edit.py:377 -#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:266 +#: netbox/dcim/forms/bulk_edit.py:235 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_import.py:199 netbox/dcim/forms/bulk_import.py:273 #: netbox/dcim/forms/filtersets.py:260 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:10 msgid "Width" msgstr "宽度" -#: netbox/dcim/forms/bulk_edit.py:240 netbox/dcim/forms/bulk_edit.py:383 +#: netbox/dcim/forms/bulk_edit.py:241 netbox/dcim/forms/bulk_edit.py:389 +#: netbox/dcim/forms/bulk_import.py:280 #: netbox/templates/dcim/devicetype.html:37 msgid "Height (U)" msgstr "高度(U)" -#: netbox/dcim/forms/bulk_edit.py:249 netbox/dcim/forms/bulk_edit.py:388 +#: netbox/dcim/forms/bulk_edit.py:250 netbox/dcim/forms/bulk_edit.py:394 #: netbox/dcim/forms/filtersets.py:274 msgid "Descending units" msgstr "U位显示降序" -#: netbox/dcim/forms/bulk_edit.py:252 netbox/dcim/forms/bulk_edit.py:391 +#: netbox/dcim/forms/bulk_edit.py:253 netbox/dcim/forms/bulk_edit.py:397 msgid "Outer width" msgstr "外部宽度" -#: netbox/dcim/forms/bulk_edit.py:257 netbox/dcim/forms/bulk_edit.py:396 +#: netbox/dcim/forms/bulk_edit.py:258 netbox/dcim/forms/bulk_edit.py:402 msgid "Outer depth" msgstr "外部深度" -#: netbox/dcim/forms/bulk_edit.py:262 netbox/dcim/forms/bulk_edit.py:401 -#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:271 +#: netbox/dcim/forms/bulk_edit.py:263 netbox/dcim/forms/bulk_edit.py:407 +#: netbox/dcim/forms/bulk_import.py:204 netbox/dcim/forms/bulk_import.py:283 msgid "Outer unit" msgstr "外部单元" -#: netbox/dcim/forms/bulk_edit.py:267 netbox/dcim/forms/bulk_edit.py:406 +#: netbox/dcim/forms/bulk_edit.py:268 netbox/dcim/forms/bulk_edit.py:412 msgid "Mounting depth" msgstr "安装深度" -#: netbox/dcim/forms/bulk_edit.py:272 netbox/dcim/forms/bulk_edit.py:299 -#: netbox/dcim/forms/bulk_edit.py:416 netbox/dcim/forms/bulk_edit.py:446 -#: netbox/dcim/forms/bulk_edit.py:529 netbox/dcim/forms/bulk_edit.py:552 -#: netbox/dcim/forms/bulk_edit.py:573 netbox/dcim/forms/bulk_edit.py:595 -#: netbox/dcim/forms/bulk_import.py:384 netbox/dcim/forms/bulk_import.py:416 +#: netbox/dcim/forms/bulk_edit.py:273 netbox/dcim/forms/bulk_edit.py:300 +#: netbox/dcim/forms/bulk_edit.py:422 netbox/dcim/forms/bulk_edit.py:452 +#: netbox/dcim/forms/bulk_edit.py:535 netbox/dcim/forms/bulk_edit.py:558 +#: netbox/dcim/forms/bulk_edit.py:579 netbox/dcim/forms/bulk_edit.py:601 +#: netbox/dcim/forms/bulk_import.py:406 netbox/dcim/forms/bulk_import.py:438 #: netbox/dcim/forms/filtersets.py:285 netbox/dcim/forms/filtersets.py:307 #: netbox/dcim/forms/filtersets.py:327 netbox/dcim/forms/filtersets.py:401 #: netbox/dcim/forms/filtersets.py:488 netbox/dcim/forms/filtersets.py:594 @@ -3545,10 +3544,10 @@ msgstr "安装深度" #: netbox/extras/forms/bulk_edit.py:53 netbox/extras/forms/bulk_edit.py:133 #: netbox/extras/forms/bulk_edit.py:183 netbox/extras/forms/bulk_edit.py:288 #: netbox/extras/forms/filtersets.py:64 netbox/extras/forms/filtersets.py:156 -#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:189 +#: netbox/extras/forms/filtersets.py:243 netbox/ipam/forms/bulk_edit.py:190 #: netbox/templates/dcim/device.html:324 #: netbox/templates/dcim/devicetype.html:49 -#: netbox/templates/dcim/moduletype.html:34 netbox/templates/dcim/rack.html:81 +#: netbox/templates/dcim/moduletype.html:45 netbox/templates/dcim/rack.html:81 #: netbox/templates/dcim/racktype.html:41 #: netbox/templates/extras/configcontext.html:17 #: netbox/templates/extras/customlink.html:25 @@ -3557,61 +3556,61 @@ msgstr "安装深度" msgid "Weight" msgstr "重量" -#: netbox/dcim/forms/bulk_edit.py:277 netbox/dcim/forms/bulk_edit.py:421 +#: netbox/dcim/forms/bulk_edit.py:278 netbox/dcim/forms/bulk_edit.py:427 #: netbox/dcim/forms/filtersets.py:290 msgid "Max weight" msgstr "最大承重" -#: netbox/dcim/forms/bulk_edit.py:282 netbox/dcim/forms/bulk_edit.py:426 -#: netbox/dcim/forms/bulk_edit.py:534 netbox/dcim/forms/bulk_edit.py:578 -#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:283 -#: netbox/dcim/forms/bulk_import.py:389 netbox/dcim/forms/bulk_import.py:421 +#: netbox/dcim/forms/bulk_edit.py:283 netbox/dcim/forms/bulk_edit.py:432 +#: netbox/dcim/forms/bulk_edit.py:540 netbox/dcim/forms/bulk_edit.py:584 +#: netbox/dcim/forms/bulk_import.py:210 netbox/dcim/forms/bulk_import.py:295 +#: netbox/dcim/forms/bulk_import.py:411 netbox/dcim/forms/bulk_import.py:443 #: netbox/dcim/forms/filtersets.py:295 netbox/dcim/forms/filtersets.py:598 #: netbox/dcim/forms/filtersets.py:678 msgid "Weight unit" msgstr "重量单位" -#: netbox/dcim/forms/bulk_edit.py:296 netbox/dcim/forms/filtersets.py:305 +#: netbox/dcim/forms/bulk_edit.py:297 netbox/dcim/forms/filtersets.py:305 #: netbox/dcim/forms/model_forms.py:217 netbox/dcim/forms/model_forms.py:256 #: netbox/templates/dcim/rack.html:45 netbox/templates/dcim/racktype.html:13 msgid "Rack Type" msgstr "机架类型" -#: netbox/dcim/forms/bulk_edit.py:298 netbox/dcim/forms/model_forms.py:220 +#: netbox/dcim/forms/bulk_edit.py:299 netbox/dcim/forms/model_forms.py:220 #: netbox/dcim/forms/model_forms.py:297 msgid "Outer Dimensions" msgstr "外部尺寸" -#: netbox/dcim/forms/bulk_edit.py:301 netbox/dcim/forms/model_forms.py:222 +#: netbox/dcim/forms/bulk_edit.py:302 netbox/dcim/forms/model_forms.py:222 #: netbox/dcim/forms/model_forms.py:299 netbox/templates/dcim/device.html:315 #: netbox/templates/dcim/inc/panels/racktype_dimensions.html:3 msgid "Dimensions" msgstr "外部尺寸" -#: netbox/dcim/forms/bulk_edit.py:303 netbox/dcim/forms/filtersets.py:306 +#: netbox/dcim/forms/bulk_edit.py:304 netbox/dcim/forms/filtersets.py:306 #: netbox/dcim/forms/filtersets.py:326 netbox/dcim/forms/model_forms.py:224 #: netbox/templates/dcim/inc/panels/racktype_numbering.html:3 msgid "Numbering" msgstr "编号" -#: netbox/dcim/forms/bulk_edit.py:357 netbox/dcim/forms/bulk_edit.py:1262 -#: netbox/dcim/forms/bulk_edit.py:1655 netbox/dcim/forms/bulk_import.py:253 -#: netbox/dcim/forms/bulk_import.py:1076 netbox/dcim/forms/filtersets.py:367 +#: netbox/dcim/forms/bulk_edit.py:358 netbox/dcim/forms/bulk_edit.py:1277 +#: netbox/dcim/forms/bulk_edit.py:1698 netbox/dcim/forms/bulk_import.py:253 +#: netbox/dcim/forms/bulk_import.py:1098 netbox/dcim/forms/filtersets.py:367 #: netbox/dcim/forms/filtersets.py:777 netbox/dcim/forms/filtersets.py:1534 -#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1070 -#: netbox/dcim/forms/model_forms.py:1510 +#: netbox/dcim/forms/model_forms.py:251 netbox/dcim/forms/model_forms.py:1077 +#: netbox/dcim/forms/model_forms.py:1517 #: netbox/dcim/forms/object_import.py:181 netbox/dcim/tables/devices.py:169 #: netbox/dcim/tables/devices.py:809 netbox/dcim/tables/devices.py:937 #: netbox/dcim/tables/devicetypes.py:304 netbox/dcim/tables/racks.py:129 -#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:260 -#: netbox/ipam/forms/bulk_edit.py:310 netbox/ipam/forms/bulk_edit.py:358 -#: netbox/ipam/forms/bulk_edit.py:556 netbox/ipam/forms/bulk_import.py:197 +#: netbox/extras/filtersets.py:552 netbox/ipam/forms/bulk_edit.py:261 +#: netbox/ipam/forms/bulk_edit.py:311 netbox/ipam/forms/bulk_edit.py:359 +#: netbox/ipam/forms/bulk_edit.py:511 netbox/ipam/forms/bulk_import.py:197 #: netbox/ipam/forms/bulk_import.py:262 netbox/ipam/forms/bulk_import.py:298 -#: netbox/ipam/forms/bulk_import.py:455 netbox/ipam/forms/filtersets.py:237 +#: netbox/ipam/forms/bulk_import.py:479 netbox/ipam/forms/filtersets.py:237 #: netbox/ipam/forms/filtersets.py:289 netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:509 netbox/ipam/forms/model_forms.py:188 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:250 -#: netbox/ipam/forms/model_forms.py:643 netbox/ipam/tables/ip.py:258 +#: netbox/ipam/forms/model_forms.py:676 netbox/ipam/tables/ip.py:258 #: netbox/ipam/tables/ip.py:316 netbox/ipam/tables/ip.py:367 #: netbox/ipam/tables/vlans.py:130 netbox/ipam/tables/vlans.py:235 #: netbox/templates/dcim/device.html:182 @@ -3639,45 +3638,50 @@ msgstr "编号" msgid "Role" msgstr "角色" -#: netbox/dcim/forms/bulk_edit.py:364 netbox/dcim/forms/bulk_edit.py:712 -#: netbox/dcim/forms/bulk_edit.py:764 netbox/templates/dcim/device.html:104 +#: netbox/dcim/forms/bulk_edit.py:363 netbox/dcim/forms/bulk_import.py:260 +#: netbox/dcim/forms/filtersets.py:380 +msgid "Rack type" +msgstr "机柜类型" + +#: netbox/dcim/forms/bulk_edit.py:370 netbox/dcim/forms/bulk_edit.py:718 +#: netbox/dcim/forms/bulk_edit.py:779 netbox/templates/dcim/device.html:104 #: netbox/templates/dcim/module.html:77 #: netbox/templates/dcim/modulebay.html:70 netbox/templates/dcim/rack.html:57 #: netbox/templates/virtualization/virtualmachine.html:35 msgid "Serial Number" msgstr "序列号" -#: netbox/dcim/forms/bulk_edit.py:367 netbox/dcim/forms/filtersets.py:387 +#: netbox/dcim/forms/bulk_edit.py:373 netbox/dcim/forms/filtersets.py:387 #: netbox/dcim/forms/filtersets.py:813 netbox/dcim/forms/filtersets.py:967 #: netbox/dcim/forms/filtersets.py:1546 msgid "Asset tag" msgstr "资产标签" -#: netbox/dcim/forms/bulk_edit.py:411 netbox/dcim/forms/bulk_edit.py:524 -#: netbox/dcim/forms/bulk_edit.py:568 netbox/dcim/forms/bulk_edit.py:705 -#: netbox/dcim/forms/bulk_import.py:277 netbox/dcim/forms/bulk_import.py:410 -#: netbox/dcim/forms/bulk_import.py:580 netbox/dcim/forms/filtersets.py:280 +#: netbox/dcim/forms/bulk_edit.py:417 netbox/dcim/forms/bulk_edit.py:530 +#: netbox/dcim/forms/bulk_edit.py:574 netbox/dcim/forms/bulk_edit.py:711 +#: netbox/dcim/forms/bulk_import.py:289 netbox/dcim/forms/bulk_import.py:432 +#: netbox/dcim/forms/bulk_import.py:602 netbox/dcim/forms/filtersets.py:280 #: netbox/dcim/forms/filtersets.py:511 netbox/dcim/forms/filtersets.py:669 #: netbox/dcim/forms/filtersets.py:804 netbox/templates/dcim/device.html:98 #: netbox/templates/dcim/devicetype.html:65 -#: netbox/templates/dcim/moduletype.html:30 netbox/templates/dcim/rack.html:65 +#: netbox/templates/dcim/moduletype.html:41 netbox/templates/dcim/rack.html:65 #: netbox/templates/dcim/racktype.html:28 msgid "Airflow" msgstr "气流方向" -#: netbox/dcim/forms/bulk_edit.py:440 netbox/dcim/forms/bulk_edit.py:910 -#: netbox/dcim/forms/bulk_import.py:322 netbox/dcim/forms/bulk_import.py:325 -#: netbox/dcim/forms/bulk_import.py:553 netbox/dcim/forms/bulk_import.py:1358 -#: netbox/dcim/forms/bulk_import.py:1362 netbox/dcim/forms/filtersets.py:104 +#: netbox/dcim/forms/bulk_edit.py:446 netbox/dcim/forms/bulk_edit.py:925 +#: netbox/dcim/forms/bulk_import.py:344 netbox/dcim/forms/bulk_import.py:347 +#: netbox/dcim/forms/bulk_import.py:575 netbox/dcim/forms/bulk_import.py:1380 +#: netbox/dcim/forms/bulk_import.py:1384 netbox/dcim/forms/filtersets.py:104 #: netbox/dcim/forms/filtersets.py:324 netbox/dcim/forms/filtersets.py:405 #: netbox/dcim/forms/filtersets.py:419 netbox/dcim/forms/filtersets.py:457 #: netbox/dcim/forms/filtersets.py:772 netbox/dcim/forms/filtersets.py:1035 #: netbox/dcim/forms/filtersets.py:1167 netbox/dcim/forms/model_forms.py:264 #: netbox/dcim/forms/model_forms.py:306 netbox/dcim/forms/model_forms.py:479 -#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:400 +#: netbox/dcim/forms/model_forms.py:755 netbox/dcim/forms/object_create.py:392 #: netbox/dcim/tables/devices.py:161 netbox/dcim/tables/power.py:70 -#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/bulk_edit.py:468 -#: netbox/ipam/forms/filtersets.py:442 netbox/templates/dcim/device.html:30 +#: netbox/dcim/tables/racks.py:217 netbox/ipam/forms/filtersets.py:442 +#: netbox/templates/dcim/device.html:30 #: netbox/templates/dcim/inc/cable_termination.html:16 #: netbox/templates/dcim/powerfeed.html:28 netbox/templates/dcim/rack.html:13 #: netbox/templates/dcim/rack/base.html:4 @@ -3687,64 +3691,64 @@ msgstr "气流方向" msgid "Rack" msgstr "机柜" -#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:730 +#: netbox/dcim/forms/bulk_edit.py:450 netbox/dcim/forms/bulk_edit.py:744 #: netbox/dcim/forms/filtersets.py:325 netbox/dcim/forms/filtersets.py:398 #: netbox/dcim/forms/filtersets.py:481 netbox/dcim/forms/filtersets.py:608 #: netbox/dcim/forms/filtersets.py:721 netbox/dcim/forms/filtersets.py:942 -#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1580 +#: netbox/dcim/forms/model_forms.py:670 netbox/dcim/forms/model_forms.py:1587 #: netbox/templates/dcim/device_edit.html:20 msgid "Hardware" msgstr "硬件" -#: netbox/dcim/forms/bulk_edit.py:500 netbox/dcim/forms/bulk_import.py:377 +#: netbox/dcim/forms/bulk_edit.py:506 netbox/dcim/forms/bulk_import.py:399 #: netbox/dcim/forms/filtersets.py:499 netbox/dcim/forms/model_forms.py:353 msgid "Default platform" msgstr "默认系统平台" -#: netbox/dcim/forms/bulk_edit.py:505 netbox/dcim/forms/bulk_edit.py:564 +#: netbox/dcim/forms/bulk_edit.py:511 netbox/dcim/forms/bulk_edit.py:570 #: netbox/dcim/forms/filtersets.py:502 netbox/dcim/forms/filtersets.py:622 msgid "Part number" msgstr "部件编码(PN)" -#: netbox/dcim/forms/bulk_edit.py:509 +#: netbox/dcim/forms/bulk_edit.py:515 msgid "U height" msgstr "U高度" -#: netbox/dcim/forms/bulk_edit.py:521 netbox/dcim/tables/devicetypes.py:102 +#: netbox/dcim/forms/bulk_edit.py:527 netbox/dcim/tables/devicetypes.py:102 msgid "Exclude from utilization" msgstr "从利用率中排除" -#: netbox/dcim/forms/bulk_edit.py:550 netbox/dcim/forms/model_forms.py:368 +#: netbox/dcim/forms/bulk_edit.py:556 netbox/dcim/forms/model_forms.py:368 #: netbox/dcim/tables/devicetypes.py:77 netbox/templates/dcim/device.html:88 #: netbox/templates/dcim/devicebay.html:52 #: netbox/templates/dcim/module.html:61 msgid "Device Type" msgstr "设备型号" -#: netbox/dcim/forms/bulk_edit.py:592 netbox/dcim/forms/model_forms.py:401 +#: netbox/dcim/forms/bulk_edit.py:598 netbox/dcim/forms/model_forms.py:401 #: netbox/dcim/tables/modules.py:17 netbox/dcim/tables/modules.py:65 #: netbox/templates/dcim/module.html:65 #: netbox/templates/dcim/modulebay.html:66 -#: netbox/templates/dcim/moduletype.html:11 +#: netbox/templates/dcim/moduletype.html:22 msgid "Module Type" msgstr "设备配件类型" -#: netbox/dcim/forms/bulk_edit.py:596 netbox/dcim/forms/model_forms.py:371 +#: netbox/dcim/forms/bulk_edit.py:602 netbox/dcim/forms/model_forms.py:371 #: netbox/dcim/forms/model_forms.py:402 #: netbox/templates/dcim/devicetype.html:11 msgid "Chassis" msgstr "机箱" -#: netbox/dcim/forms/bulk_edit.py:610 netbox/dcim/models/devices.py:484 +#: netbox/dcim/forms/bulk_edit.py:616 netbox/dcim/models/devices.py:484 #: netbox/dcim/tables/devices.py:67 msgid "VM role" msgstr "VM 角色" -#: netbox/dcim/forms/bulk_edit.py:613 netbox/dcim/forms/bulk_edit.py:637 -#: netbox/dcim/forms/bulk_edit.py:720 netbox/dcim/forms/bulk_import.py:434 -#: netbox/dcim/forms/bulk_import.py:438 netbox/dcim/forms/bulk_import.py:457 -#: netbox/dcim/forms/bulk_import.py:461 netbox/dcim/forms/bulk_import.py:586 -#: netbox/dcim/forms/bulk_import.py:590 netbox/dcim/forms/filtersets.py:689 +#: netbox/dcim/forms/bulk_edit.py:619 netbox/dcim/forms/bulk_edit.py:643 +#: netbox/dcim/forms/bulk_edit.py:726 netbox/dcim/forms/bulk_import.py:456 +#: netbox/dcim/forms/bulk_import.py:460 netbox/dcim/forms/bulk_import.py:479 +#: netbox/dcim/forms/bulk_import.py:483 netbox/dcim/forms/bulk_import.py:608 +#: netbox/dcim/forms/bulk_import.py:612 netbox/dcim/forms/filtersets.py:689 #: netbox/dcim/forms/filtersets.py:705 netbox/dcim/forms/filtersets.py:823 #: netbox/dcim/forms/model_forms.py:415 netbox/dcim/forms/model_forms.py:441 #: netbox/dcim/forms/model_forms.py:555 @@ -3755,19 +3759,19 @@ msgstr "VM 角色" msgid "Config template" msgstr "配置模版" -#: netbox/dcim/forms/bulk_edit.py:661 netbox/dcim/forms/bulk_edit.py:1061 -#: netbox/dcim/forms/bulk_import.py:492 netbox/dcim/forms/filtersets.py:114 +#: netbox/dcim/forms/bulk_edit.py:667 netbox/dcim/forms/bulk_edit.py:1076 +#: netbox/dcim/forms/bulk_import.py:514 netbox/dcim/forms/filtersets.py:114 #: netbox/dcim/forms/model_forms.py:501 netbox/dcim/forms/model_forms.py:872 #: netbox/dcim/forms/model_forms.py:889 netbox/extras/filtersets.py:547 msgid "Device type" msgstr "设备型号" -#: netbox/dcim/forms/bulk_edit.py:672 netbox/dcim/forms/bulk_import.py:473 +#: netbox/dcim/forms/bulk_edit.py:678 netbox/dcim/forms/bulk_import.py:495 #: netbox/dcim/forms/filtersets.py:119 netbox/dcim/forms/model_forms.py:509 msgid "Device role" msgstr "设备角色" -#: netbox/dcim/forms/bulk_edit.py:695 netbox/dcim/forms/bulk_import.py:498 +#: netbox/dcim/forms/bulk_edit.py:701 netbox/dcim/forms/bulk_import.py:520 #: netbox/dcim/forms/filtersets.py:796 netbox/dcim/forms/model_forms.py:451 #: netbox/dcim/forms/model_forms.py:513 netbox/dcim/tables/devices.py:182 #: netbox/extras/filtersets.py:563 netbox/templates/dcim/device.html:186 @@ -3781,14 +3785,36 @@ msgstr "设备角色" msgid "Platform" msgstr "平台" -#: netbox/dcim/forms/bulk_edit.py:728 netbox/dcim/forms/bulk_edit.py:1281 -#: netbox/dcim/forms/bulk_edit.py:1650 netbox/dcim/forms/bulk_edit.py:1696 -#: netbox/dcim/forms/bulk_import.py:641 netbox/dcim/forms/bulk_import.py:703 -#: netbox/dcim/forms/bulk_import.py:729 netbox/dcim/forms/bulk_import.py:755 -#: netbox/dcim/forms/bulk_import.py:775 netbox/dcim/forms/bulk_import.py:828 -#: netbox/dcim/forms/bulk_import.py:946 netbox/dcim/forms/bulk_import.py:994 -#: netbox/dcim/forms/bulk_import.py:1011 netbox/dcim/forms/bulk_import.py:1023 -#: netbox/dcim/forms/bulk_import.py:1071 netbox/dcim/forms/bulk_import.py:1422 +#: netbox/dcim/forms/bulk_edit.py:731 netbox/dcim/forms/bulk_import.py:539 +#: netbox/dcim/forms/filtersets.py:728 netbox/dcim/forms/filtersets.py:898 +#: netbox/dcim/forms/model_forms.py:522 netbox/dcim/tables/devices.py:202 +#: netbox/extras/filtersets.py:596 netbox/extras/forms/filtersets.py:322 +#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 +#: netbox/templates/dcim/device.html:239 +#: netbox/templates/virtualization/cluster.html:10 +#: netbox/templates/virtualization/virtualmachine.html:92 +#: netbox/templates/virtualization/virtualmachine.html:101 +#: netbox/virtualization/filtersets.py:157 +#: netbox/virtualization/filtersets.py:277 +#: netbox/virtualization/forms/bulk_edit.py:129 +#: netbox/virtualization/forms/bulk_import.py:92 +#: netbox/virtualization/forms/filtersets.py:99 +#: netbox/virtualization/forms/filtersets.py:123 +#: netbox/virtualization/forms/filtersets.py:204 +#: netbox/virtualization/forms/model_forms.py:79 +#: netbox/virtualization/forms/model_forms.py:176 +#: netbox/virtualization/tables/virtualmachines.py:67 +msgid "Cluster" +msgstr "集群" + +#: netbox/dcim/forms/bulk_edit.py:742 netbox/dcim/forms/bulk_edit.py:1296 +#: netbox/dcim/forms/bulk_edit.py:1693 netbox/dcim/forms/bulk_edit.py:1739 +#: netbox/dcim/forms/bulk_import.py:663 netbox/dcim/forms/bulk_import.py:725 +#: netbox/dcim/forms/bulk_import.py:751 netbox/dcim/forms/bulk_import.py:777 +#: netbox/dcim/forms/bulk_import.py:797 netbox/dcim/forms/bulk_import.py:850 +#: netbox/dcim/forms/bulk_import.py:968 netbox/dcim/forms/bulk_import.py:1016 +#: netbox/dcim/forms/bulk_import.py:1033 netbox/dcim/forms/bulk_import.py:1045 +#: netbox/dcim/forms/bulk_import.py:1093 netbox/dcim/forms/bulk_import.py:1444 #: netbox/dcim/forms/connections.py:24 netbox/dcim/forms/filtersets.py:131 #: netbox/dcim/forms/filtersets.py:921 netbox/dcim/forms/filtersets.py:1051 #: netbox/dcim/forms/filtersets.py:1242 netbox/dcim/forms/filtersets.py:1267 @@ -3798,9 +3824,9 @@ msgstr "平台" #: netbox/dcim/forms/filtersets.py:1511 netbox/dcim/forms/filtersets.py:1528 #: netbox/dcim/forms/filtersets.py:1592 netbox/dcim/forms/filtersets.py:1616 #: netbox/dcim/forms/filtersets.py:1640 netbox/dcim/forms/model_forms.py:633 -#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1208 -#: netbox/dcim/forms/model_forms.py:1664 -#: netbox/dcim/forms/object_create.py:257 netbox/dcim/tables/connections.py:22 +#: netbox/dcim/forms/model_forms.py:849 netbox/dcim/forms/model_forms.py:1215 +#: netbox/dcim/forms/model_forms.py:1671 +#: netbox/dcim/forms/object_create.py:249 netbox/dcim/tables/connections.py:22 #: netbox/dcim/tables/connections.py:41 netbox/dcim/tables/connections.py:60 #: netbox/dcim/tables/devices.py:285 netbox/dcim/tables/devices.py:371 #: netbox/dcim/tables/devices.py:412 netbox/dcim/tables/devices.py:454 @@ -3809,10 +3835,10 @@ msgstr "平台" #: netbox/dcim/tables/devices.py:801 netbox/dcim/tables/devices.py:861 #: netbox/dcim/tables/devices.py:930 netbox/dcim/tables/devices.py:1057 #: netbox/dcim/tables/modules.py:52 netbox/extras/forms/filtersets.py:321 -#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:481 -#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:319 -#: netbox/ipam/forms/model_forms.py:679 netbox/ipam/forms/model_forms.py:712 -#: netbox/ipam/forms/model_forms.py:738 netbox/ipam/tables/vlans.py:180 +#: netbox/ipam/forms/bulk_import.py:304 netbox/ipam/forms/bulk_import.py:505 +#: netbox/ipam/forms/filtersets.py:551 netbox/ipam/forms/model_forms.py:323 +#: netbox/ipam/forms/model_forms.py:712 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:771 netbox/ipam/tables/vlans.py:180 #: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleserverport.html:20 #: netbox/templates/dcim/device.html:15 netbox/templates/dcim/device.html:130 @@ -3839,7 +3865,7 @@ msgstr "平台" #: netbox/virtualization/forms/bulk_import.py:99 #: netbox/virtualization/forms/filtersets.py:128 #: netbox/virtualization/forms/model_forms.py:185 -#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:44 +#: netbox/virtualization/tables/virtualmachines.py:71 netbox/vpn/choices.py:52 #: netbox/vpn/forms/bulk_import.py:86 netbox/vpn/forms/bulk_import.py:283 #: netbox/vpn/forms/filtersets.py:275 netbox/vpn/forms/model_forms.py:90 #: netbox/vpn/forms/model_forms.py:125 netbox/vpn/forms/model_forms.py:236 @@ -3849,23 +3875,28 @@ msgstr "平台" msgid "Device" msgstr "设备" -#: netbox/dcim/forms/bulk_edit.py:731 +#: netbox/dcim/forms/bulk_edit.py:745 #: netbox/templates/extras/dashboard/widget_config.html:7 #: netbox/virtualization/forms/bulk_edit.py:191 msgid "Configuration" msgstr "配置" -#: netbox/dcim/forms/bulk_edit.py:745 netbox/dcim/forms/bulk_import.py:653 +#: netbox/dcim/forms/bulk_edit.py:746 netbox/netbox/navigation/menu.py:243 +#: netbox/templates/dcim/device_edit.html:78 +msgid "Virtualization" +msgstr "虚拟化" + +#: netbox/dcim/forms/bulk_edit.py:760 netbox/dcim/forms/bulk_import.py:675 #: netbox/dcim/forms/model_forms.py:647 netbox/dcim/forms/model_forms.py:897 msgid "Module type" msgstr "模块类型" -#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:984 -#: netbox/dcim/forms/bulk_edit.py:1003 netbox/dcim/forms/bulk_edit.py:1026 -#: netbox/dcim/forms/bulk_edit.py:1068 netbox/dcim/forms/bulk_edit.py:1112 -#: netbox/dcim/forms/bulk_edit.py:1163 netbox/dcim/forms/bulk_edit.py:1190 -#: netbox/dcim/forms/bulk_edit.py:1217 netbox/dcim/forms/bulk_edit.py:1235 -#: netbox/dcim/forms/bulk_edit.py:1253 netbox/dcim/forms/filtersets.py:67 +#: netbox/dcim/forms/bulk_edit.py:814 netbox/dcim/forms/bulk_edit.py:999 +#: netbox/dcim/forms/bulk_edit.py:1018 netbox/dcim/forms/bulk_edit.py:1041 +#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_edit.py:1127 +#: netbox/dcim/forms/bulk_edit.py:1178 netbox/dcim/forms/bulk_edit.py:1205 +#: netbox/dcim/forms/bulk_edit.py:1232 netbox/dcim/forms/bulk_edit.py:1250 +#: netbox/dcim/forms/bulk_edit.py:1268 netbox/dcim/forms/filtersets.py:67 #: netbox/dcim/forms/object_create.py:46 netbox/templates/dcim/cable.html:32 #: netbox/templates/dcim/consoleport.html:32 #: netbox/templates/dcim/consoleserverport.html:32 @@ -3883,109 +3914,109 @@ msgstr "模块类型" msgid "Label" msgstr "标记" -#: netbox/dcim/forms/bulk_edit.py:808 netbox/dcim/forms/filtersets.py:1068 +#: netbox/dcim/forms/bulk_edit.py:823 netbox/dcim/forms/filtersets.py:1068 #: netbox/templates/dcim/cable.html:50 msgid "Length" msgstr "长度" -#: netbox/dcim/forms/bulk_edit.py:813 netbox/dcim/forms/bulk_import.py:1226 -#: netbox/dcim/forms/bulk_import.py:1229 netbox/dcim/forms/filtersets.py:1072 +#: netbox/dcim/forms/bulk_edit.py:828 netbox/dcim/forms/bulk_import.py:1248 +#: netbox/dcim/forms/bulk_import.py:1251 netbox/dcim/forms/filtersets.py:1072 msgid "Length unit" msgstr "长度单位" -#: netbox/dcim/forms/bulk_edit.py:837 +#: netbox/dcim/forms/bulk_edit.py:852 #: netbox/templates/dcim/virtualchassis.html:23 msgid "Domain" msgstr "域" -#: netbox/dcim/forms/bulk_edit.py:905 netbox/dcim/forms/bulk_import.py:1345 +#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1367 #: netbox/dcim/forms/filtersets.py:1158 netbox/dcim/forms/model_forms.py:750 msgid "Power panel" msgstr "电源面版" -#: netbox/dcim/forms/bulk_edit.py:927 netbox/dcim/forms/bulk_import.py:1381 +#: netbox/dcim/forms/bulk_edit.py:942 netbox/dcim/forms/bulk_import.py:1403 #: netbox/dcim/forms/filtersets.py:1180 #: netbox/templates/dcim/powerfeed.html:83 msgid "Supply" msgstr "供应" -#: netbox/dcim/forms/bulk_edit.py:933 netbox/dcim/forms/bulk_import.py:1386 +#: netbox/dcim/forms/bulk_edit.py:948 netbox/dcim/forms/bulk_import.py:1408 #: netbox/dcim/forms/filtersets.py:1185 #: netbox/templates/dcim/powerfeed.html:95 msgid "Phase" msgstr "相位" -#: netbox/dcim/forms/bulk_edit.py:939 netbox/dcim/forms/filtersets.py:1190 +#: netbox/dcim/forms/bulk_edit.py:954 netbox/dcim/forms/filtersets.py:1190 #: netbox/templates/dcim/powerfeed.html:87 msgid "Voltage" msgstr "电压" -#: netbox/dcim/forms/bulk_edit.py:943 netbox/dcim/forms/filtersets.py:1194 +#: netbox/dcim/forms/bulk_edit.py:958 netbox/dcim/forms/filtersets.py:1194 #: netbox/templates/dcim/powerfeed.html:91 msgid "Amperage" msgstr "电流" -#: netbox/dcim/forms/bulk_edit.py:947 netbox/dcim/forms/filtersets.py:1198 +#: netbox/dcim/forms/bulk_edit.py:962 netbox/dcim/forms/filtersets.py:1198 msgid "Max utilization" msgstr "最大利用率" -#: netbox/dcim/forms/bulk_edit.py:1036 +#: netbox/dcim/forms/bulk_edit.py:1051 msgid "Maximum draw" msgstr "最大功率" -#: netbox/dcim/forms/bulk_edit.py:1039 +#: netbox/dcim/forms/bulk_edit.py:1054 #: netbox/dcim/models/device_component_templates.py:282 #: netbox/dcim/models/device_components.py:356 msgid "Maximum power draw (watts)" msgstr "最大功率(瓦)" -#: netbox/dcim/forms/bulk_edit.py:1042 +#: netbox/dcim/forms/bulk_edit.py:1057 msgid "Allocated draw" msgstr "分配功率" -#: netbox/dcim/forms/bulk_edit.py:1045 +#: netbox/dcim/forms/bulk_edit.py:1060 #: netbox/dcim/models/device_component_templates.py:289 #: netbox/dcim/models/device_components.py:363 msgid "Allocated power draw (watts)" msgstr "分配功率(瓦)" -#: netbox/dcim/forms/bulk_edit.py:1078 netbox/dcim/forms/bulk_import.py:786 -#: netbox/dcim/forms/model_forms.py:953 netbox/dcim/forms/model_forms.py:1278 -#: netbox/dcim/forms/model_forms.py:1567 netbox/dcim/forms/object_import.py:55 +#: netbox/dcim/forms/bulk_edit.py:1093 netbox/dcim/forms/bulk_import.py:808 +#: netbox/dcim/forms/model_forms.py:960 netbox/dcim/forms/model_forms.py:1285 +#: netbox/dcim/forms/model_forms.py:1574 netbox/dcim/forms/object_import.py:55 msgid "Power port" msgstr "电源接口" -#: netbox/dcim/forms/bulk_edit.py:1083 netbox/dcim/forms/bulk_import.py:793 +#: netbox/dcim/forms/bulk_edit.py:1098 netbox/dcim/forms/bulk_import.py:815 msgid "Feed leg" msgstr "馈电线路" -#: netbox/dcim/forms/bulk_edit.py:1129 netbox/dcim/forms/bulk_edit.py:1440 +#: netbox/dcim/forms/bulk_edit.py:1144 netbox/dcim/forms/bulk_edit.py:1462 msgid "Management only" msgstr "仅限管理" -#: netbox/dcim/forms/bulk_edit.py:1139 netbox/dcim/forms/bulk_edit.py:1446 -#: netbox/dcim/forms/bulk_import.py:876 netbox/dcim/forms/filtersets.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1154 netbox/dcim/forms/bulk_edit.py:1468 +#: netbox/dcim/forms/bulk_import.py:898 netbox/dcim/forms/filtersets.py:1394 #: netbox/dcim/forms/object_import.py:90 #: netbox/dcim/models/device_component_templates.py:437 #: netbox/dcim/models/device_components.py:670 msgid "PoE mode" msgstr "PoE模式" -#: netbox/dcim/forms/bulk_edit.py:1145 netbox/dcim/forms/bulk_edit.py:1452 -#: netbox/dcim/forms/bulk_import.py:882 netbox/dcim/forms/filtersets.py:1399 +#: netbox/dcim/forms/bulk_edit.py:1160 netbox/dcim/forms/bulk_edit.py:1474 +#: netbox/dcim/forms/bulk_import.py:904 netbox/dcim/forms/filtersets.py:1399 #: netbox/dcim/forms/object_import.py:95 #: netbox/dcim/models/device_component_templates.py:443 #: netbox/dcim/models/device_components.py:676 msgid "PoE type" msgstr "PoE类型" -#: netbox/dcim/forms/bulk_edit.py:1151 netbox/dcim/forms/filtersets.py:1404 +#: netbox/dcim/forms/bulk_edit.py:1166 netbox/dcim/forms/filtersets.py:1404 #: netbox/dcim/forms/object_import.py:100 msgid "Wireless role" msgstr "无线角色" -#: netbox/dcim/forms/bulk_edit.py:1288 netbox/dcim/forms/model_forms.py:669 -#: netbox/dcim/forms/model_forms.py:1223 netbox/dcim/tables/devices.py:313 +#: netbox/dcim/forms/bulk_edit.py:1303 netbox/dcim/forms/model_forms.py:669 +#: netbox/dcim/forms/model_forms.py:1230 netbox/dcim/tables/devices.py:313 #: netbox/templates/dcim/consoleport.html:24 #: netbox/templates/dcim/consoleserverport.html:24 #: netbox/templates/dcim/frontport.html:24 @@ -3999,17 +4030,17 @@ msgstr "无线角色" msgid "Module" msgstr "模块" -#: netbox/dcim/forms/bulk_edit.py:1420 netbox/dcim/tables/devices.py:665 +#: netbox/dcim/forms/bulk_edit.py:1442 netbox/dcim/tables/devices.py:665 #: netbox/templates/dcim/interface.html:110 msgid "LAG" msgstr "链路聚合" -#: netbox/dcim/forms/bulk_edit.py:1425 netbox/dcim/forms/model_forms.py:1305 +#: netbox/dcim/forms/bulk_edit.py:1447 netbox/dcim/forms/model_forms.py:1312 msgid "Virtual device contexts" msgstr "设备虚拟上下文" -#: netbox/dcim/forms/bulk_edit.py:1431 netbox/dcim/forms/bulk_import.py:714 -#: netbox/dcim/forms/bulk_import.py:740 netbox/dcim/forms/filtersets.py:1252 +#: netbox/dcim/forms/bulk_edit.py:1453 netbox/dcim/forms/bulk_import.py:736 +#: netbox/dcim/forms/bulk_import.py:762 netbox/dcim/forms/filtersets.py:1252 #: netbox/dcim/forms/filtersets.py:1277 netbox/dcim/forms/filtersets.py:1358 #: netbox/dcim/tables/devices.py:610 #: netbox/templates/circuits/inc/circuit_termination_fields.html:67 @@ -4018,7 +4049,7 @@ msgstr "设备虚拟上下文" msgid "Speed" msgstr "速率" -#: netbox/dcim/forms/bulk_edit.py:1460 netbox/dcim/forms/bulk_import.py:885 +#: netbox/dcim/forms/bulk_edit.py:1482 netbox/dcim/forms/bulk_import.py:907 #: netbox/templates/vpn/ikepolicy.html:25 #: netbox/templates/vpn/ipsecprofile.html:21 #: netbox/templates/vpn/ipsecprofile.html:48 @@ -4032,76 +4063,88 @@ msgstr "速率" msgid "Mode" msgstr "模式" -#: netbox/dcim/forms/bulk_edit.py:1468 netbox/dcim/forms/model_forms.py:1354 +#: netbox/dcim/forms/bulk_edit.py:1490 netbox/dcim/forms/model_forms.py:1361 #: netbox/ipam/forms/bulk_import.py:178 netbox/ipam/forms/filtersets.py:498 #: netbox/ipam/models/vlans.py:84 netbox/virtualization/forms/bulk_edit.py:240 #: netbox/virtualization/forms/model_forms.py:321 msgid "VLAN group" msgstr "VLAN 组" -#: netbox/dcim/forms/bulk_edit.py:1476 netbox/dcim/forms/model_forms.py:1360 +#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1367 #: netbox/dcim/tables/devices.py:579 #: netbox/virtualization/forms/bulk_edit.py:248 #: netbox/virtualization/forms/model_forms.py:326 msgid "Untagged VLAN" msgstr "未标记的VLAN" -#: netbox/dcim/forms/bulk_edit.py:1484 netbox/dcim/forms/model_forms.py:1369 +#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/model_forms.py:1376 #: netbox/dcim/tables/devices.py:585 #: netbox/virtualization/forms/bulk_edit.py:256 #: netbox/virtualization/forms/model_forms.py:335 msgid "Tagged VLANs" msgstr "已标记 VLANs" -#: netbox/dcim/forms/bulk_edit.py:1494 netbox/dcim/forms/model_forms.py:1341 +#: netbox/dcim/forms/bulk_edit.py:1511 +msgid "Add tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1520 +msgid "Remove tagged VLANs" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1536 netbox/dcim/forms/model_forms.py:1348 msgid "Wireless LAN group" msgstr "无线局域网组" -#: netbox/dcim/forms/bulk_edit.py:1499 netbox/dcim/forms/model_forms.py:1346 +#: netbox/dcim/forms/bulk_edit.py:1541 netbox/dcim/forms/model_forms.py:1353 #: netbox/dcim/tables/devices.py:619 netbox/netbox/navigation/menu.py:146 #: netbox/templates/dcim/interface.html:280 #: netbox/wireless/tables/wirelesslan.py:24 msgid "Wireless LANs" msgstr "无线局域网" -#: netbox/dcim/forms/bulk_edit.py:1508 netbox/dcim/forms/filtersets.py:1328 -#: netbox/dcim/forms/model_forms.py:1390 netbox/ipam/forms/bulk_edit.py:285 -#: netbox/ipam/forms/bulk_edit.py:377 netbox/ipam/forms/filtersets.py:169 +#: netbox/dcim/forms/bulk_edit.py:1550 netbox/dcim/forms/filtersets.py:1328 +#: netbox/dcim/forms/model_forms.py:1397 netbox/ipam/forms/bulk_edit.py:286 +#: netbox/ipam/forms/bulk_edit.py:378 netbox/ipam/forms/filtersets.py:169 #: netbox/templates/dcim/interface.html:122 #: netbox/templates/ipam/prefix.html:95 #: netbox/virtualization/forms/model_forms.py:349 msgid "Addressing" msgstr "寻址" -#: netbox/dcim/forms/bulk_edit.py:1509 netbox/dcim/forms/filtersets.py:720 -#: netbox/dcim/forms/model_forms.py:1391 +#: netbox/dcim/forms/bulk_edit.py:1551 netbox/dcim/forms/filtersets.py:720 +#: netbox/dcim/forms/model_forms.py:1398 #: netbox/virtualization/forms/model_forms.py:350 msgid "Operation" msgstr "操作" -#: netbox/dcim/forms/bulk_edit.py:1510 netbox/dcim/forms/filtersets.py:1329 -#: netbox/dcim/forms/model_forms.py:987 netbox/dcim/forms/model_forms.py:1393 +#: netbox/dcim/forms/bulk_edit.py:1552 netbox/dcim/forms/filtersets.py:1329 +#: netbox/dcim/forms/model_forms.py:994 netbox/dcim/forms/model_forms.py:1400 msgid "PoE" msgstr "PoE" -#: netbox/dcim/forms/bulk_edit.py:1511 netbox/dcim/forms/model_forms.py:1392 +#: netbox/dcim/forms/bulk_edit.py:1553 netbox/dcim/forms/model_forms.py:1399 #: netbox/templates/dcim/interface.html:99 #: netbox/virtualization/forms/bulk_edit.py:267 #: netbox/virtualization/forms/model_forms.py:351 msgid "Related Interfaces" msgstr "相关接口" -#: netbox/dcim/forms/bulk_edit.py:1512 netbox/dcim/forms/model_forms.py:1394 +#: netbox/dcim/forms/bulk_edit.py:1554 netbox/dcim/forms/model_forms.py:1401 #: netbox/virtualization/forms/bulk_edit.py:268 #: netbox/virtualization/forms/model_forms.py:352 msgid "802.1Q Switching" msgstr "802.1Q 交换" -#: netbox/dcim/forms/bulk_edit.py:1574 netbox/dcim/forms/bulk_edit.py:1576 +#: netbox/dcim/forms/bulk_edit.py:1558 +msgid "Add/Remove" +msgstr "" + +#: netbox/dcim/forms/bulk_edit.py:1617 netbox/dcim/forms/bulk_edit.py:1619 msgid "Interface mode must be specified to assign VLANs" msgstr "该接口模式下,必须指定VLAN" -#: netbox/dcim/forms/bulk_edit.py:1581 netbox/dcim/forms/common.py:50 +#: netbox/dcim/forms/bulk_edit.py:1624 netbox/dcim/forms/common.py:50 msgid "An access interface cannot have tagged VLANs assigned." msgstr "access接口不允许指定Tag的VLAN" @@ -4127,9 +4170,9 @@ msgstr "指定组" msgid "available options" msgstr "可用选项" -#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:543 -#: netbox/dcim/forms/bulk_import.py:1342 netbox/ipam/forms/bulk_import.py:175 -#: netbox/ipam/forms/bulk_import.py:433 +#: netbox/dcim/forms/bulk_import.py:134 netbox/dcim/forms/bulk_import.py:565 +#: netbox/dcim/forms/bulk_import.py:1364 netbox/ipam/forms/bulk_import.py:175 +#: netbox/ipam/forms/bulk_import.py:457 #: netbox/virtualization/forms/bulk_import.py:63 #: netbox/virtualization/forms/bulk_import.py:89 msgid "Assigned site" @@ -4151,15 +4194,15 @@ msgstr "这种机架类型的制造商" msgid "The lowest-numbered position in the rack" msgstr "机架中编号最低的位置" -#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:268 +#: netbox/dcim/forms/bulk_import.py:201 netbox/dcim/forms/bulk_import.py:276 msgid "Rail-to-rail width (in inches)" msgstr "设备安装宽度(英寸)" -#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:274 +#: netbox/dcim/forms/bulk_import.py:207 netbox/dcim/forms/bulk_import.py:286 msgid "Unit for outer dimensions" msgstr "外形尺寸单位" -#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:286 +#: netbox/dcim/forms/bulk_import.py:213 netbox/dcim/forms/bulk_import.py:298 msgid "Unit for rack weights" msgstr "机柜重量单位" @@ -4171,240 +4214,230 @@ msgstr "指定租户名称" msgid "Name of assigned role" msgstr "指定规则名称" -#: netbox/dcim/forms/bulk_import.py:280 netbox/dcim/forms/bulk_import.py:413 -#: netbox/dcim/forms/bulk_import.py:583 +#: netbox/dcim/forms/bulk_import.py:264 +msgid "Rack type model" +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:292 netbox/dcim/forms/bulk_import.py:435 +#: netbox/dcim/forms/bulk_import.py:605 msgid "Airflow direction" msgstr "风道方向" -#: netbox/dcim/forms/bulk_import.py:312 +#: netbox/dcim/forms/bulk_import.py:324 +msgid "Width must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:326 +msgid "U height must be set if not specifying a rack type." +msgstr "" + +#: netbox/dcim/forms/bulk_import.py:334 msgid "Parent site" msgstr "上一级站点" -#: netbox/dcim/forms/bulk_import.py:319 netbox/dcim/forms/bulk_import.py:1355 +#: netbox/dcim/forms/bulk_import.py:341 netbox/dcim/forms/bulk_import.py:1377 msgid "Rack's location (if any)" msgstr "机柜所在位置(如果有)" -#: netbox/dcim/forms/bulk_import.py:328 netbox/dcim/forms/model_forms.py:311 +#: netbox/dcim/forms/bulk_import.py:350 netbox/dcim/forms/model_forms.py:311 #: netbox/dcim/tables/racks.py:222 #: netbox/templates/dcim/rackreservation.html:12 #: netbox/templates/dcim/rackreservation.html:45 msgid "Units" msgstr "单元(U)" -#: netbox/dcim/forms/bulk_import.py:331 +#: netbox/dcim/forms/bulk_import.py:353 msgid "Comma-separated list of individual unit numbers" msgstr "占用U位号列表,以逗号分隔" -#: netbox/dcim/forms/bulk_import.py:374 +#: netbox/dcim/forms/bulk_import.py:396 msgid "The manufacturer which produces this device type" msgstr "生产这种类型设备的制造商" -#: netbox/dcim/forms/bulk_import.py:381 +#: netbox/dcim/forms/bulk_import.py:403 msgid "The default platform for devices of this type (optional)" msgstr "此类型设备的默认平台(可选)" -#: netbox/dcim/forms/bulk_import.py:386 +#: netbox/dcim/forms/bulk_import.py:408 msgid "Device weight" msgstr "设备重量" -#: netbox/dcim/forms/bulk_import.py:392 +#: netbox/dcim/forms/bulk_import.py:414 msgid "Unit for device weight" msgstr "设备重量单位" -#: netbox/dcim/forms/bulk_import.py:418 +#: netbox/dcim/forms/bulk_import.py:440 msgid "Module weight" msgstr "模块重量" -#: netbox/dcim/forms/bulk_import.py:424 +#: netbox/dcim/forms/bulk_import.py:446 msgid "Unit for module weight" msgstr "模块重量单位" -#: netbox/dcim/forms/bulk_import.py:454 +#: netbox/dcim/forms/bulk_import.py:476 msgid "Limit platform assignments to this manufacturer" msgstr "限定此系统平台的制造商" -#: netbox/dcim/forms/bulk_import.py:476 netbox/dcim/forms/bulk_import.py:1425 +#: netbox/dcim/forms/bulk_import.py:498 netbox/dcim/forms/bulk_import.py:1447 #: netbox/tenancy/forms/bulk_import.py:106 msgid "Assigned role" msgstr "指定规则" -#: netbox/dcim/forms/bulk_import.py:489 +#: netbox/dcim/forms/bulk_import.py:511 msgid "Device type manufacturer" msgstr "设备制造商" -#: netbox/dcim/forms/bulk_import.py:495 +#: netbox/dcim/forms/bulk_import.py:517 msgid "Device type model" msgstr "设备型号" -#: netbox/dcim/forms/bulk_import.py:502 +#: netbox/dcim/forms/bulk_import.py:524 #: netbox/virtualization/forms/bulk_import.py:126 msgid "Assigned platform" msgstr "指定系统平台" -#: netbox/dcim/forms/bulk_import.py:510 netbox/dcim/forms/bulk_import.py:514 +#: netbox/dcim/forms/bulk_import.py:532 netbox/dcim/forms/bulk_import.py:536 #: netbox/dcim/forms/model_forms.py:536 msgid "Virtual chassis" msgstr "堆叠" -#: netbox/dcim/forms/bulk_import.py:517 netbox/dcim/forms/filtersets.py:728 -#: netbox/dcim/forms/filtersets.py:898 netbox/dcim/forms/model_forms.py:522 -#: netbox/dcim/tables/devices.py:202 netbox/extras/filtersets.py:596 -#: netbox/extras/forms/filtersets.py:322 netbox/ipam/forms/bulk_edit.py:482 -#: netbox/ipam/forms/filtersets.py:415 netbox/ipam/forms/filtersets.py:447 -#: netbox/templates/dcim/device.html:239 -#: netbox/templates/virtualization/cluster.html:10 -#: netbox/templates/virtualization/virtualmachine.html:92 -#: netbox/templates/virtualization/virtualmachine.html:101 -#: netbox/virtualization/filtersets.py:157 -#: netbox/virtualization/filtersets.py:277 -#: netbox/virtualization/forms/bulk_edit.py:129 -#: netbox/virtualization/forms/bulk_import.py:92 -#: netbox/virtualization/forms/filtersets.py:99 -#: netbox/virtualization/forms/filtersets.py:123 -#: netbox/virtualization/forms/filtersets.py:204 -#: netbox/virtualization/forms/model_forms.py:79 -#: netbox/virtualization/forms/model_forms.py:176 -#: netbox/virtualization/tables/virtualmachines.py:67 -msgid "Cluster" -msgstr "集群" - -#: netbox/dcim/forms/bulk_import.py:521 +#: netbox/dcim/forms/bulk_import.py:543 msgid "Virtualization cluster" msgstr "虚拟化集群" -#: netbox/dcim/forms/bulk_import.py:550 +#: netbox/dcim/forms/bulk_import.py:572 msgid "Assigned location (if any)" msgstr "指定位置(如果有)" -#: netbox/dcim/forms/bulk_import.py:557 +#: netbox/dcim/forms/bulk_import.py:579 msgid "Assigned rack (if any)" msgstr "指定机柜(如果有)" -#: netbox/dcim/forms/bulk_import.py:560 +#: netbox/dcim/forms/bulk_import.py:582 msgid "Face" msgstr "朝向" -#: netbox/dcim/forms/bulk_import.py:563 +#: netbox/dcim/forms/bulk_import.py:585 msgid "Mounted rack face" msgstr "机架正面安装" -#: netbox/dcim/forms/bulk_import.py:570 +#: netbox/dcim/forms/bulk_import.py:592 msgid "Parent device (for child devices)" msgstr "上一级设备(用于子设备)" -#: netbox/dcim/forms/bulk_import.py:573 +#: netbox/dcim/forms/bulk_import.py:595 msgid "Device bay" msgstr "设备托架" -#: netbox/dcim/forms/bulk_import.py:577 +#: netbox/dcim/forms/bulk_import.py:599 msgid "Device bay in which this device is installed (for child devices)" msgstr "安装此设备的设备托架(用于子设备)" -#: netbox/dcim/forms/bulk_import.py:644 +#: netbox/dcim/forms/bulk_import.py:666 msgid "The device in which this module is installed" msgstr "安装此模块的设备" -#: netbox/dcim/forms/bulk_import.py:647 netbox/dcim/forms/model_forms.py:640 +#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:640 msgid "Module bay" msgstr "设备板卡插槽" -#: netbox/dcim/forms/bulk_import.py:650 +#: netbox/dcim/forms/bulk_import.py:672 msgid "The module bay in which this module is installed" msgstr "安装此模块的模块托架" -#: netbox/dcim/forms/bulk_import.py:656 +#: netbox/dcim/forms/bulk_import.py:678 msgid "The type of module" msgstr "模块类型" -#: netbox/dcim/forms/bulk_import.py:664 netbox/dcim/forms/model_forms.py:656 +#: netbox/dcim/forms/bulk_import.py:686 netbox/dcim/forms/model_forms.py:656 msgid "Replicate components" msgstr "组件冗余" -#: netbox/dcim/forms/bulk_import.py:666 +#: netbox/dcim/forms/bulk_import.py:688 msgid "" "Automatically populate components associated with this module type (enabled " "by default)" msgstr "自动填充此模块类型关联的组件(默认启用)" -#: netbox/dcim/forms/bulk_import.py:669 netbox/dcim/forms/model_forms.py:662 +#: netbox/dcim/forms/bulk_import.py:691 netbox/dcim/forms/model_forms.py:662 msgid "Adopt components" msgstr "选定组件" -#: netbox/dcim/forms/bulk_import.py:671 netbox/dcim/forms/model_forms.py:665 +#: netbox/dcim/forms/bulk_import.py:693 netbox/dcim/forms/model_forms.py:665 msgid "Adopt already existing components" msgstr "选定已经存在的组件" -#: netbox/dcim/forms/bulk_import.py:711 netbox/dcim/forms/bulk_import.py:737 -#: netbox/dcim/forms/bulk_import.py:763 +#: netbox/dcim/forms/bulk_import.py:733 netbox/dcim/forms/bulk_import.py:759 +#: netbox/dcim/forms/bulk_import.py:785 msgid "Port type" msgstr "端口类型" -#: netbox/dcim/forms/bulk_import.py:719 netbox/dcim/forms/bulk_import.py:745 +#: netbox/dcim/forms/bulk_import.py:741 netbox/dcim/forms/bulk_import.py:767 msgid "Port speed in bps" msgstr "端口速率(bps)" -#: netbox/dcim/forms/bulk_import.py:783 +#: netbox/dcim/forms/bulk_import.py:805 msgid "Outlet type" msgstr "插座类型" -#: netbox/dcim/forms/bulk_import.py:790 +#: netbox/dcim/forms/bulk_import.py:812 msgid "Local power port which feeds this outlet" msgstr "该插座供电的电源端口" -#: netbox/dcim/forms/bulk_import.py:796 +#: netbox/dcim/forms/bulk_import.py:818 msgid "Electrical phase (for three-phase circuits)" msgstr "供电相位(用于三相电)" -#: netbox/dcim/forms/bulk_import.py:837 netbox/dcim/forms/model_forms.py:1316 +#: netbox/dcim/forms/bulk_import.py:859 netbox/dcim/forms/model_forms.py:1323 #: netbox/virtualization/forms/bulk_import.py:155 #: netbox/virtualization/forms/model_forms.py:305 msgid "Parent interface" msgstr "上一级接口" -#: netbox/dcim/forms/bulk_import.py:844 netbox/dcim/forms/model_forms.py:1324 +#: netbox/dcim/forms/bulk_import.py:866 netbox/dcim/forms/model_forms.py:1331 #: netbox/virtualization/forms/bulk_import.py:162 #: netbox/virtualization/forms/model_forms.py:313 msgid "Bridged interface" msgstr "桥接接口" -#: netbox/dcim/forms/bulk_import.py:847 +#: netbox/dcim/forms/bulk_import.py:869 msgid "Lag" msgstr "聚合接口" -#: netbox/dcim/forms/bulk_import.py:851 +#: netbox/dcim/forms/bulk_import.py:873 msgid "Parent LAG interface" msgstr "上一级聚合接口" -#: netbox/dcim/forms/bulk_import.py:854 +#: netbox/dcim/forms/bulk_import.py:876 msgid "Vdcs" msgstr "Vdcs" -#: netbox/dcim/forms/bulk_import.py:859 +#: netbox/dcim/forms/bulk_import.py:881 msgid "VDC names separated by commas, encased with double quotes. Example:" msgstr "VDC名称,用逗号分隔,用双引号包含。例如:" -#: netbox/dcim/forms/bulk_import.py:865 +#: netbox/dcim/forms/bulk_import.py:887 msgid "Physical medium" msgstr "物理接口类型" -#: netbox/dcim/forms/bulk_import.py:868 netbox/dcim/forms/filtersets.py:1365 +#: netbox/dcim/forms/bulk_import.py:890 netbox/dcim/forms/filtersets.py:1365 msgid "Duplex" msgstr "双工" -#: netbox/dcim/forms/bulk_import.py:873 +#: netbox/dcim/forms/bulk_import.py:895 msgid "Poe mode" msgstr "POE模式" -#: netbox/dcim/forms/bulk_import.py:879 +#: netbox/dcim/forms/bulk_import.py:901 msgid "Poe type" msgstr "POE类型" -#: netbox/dcim/forms/bulk_import.py:888 +#: netbox/dcim/forms/bulk_import.py:910 #: netbox/virtualization/forms/bulk_import.py:168 msgid "IEEE 802.1Q operational mode (for L2 interfaces)" msgstr "IEEE 802.1Q 运作模式(针对二层接口)" -#: netbox/dcim/forms/bulk_import.py:895 netbox/ipam/forms/bulk_import.py:161 +#: netbox/dcim/forms/bulk_import.py:917 netbox/ipam/forms/bulk_import.py:161 #: netbox/ipam/forms/bulk_import.py:247 netbox/ipam/forms/bulk_import.py:283 #: netbox/ipam/forms/filtersets.py:201 netbox/ipam/forms/filtersets.py:277 #: netbox/ipam/forms/filtersets.py:336 @@ -4412,172 +4445,172 @@ msgstr "IEEE 802.1Q 运作模式(针对二层接口)" msgid "Assigned VRF" msgstr "指定VRF" -#: netbox/dcim/forms/bulk_import.py:898 +#: netbox/dcim/forms/bulk_import.py:920 msgid "Rf role" msgstr "射频类型" -#: netbox/dcim/forms/bulk_import.py:901 +#: netbox/dcim/forms/bulk_import.py:923 msgid "Wireless role (AP/station)" msgstr "无线角色(AP/基站)" -#: netbox/dcim/forms/bulk_import.py:937 +#: netbox/dcim/forms/bulk_import.py:959 #, python-brace-format msgid "VDC {vdc} is not assigned to device {device}" msgstr "VDC {vdc} 没有指定给设备 {device}" -#: netbox/dcim/forms/bulk_import.py:951 netbox/dcim/forms/model_forms.py:1000 -#: netbox/dcim/forms/model_forms.py:1575 +#: netbox/dcim/forms/bulk_import.py:973 netbox/dcim/forms/model_forms.py:1007 +#: netbox/dcim/forms/model_forms.py:1582 #: netbox/dcim/forms/object_import.py:117 msgid "Rear port" msgstr "后置端口" -#: netbox/dcim/forms/bulk_import.py:954 +#: netbox/dcim/forms/bulk_import.py:976 msgid "Corresponding rear port" msgstr "对应后置端口" -#: netbox/dcim/forms/bulk_import.py:959 netbox/dcim/forms/bulk_import.py:1000 -#: netbox/dcim/forms/bulk_import.py:1216 +#: netbox/dcim/forms/bulk_import.py:981 netbox/dcim/forms/bulk_import.py:1022 +#: netbox/dcim/forms/bulk_import.py:1238 msgid "Physical medium classification" msgstr "物理端口类型" -#: netbox/dcim/forms/bulk_import.py:1028 netbox/dcim/tables/devices.py:822 +#: netbox/dcim/forms/bulk_import.py:1050 netbox/dcim/tables/devices.py:822 msgid "Installed device" msgstr "安装设备" -#: netbox/dcim/forms/bulk_import.py:1032 +#: netbox/dcim/forms/bulk_import.py:1054 msgid "Child device installed within this bay" msgstr "此托架内安装的子设备" -#: netbox/dcim/forms/bulk_import.py:1034 +#: netbox/dcim/forms/bulk_import.py:1056 msgid "Child device not found." msgstr "子设备未找到" -#: netbox/dcim/forms/bulk_import.py:1092 +#: netbox/dcim/forms/bulk_import.py:1114 msgid "Parent inventory item" msgstr "上一级库存项" -#: netbox/dcim/forms/bulk_import.py:1095 +#: netbox/dcim/forms/bulk_import.py:1117 msgid "Component type" msgstr "组件类型" -#: netbox/dcim/forms/bulk_import.py:1099 +#: netbox/dcim/forms/bulk_import.py:1121 msgid "Component Type" msgstr "组件类型" -#: netbox/dcim/forms/bulk_import.py:1102 +#: netbox/dcim/forms/bulk_import.py:1124 msgid "Compnent name" msgstr "组件名称" -#: netbox/dcim/forms/bulk_import.py:1104 +#: netbox/dcim/forms/bulk_import.py:1126 msgid "Component Name" msgstr "组件名称" -#: netbox/dcim/forms/bulk_import.py:1146 +#: netbox/dcim/forms/bulk_import.py:1168 #, python-brace-format msgid "Component not found: {device} - {component_name}" msgstr "组件未找到: {device} - {component_name}" -#: netbox/dcim/forms/bulk_import.py:1171 +#: netbox/dcim/forms/bulk_import.py:1193 msgid "Side A device" msgstr "A端设备" -#: netbox/dcim/forms/bulk_import.py:1174 netbox/dcim/forms/bulk_import.py:1192 +#: netbox/dcim/forms/bulk_import.py:1196 netbox/dcim/forms/bulk_import.py:1214 msgid "Device name" msgstr "设备名字" -#: netbox/dcim/forms/bulk_import.py:1177 +#: netbox/dcim/forms/bulk_import.py:1199 msgid "Side A type" msgstr "A端线缆类型" -#: netbox/dcim/forms/bulk_import.py:1180 netbox/dcim/forms/bulk_import.py:1198 +#: netbox/dcim/forms/bulk_import.py:1202 netbox/dcim/forms/bulk_import.py:1220 msgid "Termination type" msgstr "线缆接口类型" -#: netbox/dcim/forms/bulk_import.py:1183 +#: netbox/dcim/forms/bulk_import.py:1205 msgid "Side A name" msgstr "A端设备名称" -#: netbox/dcim/forms/bulk_import.py:1184 netbox/dcim/forms/bulk_import.py:1202 +#: netbox/dcim/forms/bulk_import.py:1206 netbox/dcim/forms/bulk_import.py:1224 msgid "Termination name" msgstr "线缆类型名称" -#: netbox/dcim/forms/bulk_import.py:1189 +#: netbox/dcim/forms/bulk_import.py:1211 msgid "Side B device" msgstr "B端设备" -#: netbox/dcim/forms/bulk_import.py:1195 +#: netbox/dcim/forms/bulk_import.py:1217 msgid "Side B type" msgstr "B端线缆类型" -#: netbox/dcim/forms/bulk_import.py:1201 +#: netbox/dcim/forms/bulk_import.py:1223 msgid "Side B name" msgstr "B端设备名称" -#: netbox/dcim/forms/bulk_import.py:1210 +#: netbox/dcim/forms/bulk_import.py:1232 #: netbox/wireless/forms/bulk_import.py:86 msgid "Connection status" msgstr "连接状态" -#: netbox/dcim/forms/bulk_import.py:1262 +#: netbox/dcim/forms/bulk_import.py:1284 #, python-brace-format msgid "Side {side_upper}: {device} {termination_object} is already connected" msgstr " {side_upper}端: {device} {termination_object}已连接" -#: netbox/dcim/forms/bulk_import.py:1268 +#: netbox/dcim/forms/bulk_import.py:1290 #, python-brace-format msgid "{side_upper} side termination not found: {device} {name}" msgstr "{side_upper} 端接口类型未发现: {device} {name}" -#: netbox/dcim/forms/bulk_import.py:1293 netbox/dcim/forms/model_forms.py:785 +#: netbox/dcim/forms/bulk_import.py:1315 netbox/dcim/forms/model_forms.py:785 #: netbox/dcim/tables/devices.py:1027 netbox/templates/dcim/device.html:132 #: netbox/templates/dcim/virtualchassis.html:27 #: netbox/templates/dcim/virtualchassis.html:67 msgid "Master" msgstr "Master" -#: netbox/dcim/forms/bulk_import.py:1297 +#: netbox/dcim/forms/bulk_import.py:1319 msgid "Master device" msgstr "主设备" -#: netbox/dcim/forms/bulk_import.py:1314 +#: netbox/dcim/forms/bulk_import.py:1336 msgid "Name of parent site" msgstr "父站点名称" -#: netbox/dcim/forms/bulk_import.py:1348 +#: netbox/dcim/forms/bulk_import.py:1370 msgid "Upstream power panel" msgstr "上一级电源面板" -#: netbox/dcim/forms/bulk_import.py:1378 +#: netbox/dcim/forms/bulk_import.py:1400 msgid "Primary or redundant" msgstr "主线路/备用线路" -#: netbox/dcim/forms/bulk_import.py:1383 +#: netbox/dcim/forms/bulk_import.py:1405 msgid "Supply type (AC/DC)" msgstr "供应类型(AC/DC)" -#: netbox/dcim/forms/bulk_import.py:1388 +#: netbox/dcim/forms/bulk_import.py:1410 msgid "Single or three-phase" msgstr "单相或三相" -#: netbox/dcim/forms/bulk_import.py:1439 netbox/dcim/forms/model_forms.py:1670 +#: netbox/dcim/forms/bulk_import.py:1461 netbox/dcim/forms/model_forms.py:1677 #: netbox/templates/dcim/device.html:190 #: netbox/templates/dcim/virtualdevicecontext.html:30 #: netbox/templates/virtualization/virtualmachine.html:52 msgid "Primary IPv4" msgstr "主 IPv4" -#: netbox/dcim/forms/bulk_import.py:1443 +#: netbox/dcim/forms/bulk_import.py:1465 msgid "IPv4 address with mask, e.g. 1.2.3.4/24" msgstr "带掩码的 IPv4 地址,例如 1.2.3.4/24" -#: netbox/dcim/forms/bulk_import.py:1446 netbox/dcim/forms/model_forms.py:1679 +#: netbox/dcim/forms/bulk_import.py:1468 netbox/dcim/forms/model_forms.py:1686 #: netbox/templates/dcim/device.html:206 #: netbox/templates/dcim/virtualdevicecontext.html:41 #: netbox/templates/virtualization/virtualmachine.html:68 msgid "Primary IPv6" msgstr "主 IPv6" -#: netbox/dcim/forms/bulk_import.py:1450 +#: netbox/dcim/forms/bulk_import.py:1472 msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64" msgstr "带有前缀长度的 IPv6 地址,例如 2001:db8:: 1/64" @@ -4658,10 +4691,6 @@ msgstr "上一级组" msgid "Facility" msgstr "设施" -#: netbox/dcim/forms/filtersets.py:380 -msgid "Rack type" -msgstr "机柜类型" - #: netbox/dcim/forms/filtersets.py:397 msgid "Function" msgstr "功能用途" @@ -4698,7 +4727,7 @@ msgid "Has virtual device contexts" msgstr "有虚拟设备上下文" #: netbox/dcim/forms/filtersets.py:903 netbox/extras/filtersets.py:585 -#: netbox/ipam/forms/bulk_edit.py:479 netbox/ipam/forms/filtersets.py:452 +#: netbox/ipam/forms/filtersets.py:452 #: netbox/virtualization/forms/filtersets.py:112 msgid "Cluster group" msgstr "堆叠组" @@ -4737,7 +4766,7 @@ msgstr "类型" msgid "Mgmt only" msgstr "仅用于管理" -#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1383 +#: netbox/dcim/forms/filtersets.py:1389 netbox/dcim/forms/model_forms.py:1390 #: netbox/dcim/models/device_components.py:629 #: netbox/templates/dcim/interface.html:129 msgid "WWN" @@ -4837,36 +4866,46 @@ msgstr "自动填充与此模块类型关联的组件" msgid "Characteristics" msgstr "特性" -#: netbox/dcim/forms/model_forms.py:1087 +#: netbox/dcim/forms/model_forms.py:914 +#, python-brace-format +msgid "" +"Alphanumeric ranges are supported for bulk creation. Mixed cases and types " +"within a single range are not supported (example: " +"[ge,xe]-0/0/[0-9]). The token {module}, if " +"present, will be automatically replaced with the position value when " +"creating a new module." +msgstr "" + +#: netbox/dcim/forms/model_forms.py:1094 msgid "Console port template" msgstr "控制台端口模板" -#: netbox/dcim/forms/model_forms.py:1095 +#: netbox/dcim/forms/model_forms.py:1102 msgid "Console server port template" msgstr "控制口模版" -#: netbox/dcim/forms/model_forms.py:1103 +#: netbox/dcim/forms/model_forms.py:1110 msgid "Front port template" msgstr "前向端口模版" -#: netbox/dcim/forms/model_forms.py:1111 +#: netbox/dcim/forms/model_forms.py:1118 msgid "Interface template" msgstr "接口模版" -#: netbox/dcim/forms/model_forms.py:1119 +#: netbox/dcim/forms/model_forms.py:1126 msgid "Power outlet template" msgstr "电源插座模版" -#: netbox/dcim/forms/model_forms.py:1127 +#: netbox/dcim/forms/model_forms.py:1134 msgid "Power port template" msgstr "电源接口模版" -#: netbox/dcim/forms/model_forms.py:1135 +#: netbox/dcim/forms/model_forms.py:1142 msgid "Rear port template" msgstr "后置接口模版" -#: netbox/dcim/forms/model_forms.py:1144 netbox/dcim/forms/model_forms.py:1388 -#: netbox/dcim/forms/model_forms.py:1551 netbox/dcim/forms/model_forms.py:1583 +#: netbox/dcim/forms/model_forms.py:1151 netbox/dcim/forms/model_forms.py:1395 +#: netbox/dcim/forms/model_forms.py:1558 netbox/dcim/forms/model_forms.py:1590 #: netbox/dcim/tables/connections.py:65 netbox/ipam/forms/bulk_import.py:318 #: netbox/ipam/forms/model_forms.py:280 netbox/ipam/forms/model_forms.py:289 #: netbox/ipam/tables/fhrp.py:64 netbox/ipam/tables/ip.py:372 @@ -4890,7 +4929,7 @@ msgstr "后置接口模版" msgid "Interface" msgstr "接口" -#: netbox/dcim/forms/model_forms.py:1145 netbox/dcim/forms/model_forms.py:1584 +#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 #: netbox/dcim/tables/connections.py:27 #: netbox/templates/dcim/consoleport.html:17 #: netbox/templates/dcim/consoleserverport.html:74 @@ -4898,14 +4937,14 @@ msgstr "接口" msgid "Console Port" msgstr "Console 端口" -#: netbox/dcim/forms/model_forms.py:1146 netbox/dcim/forms/model_forms.py:1585 +#: netbox/dcim/forms/model_forms.py:1153 netbox/dcim/forms/model_forms.py:1592 #: netbox/templates/dcim/consoleport.html:73 #: netbox/templates/dcim/consoleserverport.html:17 #: netbox/templates/dcim/frontport.html:109 msgid "Console Server Port" msgstr "Console 服务器端口" -#: netbox/dcim/forms/model_forms.py:1147 netbox/dcim/forms/model_forms.py:1586 +#: netbox/dcim/forms/model_forms.py:1154 netbox/dcim/forms/model_forms.py:1593 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/dcim/consoleport.html:76 #: netbox/templates/dcim/consoleserverport.html:77 @@ -4916,7 +4955,7 @@ msgstr "Console 服务器端口" msgid "Front Port" msgstr "前置接口" -#: netbox/dcim/forms/model_forms.py:1148 netbox/dcim/forms/model_forms.py:1587 +#: netbox/dcim/forms/model_forms.py:1155 netbox/dcim/forms/model_forms.py:1594 #: netbox/dcim/tables/devices.py:710 #: netbox/templates/circuits/inc/circuit_termination_fields.html:53 #: netbox/templates/dcim/consoleport.html:79 @@ -4929,74 +4968,74 @@ msgstr "前置接口" msgid "Rear Port" msgstr "后置接口" -#: netbox/dcim/forms/model_forms.py:1149 netbox/dcim/forms/model_forms.py:1588 +#: netbox/dcim/forms/model_forms.py:1156 netbox/dcim/forms/model_forms.py:1595 #: netbox/dcim/tables/connections.py:46 netbox/dcim/tables/devices.py:512 #: netbox/templates/dcim/poweroutlet.html:44 #: netbox/templates/dcim/powerport.html:17 msgid "Power Port" msgstr "电源接口" -#: netbox/dcim/forms/model_forms.py:1150 netbox/dcim/forms/model_forms.py:1589 +#: netbox/dcim/forms/model_forms.py:1157 netbox/dcim/forms/model_forms.py:1596 #: netbox/templates/dcim/poweroutlet.html:17 #: netbox/templates/dcim/powerport.html:77 msgid "Power Outlet" msgstr "电源插座" -#: netbox/dcim/forms/model_forms.py:1152 netbox/dcim/forms/model_forms.py:1591 +#: netbox/dcim/forms/model_forms.py:1159 netbox/dcim/forms/model_forms.py:1598 msgid "Component Assignment" msgstr "组件分配" -#: netbox/dcim/forms/model_forms.py:1195 netbox/dcim/forms/model_forms.py:1638 +#: netbox/dcim/forms/model_forms.py:1202 netbox/dcim/forms/model_forms.py:1645 msgid "An InventoryItem can only be assigned to a single component." msgstr "库存项只能分配给单个组件" -#: netbox/dcim/forms/model_forms.py:1332 +#: netbox/dcim/forms/model_forms.py:1339 msgid "LAG interface" msgstr "链路聚合接口" -#: netbox/dcim/forms/model_forms.py:1355 +#: netbox/dcim/forms/model_forms.py:1362 msgid "Filter VLANs available for assignment by group." msgstr "按组筛选可供分配的 VLAN。" -#: netbox/dcim/forms/model_forms.py:1484 +#: netbox/dcim/forms/model_forms.py:1491 msgid "Child Device" msgstr "子设备" -#: netbox/dcim/forms/model_forms.py:1485 +#: netbox/dcim/forms/model_forms.py:1492 msgid "" "Child devices must first be created and assigned to the site and rack of the" " parent device." msgstr "必须首先创建子设备,并将其分配给父设备的站点和机柜。" -#: netbox/dcim/forms/model_forms.py:1527 +#: netbox/dcim/forms/model_forms.py:1534 msgid "Console port" msgstr "Console 接口" -#: netbox/dcim/forms/model_forms.py:1535 +#: netbox/dcim/forms/model_forms.py:1542 msgid "Console server port" msgstr "Console 服务器端口" -#: netbox/dcim/forms/model_forms.py:1543 +#: netbox/dcim/forms/model_forms.py:1550 msgid "Front port" msgstr "前置接口" -#: netbox/dcim/forms/model_forms.py:1559 +#: netbox/dcim/forms/model_forms.py:1566 msgid "Power outlet" msgstr "电源插座" -#: netbox/dcim/forms/model_forms.py:1579 +#: netbox/dcim/forms/model_forms.py:1586 #: netbox/templates/dcim/inventoryitem.html:17 msgid "Inventory Item" msgstr "库存项" -#: netbox/dcim/forms/model_forms.py:1652 +#: netbox/dcim/forms/model_forms.py:1659 #: netbox/templates/dcim/inventoryitemrole.html:15 msgid "Inventory Item Role" msgstr "库存物品分类" #: netbox/dcim/forms/object_create.py:48 #: netbox/dcim/forms/object_create.py:199 -#: netbox/dcim/forms/object_create.py:355 +#: netbox/dcim/forms/object_create.py:347 msgid "" "Alphanumeric ranges are supported. (Must match the number of objects being " "created.)" @@ -5010,12 +5049,12 @@ msgid "" msgstr "提供了 {value_count}个参数,实际需要{pattern_count}个。" #: netbox/dcim/forms/object_create.py:110 -#: netbox/dcim/forms/object_create.py:271 netbox/dcim/tables/devices.py:252 +#: netbox/dcim/forms/object_create.py:263 netbox/dcim/tables/devices.py:252 msgid "Rear ports" msgstr "后置接口" #: netbox/dcim/forms/object_create.py:111 -#: netbox/dcim/forms/object_create.py:272 +#: netbox/dcim/forms/object_create.py:264 msgid "Select one rear port assignment for each front port being created." msgstr "为正在创建的每个前置接口指定一个后置接口" @@ -5026,38 +5065,31 @@ msgid "" "match the selected number of rear port positions ({rearport_count})." msgstr "要创建的前置端口数({frontport_count}) 必须与所选的后置端口数({rearport_count})匹配。" -#: netbox/dcim/forms/object_create.py:251 -#, python-brace-format -msgid "" -"The string {module} will be replaced with the position of the " -"assigned module, if any." -msgstr "字符串{module} 将替换为指定位置的模块, (如果有的话)。" - -#: netbox/dcim/forms/object_create.py:320 +#: netbox/dcim/forms/object_create.py:312 #, python-brace-format msgid "" "The number of front ports to be created ({frontport_count}) must match the " "selected number of rear port positions ({rearport_count})." msgstr "要创建的前置端口数 ({frontport_count}) 必须与所选的后置端口数({rearport_count})匹配。" -#: netbox/dcim/forms/object_create.py:409 netbox/dcim/tables/devices.py:1033 +#: netbox/dcim/forms/object_create.py:401 netbox/dcim/tables/devices.py:1033 #: netbox/ipam/tables/fhrp.py:31 netbox/templates/dcim/virtualchassis.html:53 #: netbox/templates/dcim/virtualchassis_edit.html:47 #: netbox/templates/ipam/fhrpgroup.html:38 msgid "Members" msgstr "成员" -#: netbox/dcim/forms/object_create.py:418 +#: netbox/dcim/forms/object_create.py:410 msgid "Initial position" msgstr "初始位置" -#: netbox/dcim/forms/object_create.py:421 +#: netbox/dcim/forms/object_create.py:413 msgid "" "Position of the first member device. Increases by one for each additional " "member." msgstr "第一个成员设备的位置。每增加一个成员增加一个。" -#: netbox/dcim/forms/object_create.py:435 +#: netbox/dcim/forms/object_create.py:427 msgid "A position must be specified for the first VC member." msgstr "必须为第一个VC成员指定一个位置。" @@ -5933,12 +5965,12 @@ msgstr "机柜位置(U)" msgid "rack face" msgstr "机柜安装方向" -#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1415 +#: netbox/dcim/models/devices.py:670 netbox/dcim/models/devices.py:1420 #: netbox/virtualization/models/virtualmachines.py:100 msgid "primary IPv4" msgstr "首选 IPv4" -#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1423 +#: netbox/dcim/models/devices.py:678 netbox/dcim/models/devices.py:1428 #: netbox/virtualization/models/virtualmachines.py:108 msgid "primary IPv6" msgstr "首选 IPv6" @@ -6098,55 +6130,55 @@ msgid "" "device ({device})." msgstr "模块必须安装在属于指定设备({device})的模块托架内。" -#: netbox/dcim/models/devices.py:1334 +#: netbox/dcim/models/devices.py:1339 msgid "domain" msgstr "域" -#: netbox/dcim/models/devices.py:1347 netbox/dcim/models/devices.py:1348 +#: netbox/dcim/models/devices.py:1352 netbox/dcim/models/devices.py:1353 msgid "virtual chassis" msgstr "堆叠" -#: netbox/dcim/models/devices.py:1363 +#: netbox/dcim/models/devices.py:1368 #, python-brace-format msgid "" "The selected master ({master}) is not assigned to this virtual chassis." msgstr "所选主设备({master})未分配给此堆叠。" -#: netbox/dcim/models/devices.py:1379 +#: netbox/dcim/models/devices.py:1384 #, python-brace-format msgid "" "Unable to delete virtual chassis {self}. There are member interfaces which " "form a cross-chassis LAG interfaces." msgstr "无法删除堆叠 {self}。有成员接口属于跨机箱聚合。" -#: netbox/dcim/models/devices.py:1404 netbox/vpn/models/l2vpn.py:37 +#: netbox/dcim/models/devices.py:1409 netbox/vpn/models/l2vpn.py:37 msgid "identifier" msgstr "标识符" -#: netbox/dcim/models/devices.py:1405 +#: netbox/dcim/models/devices.py:1410 msgid "Numeric identifier unique to the parent device" msgstr "父设备唯一的标识符" -#: netbox/dcim/models/devices.py:1433 netbox/extras/models/customfields.py:225 +#: netbox/dcim/models/devices.py:1438 netbox/extras/models/customfields.py:225 #: netbox/extras/models/models.py:107 netbox/extras/models/models.py:694 #: netbox/netbox/models/__init__.py:115 msgid "comments" msgstr "评论" -#: netbox/dcim/models/devices.py:1449 +#: netbox/dcim/models/devices.py:1454 msgid "virtual device context" msgstr "设备虚拟实例" -#: netbox/dcim/models/devices.py:1450 +#: netbox/dcim/models/devices.py:1455 msgid "virtual device contexts" msgstr "设备虚拟实例" -#: netbox/dcim/models/devices.py:1482 +#: netbox/dcim/models/devices.py:1487 #, python-brace-format msgid "{ip} is not an IPv{family} address." msgstr "{ip} 不是有效的 IPv{family} 地址" -#: netbox/dcim/models/devices.py:1488 +#: netbox/dcim/models/devices.py:1493 msgid "Primary IP address must belong to an interface on the assigned device." msgstr "首选 IP 地址必须属于指定设备上的接口。" @@ -6329,7 +6361,7 @@ msgstr "本地分配的标识符" #: netbox/dcim/models/racks.py:308 netbox/ipam/forms/bulk_import.py:201 #: netbox/ipam/forms/bulk_import.py:266 netbox/ipam/forms/bulk_import.py:301 -#: netbox/ipam/forms/bulk_import.py:459 +#: netbox/ipam/forms/bulk_import.py:483 #: netbox/virtualization/forms/bulk_import.py:112 msgid "Functional role" msgstr "功能角色" @@ -6534,7 +6566,7 @@ msgstr "可达性" #: netbox/netbox/navigation/menu.py:75 #: netbox/virtualization/forms/model_forms.py:122 #: netbox/virtualization/tables/clusters.py:83 -#: netbox/virtualization/views.py:206 +#: netbox/virtualization/views.py:204 msgid "Devices" msgstr "设备" @@ -6563,8 +6595,8 @@ msgid "Site Group" msgstr "站点组" #: netbox/dcim/tables/devices.py:187 netbox/dcim/tables/devices.py:1068 -#: netbox/ipam/forms/bulk_import.py:503 netbox/ipam/forms/model_forms.py:306 -#: netbox/ipam/forms/model_forms.py:315 netbox/ipam/tables/ip.py:356 +#: netbox/ipam/forms/bulk_import.py:527 netbox/ipam/forms/model_forms.py:306 +#: netbox/ipam/forms/model_forms.py:319 netbox/ipam/tables/ip.py:356 #: netbox/ipam/tables/ip.py:423 netbox/ipam/tables/ip.py:446 #: netbox/templates/ipam/ipaddress.html:11 #: netbox/virtualization/tables/virtualmachines.py:95 @@ -6615,20 +6647,20 @@ msgid "Power outlets" msgstr "电源插座" #: netbox/dcim/tables/devices.py:246 netbox/dcim/tables/devices.py:1081 -#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1042 -#: netbox/dcim/views.py:1281 netbox/dcim/views.py:1977 +#: netbox/dcim/tables/devicetypes.py:128 netbox/dcim/views.py:1040 +#: netbox/dcim/views.py:1279 netbox/dcim/views.py:1975 #: netbox/netbox/navigation/menu.py:94 netbox/netbox/navigation/menu.py:250 #: netbox/templates/dcim/device/base.html:37 #: netbox/templates/dcim/device_list.html:43 #: netbox/templates/dcim/devicetype/base.html:34 +#: netbox/templates/dcim/inc/moduletype_buttons.html:25 #: netbox/templates/dcim/module.html:34 -#: netbox/templates/dcim/moduletype/base.html:34 #: netbox/templates/dcim/virtualdevicecontext.html:61 #: netbox/templates/dcim/virtualdevicecontext.html:81 #: netbox/templates/virtualization/virtualmachine/base.html:27 #: netbox/templates/virtualization/virtualmachine_list.html:14 #: netbox/virtualization/tables/virtualmachines.py:101 -#: netbox/virtualization/views.py:366 netbox/wireless/tables/wirelesslan.py:55 +#: netbox/virtualization/views.py:364 netbox/wireless/tables/wirelesslan.py:55 msgid "Interfaces" msgstr "接口" @@ -6654,8 +6686,8 @@ msgid "Module Bay" msgstr "设备板卡插槽" #: netbox/dcim/tables/devices.py:318 netbox/dcim/tables/devicetypes.py:47 -#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1117 -#: netbox/dcim/views.py:2075 netbox/netbox/navigation/menu.py:103 +#: netbox/dcim/tables/devicetypes.py:143 netbox/dcim/views.py:1115 +#: netbox/dcim/views.py:2073 netbox/netbox/navigation/menu.py:103 #: netbox/templates/dcim/device/base.html:52 #: netbox/templates/dcim/device_list.html:71 #: netbox/templates/dcim/devicetype/base.html:49 @@ -6684,7 +6716,7 @@ msgstr "最大功率(W)" msgid "Allocated draw (W)" msgstr "分配功率(W)" -#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:701 +#: netbox/dcim/tables/devices.py:558 netbox/ipam/forms/model_forms.py:734 #: netbox/ipam/tables/fhrp.py:28 netbox/ipam/views.py:596 #: netbox/ipam/views.py:696 netbox/netbox/navigation/menu.py:158 #: netbox/netbox/navigation/menu.py:160 @@ -6780,87 +6812,87 @@ msgstr "U高度" msgid "Instances" msgstr "实例" -#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:982 -#: netbox/dcim/views.py:1221 netbox/dcim/views.py:1913 +#: netbox/dcim/tables/devicetypes.py:116 netbox/dcim/views.py:980 +#: netbox/dcim/views.py:1219 netbox/dcim/views.py:1911 #: netbox/netbox/navigation/menu.py:97 #: netbox/templates/dcim/device/base.html:25 #: netbox/templates/dcim/device_list.html:15 #: netbox/templates/dcim/devicetype/base.html:22 +#: netbox/templates/dcim/inc/moduletype_buttons.html:13 #: netbox/templates/dcim/module.html:22 -#: netbox/templates/dcim/moduletype/base.html:22 msgid "Console Ports" msgstr "Console口" -#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:997 -#: netbox/dcim/views.py:1236 netbox/dcim/views.py:1929 +#: netbox/dcim/tables/devicetypes.py:119 netbox/dcim/views.py:995 +#: netbox/dcim/views.py:1234 netbox/dcim/views.py:1927 #: netbox/netbox/navigation/menu.py:98 #: netbox/templates/dcim/device/base.html:28 #: netbox/templates/dcim/device_list.html:22 #: netbox/templates/dcim/devicetype/base.html:25 +#: netbox/templates/dcim/inc/moduletype_buttons.html:16 #: netbox/templates/dcim/module.html:25 -#: netbox/templates/dcim/moduletype/base.html:25 msgid "Console Server Ports" msgstr "Console 服务端口" -#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1012 -#: netbox/dcim/views.py:1251 netbox/dcim/views.py:1945 +#: netbox/dcim/tables/devicetypes.py:122 netbox/dcim/views.py:1010 +#: netbox/dcim/views.py:1249 netbox/dcim/views.py:1943 #: netbox/netbox/navigation/menu.py:99 #: netbox/templates/dcim/device/base.html:31 #: netbox/templates/dcim/device_list.html:29 #: netbox/templates/dcim/devicetype/base.html:28 +#: netbox/templates/dcim/inc/moduletype_buttons.html:19 #: netbox/templates/dcim/module.html:28 -#: netbox/templates/dcim/moduletype/base.html:28 msgid "Power Ports" msgstr "电源接口" -#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1027 -#: netbox/dcim/views.py:1266 netbox/dcim/views.py:1961 +#: netbox/dcim/tables/devicetypes.py:125 netbox/dcim/views.py:1025 +#: netbox/dcim/views.py:1264 netbox/dcim/views.py:1959 #: netbox/netbox/navigation/menu.py:100 #: netbox/templates/dcim/device/base.html:34 #: netbox/templates/dcim/device_list.html:36 #: netbox/templates/dcim/devicetype/base.html:31 +#: netbox/templates/dcim/inc/moduletype_buttons.html:22 #: netbox/templates/dcim/module.html:31 -#: netbox/templates/dcim/moduletype/base.html:31 msgid "Power Outlets" msgstr "PDU" -#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1057 -#: netbox/dcim/views.py:1296 netbox/dcim/views.py:1999 +#: netbox/dcim/tables/devicetypes.py:131 netbox/dcim/views.py:1055 +#: netbox/dcim/views.py:1294 netbox/dcim/views.py:1997 #: netbox/netbox/navigation/menu.py:95 #: netbox/templates/dcim/device/base.html:40 #: netbox/templates/dcim/devicetype/base.html:37 +#: netbox/templates/dcim/inc/moduletype_buttons.html:28 #: netbox/templates/dcim/module.html:37 -#: netbox/templates/dcim/moduletype/base.html:37 msgid "Front Ports" msgstr "前置端口" -#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1072 -#: netbox/dcim/views.py:1311 netbox/dcim/views.py:2015 +#: netbox/dcim/tables/devicetypes.py:134 netbox/dcim/views.py:1070 +#: netbox/dcim/views.py:1309 netbox/dcim/views.py:2013 #: netbox/netbox/navigation/menu.py:96 #: netbox/templates/dcim/device/base.html:43 #: netbox/templates/dcim/device_list.html:50 #: netbox/templates/dcim/devicetype/base.html:40 +#: netbox/templates/dcim/inc/moduletype_buttons.html:31 #: netbox/templates/dcim/module.html:40 -#: netbox/templates/dcim/moduletype/base.html:40 msgid "Rear Ports" msgstr "后置端口" -#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1102 -#: netbox/dcim/views.py:2055 netbox/netbox/navigation/menu.py:102 +#: netbox/dcim/tables/devicetypes.py:137 netbox/dcim/views.py:1100 +#: netbox/dcim/views.py:2053 netbox/netbox/navigation/menu.py:102 #: netbox/templates/dcim/device/base.html:49 #: netbox/templates/dcim/device_list.html:57 #: netbox/templates/dcim/devicetype/base.html:46 msgid "Device Bays" msgstr "机柜托架" -#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1087 -#: netbox/dcim/views.py:1326 netbox/dcim/views.py:2035 +#: netbox/dcim/tables/devicetypes.py:140 netbox/dcim/views.py:1085 +#: netbox/dcim/views.py:1324 netbox/dcim/views.py:2033 #: netbox/netbox/navigation/menu.py:101 #: netbox/templates/dcim/device/base.html:46 #: netbox/templates/dcim/device_list.html:64 #: netbox/templates/dcim/devicetype/base.html:43 +#: netbox/templates/dcim/inc/moduletype_buttons.html:34 #: netbox/templates/dcim/module.html:43 -#: netbox/templates/dcim/moduletype/base.html:43 msgid "Module Bays" msgstr "设备板卡插槽" @@ -6909,7 +6941,7 @@ msgstr "空间" #: netbox/dcim/tables/sites.py:30 netbox/dcim/tables/sites.py:57 #: netbox/extras/forms/filtersets.py:351 -#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:130 +#: netbox/extras/forms/model_forms.py:517 netbox/ipam/forms/bulk_edit.py:131 #: netbox/ipam/forms/model_forms.py:153 netbox/ipam/tables/asn.py:66 #: netbox/netbox/navigation/menu.py:15 netbox/netbox/navigation/menu.py:17 msgid "Sites" @@ -6919,28 +6951,28 @@ msgstr "站点" msgid "Test case must set peer_termination_type" msgstr "测试用例必须设置对端端点类型" -#: netbox/dcim/views.py:140 +#: netbox/dcim/views.py:138 #, python-brace-format msgid "Disconnected {count} {type}" msgstr "已断开连接{count} {type}" -#: netbox/dcim/views.py:740 netbox/netbox/navigation/menu.py:51 +#: netbox/dcim/views.py:738 netbox/netbox/navigation/menu.py:51 msgid "Reservations" msgstr "机柜预留" -#: netbox/dcim/views.py:759 netbox/templates/dcim/location.html:90 +#: netbox/dcim/views.py:757 netbox/templates/dcim/location.html:90 #: netbox/templates/dcim/site.html:140 msgid "Non-Racked Devices" msgstr "未上架设备" -#: netbox/dcim/views.py:2088 netbox/extras/forms/model_forms.py:577 +#: netbox/dcim/views.py:2086 netbox/extras/forms/model_forms.py:577 #: netbox/templates/extras/configcontext.html:10 #: netbox/virtualization/forms/model_forms.py:225 -#: netbox/virtualization/views.py:407 +#: netbox/virtualization/views.py:405 msgid "Config Context" msgstr "配置实例" -#: netbox/dcim/views.py:2098 netbox/virtualization/views.py:417 +#: netbox/dcim/views.py:2096 netbox/virtualization/views.py:415 msgid "Render Config" msgstr "提交配置" @@ -6951,35 +6983,35 @@ msgstr "渲染模板时出错: {error}" #: netbox/dcim/views.py:2149 netbox/extras/tables/tables.py:550 #: netbox/netbox/navigation/menu.py:247 netbox/netbox/navigation/menu.py:249 -#: netbox/virtualization/views.py:180 +#: netbox/virtualization/views.py:178 msgid "Virtual Machines" msgstr "虚拟机" -#: netbox/dcim/views.py:2897 +#: netbox/dcim/views.py:2907 #, python-brace-format msgid "Installed device {device} in bay {device_bay}." msgstr "已安装的设备 {device} 在海湾里 {device_bay}。" -#: netbox/dcim/views.py:2938 +#: netbox/dcim/views.py:2948 #, python-brace-format msgid "Removed device {device} from bay {device_bay}." msgstr "已移除的设备 {device} 来自海湾 {device_bay}。" -#: netbox/dcim/views.py:3044 netbox/ipam/tables/ip.py:234 +#: netbox/dcim/views.py:3054 netbox/ipam/tables/ip.py:234 msgid "Children" msgstr "子网" -#: netbox/dcim/views.py:3510 +#: netbox/dcim/views.py:3520 #, python-brace-format msgid "Added member {device}" msgstr "已添加成员 {device}" -#: netbox/dcim/views.py:3557 +#: netbox/dcim/views.py:3567 #, python-brace-format msgid "Unable to remove master device {device} from the virtual chassis." msgstr "无法移除主设备 {device} 来自虚拟机箱。" -#: netbox/dcim/views.py:3570 +#: netbox/dcim/views.py:3580 #, python-brace-format msgid "Removed {device} from virtual chassis {chassis}" msgstr "已移除 {device} 来自虚拟机箱 {chassis}" @@ -7162,7 +7194,6 @@ msgstr "更新" #: netbox/extras/choices.py:228 #: netbox/templates/circuits/inc/circuit_termination.html:23 #: netbox/templates/dcim/inc/panels/inventory_items.html:37 -#: netbox/templates/dcim/moduletype/component_templates.html:23 #: netbox/templates/dcim/powerpanel.html:66 #: netbox/templates/extras/script_list.html:35 #: netbox/templates/generic/bulk_delete.html:20 @@ -7966,19 +7997,19 @@ msgstr "在指定的时间执行脚本" msgid "Interval at which this script is re-run (in minutes)" msgstr "重新运行此脚本的间隔(分钟)" -#: netbox/extras/jobs.py:49 +#: netbox/extras/jobs.py:47 msgid "Database changes have been reverted automatically." msgstr "数据库更改已自动恢复。" -#: netbox/extras/jobs.py:56 +#: netbox/extras/jobs.py:53 msgid "Script aborted with error: " msgstr "脚本因错误而中止:" -#: netbox/extras/jobs.py:66 +#: netbox/extras/jobs.py:63 msgid "An exception occurred: " msgstr "出现异常:" -#: netbox/extras/jobs.py:71 +#: netbox/extras/jobs.py:68 msgid "Database changes have been reverted due to error." msgstr "由于出现错误,数据库更改已回滚。" @@ -8960,7 +8991,7 @@ msgstr "删除小组件:" msgid "Error deleting widget: " msgstr "删除小组件错误:" -#: netbox/extras/views.py:1172 +#: netbox/extras/views.py:1175 msgid "Unable to run script: RQ worker process not running." msgstr "无法运行脚本:RQ worker 进程未运行。" @@ -9105,7 +9136,7 @@ msgid "Prefixes which contain this prefix or IP" msgstr "包含此前缀或IP的前缀" #: netbox/ipam/filtersets.py:304 netbox/ipam/filtersets.py:572 -#: netbox/ipam/forms/bulk_edit.py:342 netbox/ipam/forms/filtersets.py:196 +#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/filtersets.py:196 #: netbox/ipam/forms/filtersets.py:331 msgid "Mask length" msgstr "掩码长度" @@ -9119,7 +9150,7 @@ msgid "VLAN number (1-4094)" msgstr "VLAN 号(1-4094)" #: netbox/ipam/filtersets.py:471 netbox/ipam/filtersets.py:475 -#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:463 +#: netbox/ipam/filtersets.py:567 netbox/ipam/forms/model_forms.py:496 #: netbox/templates/tenancy/contact.html:53 #: netbox/tenancy/forms/bulk_edit.py:113 msgid "Address" @@ -9231,16 +9262,16 @@ msgstr "需要 CIDR 掩码(例如/24)" msgid "Address pattern" msgstr "地址模式" -#: netbox/ipam/forms/bulk_edit.py:49 +#: netbox/ipam/forms/bulk_edit.py:50 msgid "Enforce unique space" msgstr "强制使用唯一空间" -#: netbox/ipam/forms/bulk_edit.py:87 +#: netbox/ipam/forms/bulk_edit.py:88 msgid "Is private" msgstr "私有的" -#: netbox/ipam/forms/bulk_edit.py:108 netbox/ipam/forms/bulk_edit.py:137 -#: netbox/ipam/forms/bulk_edit.py:162 netbox/ipam/forms/bulk_import.py:89 +#: netbox/ipam/forms/bulk_edit.py:109 netbox/ipam/forms/bulk_edit.py:138 +#: netbox/ipam/forms/bulk_edit.py:163 netbox/ipam/forms/bulk_import.py:89 #: netbox/ipam/forms/bulk_import.py:109 netbox/ipam/forms/bulk_import.py:129 #: netbox/ipam/forms/filtersets.py:110 netbox/ipam/forms/filtersets.py:125 #: netbox/ipam/forms/filtersets.py:148 netbox/ipam/forms/model_forms.py:96 @@ -9254,20 +9285,20 @@ msgstr "私有的" msgid "RIR" msgstr "区域互联网注册管理机构" -#: netbox/ipam/forms/bulk_edit.py:170 +#: netbox/ipam/forms/bulk_edit.py:171 msgid "Date added" msgstr "添加日期" -#: netbox/ipam/forms/bulk_edit.py:228 netbox/ipam/forms/model_forms.py:586 -#: netbox/ipam/forms/model_forms.py:633 netbox/ipam/tables/ip.py:251 +#: netbox/ipam/forms/bulk_edit.py:229 netbox/ipam/forms/model_forms.py:619 +#: netbox/ipam/forms/model_forms.py:666 netbox/ipam/tables/ip.py:251 #: netbox/templates/ipam/vlan_edit.html:37 #: netbox/templates/ipam/vlangroup.html:27 msgid "VLAN Group" msgstr "VLAN组" -#: netbox/ipam/forms/bulk_edit.py:233 netbox/ipam/forms/bulk_import.py:185 +#: netbox/ipam/forms/bulk_edit.py:234 netbox/ipam/forms/bulk_import.py:185 #: netbox/ipam/forms/filtersets.py:256 netbox/ipam/forms/model_forms.py:218 -#: netbox/ipam/models/vlans.py:234 netbox/ipam/tables/ip.py:255 +#: netbox/ipam/models/vlans.py:250 netbox/ipam/tables/ip.py:255 #: netbox/templates/ipam/prefix.html:60 netbox/templates/ipam/vlan.html:12 #: netbox/templates/ipam/vlan/base.html:6 #: netbox/templates/ipam/vlan_edit.html:10 @@ -9280,32 +9311,32 @@ msgstr "VLAN组" msgid "VLAN" msgstr "VLAN" -#: netbox/ipam/forms/bulk_edit.py:244 +#: netbox/ipam/forms/bulk_edit.py:245 msgid "Prefix length" msgstr "前缀长度" -#: netbox/ipam/forms/bulk_edit.py:267 netbox/ipam/forms/filtersets.py:241 +#: netbox/ipam/forms/bulk_edit.py:268 netbox/ipam/forms/filtersets.py:241 #: netbox/templates/ipam/prefix.html:85 msgid "Is a pool" msgstr "是一个池" -#: netbox/ipam/forms/bulk_edit.py:272 netbox/ipam/forms/bulk_edit.py:317 +#: netbox/ipam/forms/bulk_edit.py:273 netbox/ipam/forms/bulk_edit.py:318 #: netbox/ipam/forms/filtersets.py:248 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/models/ip.py:272 netbox/ipam/models/ip.py:539 msgid "Treat as fully utilized" msgstr "设置为已被全部占用" -#: netbox/ipam/forms/bulk_edit.py:286 netbox/ipam/forms/filtersets.py:171 +#: netbox/ipam/forms/bulk_edit.py:287 netbox/ipam/forms/filtersets.py:171 msgid "VLAN Assignment" msgstr "VLAN 分配" -#: netbox/ipam/forms/bulk_edit.py:365 netbox/ipam/models/ip.py:772 +#: netbox/ipam/forms/bulk_edit.py:366 netbox/ipam/models/ip.py:772 msgid "DNS name" msgstr "DNS 名称" -#: netbox/ipam/forms/bulk_edit.py:386 netbox/ipam/forms/bulk_edit.py:579 -#: netbox/ipam/forms/bulk_import.py:394 netbox/ipam/forms/bulk_import.py:469 -#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/filtersets.py:390 +#: netbox/ipam/forms/bulk_edit.py:387 netbox/ipam/forms/bulk_edit.py:534 +#: netbox/ipam/forms/bulk_import.py:418 netbox/ipam/forms/bulk_import.py:493 +#: netbox/ipam/forms/bulk_import.py:519 netbox/ipam/forms/filtersets.py:390 #: netbox/ipam/forms/filtersets.py:530 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/service.html:32 @@ -9313,12 +9344,12 @@ msgstr "DNS 名称" msgid "Protocol" msgstr "协议" -#: netbox/ipam/forms/bulk_edit.py:393 netbox/ipam/forms/filtersets.py:397 +#: netbox/ipam/forms/bulk_edit.py:394 netbox/ipam/forms/filtersets.py:397 #: netbox/ipam/tables/fhrp.py:22 netbox/templates/ipam/fhrpgroup.html:26 msgid "Group ID" msgstr "组 ID" -#: netbox/ipam/forms/bulk_edit.py:398 netbox/ipam/forms/filtersets.py:402 +#: netbox/ipam/forms/bulk_edit.py:399 netbox/ipam/forms/filtersets.py:402 #: netbox/wireless/forms/bulk_edit.py:68 #: netbox/wireless/forms/bulk_edit.py:115 #: netbox/wireless/forms/bulk_import.py:62 @@ -9330,12 +9361,12 @@ msgstr "组 ID" msgid "Authentication type" msgstr "认证类型" -#: netbox/ipam/forms/bulk_edit.py:403 netbox/ipam/forms/filtersets.py:406 +#: netbox/ipam/forms/bulk_edit.py:404 netbox/ipam/forms/filtersets.py:406 msgid "Authentication key" msgstr "认证秘钥" -#: netbox/ipam/forms/bulk_edit.py:420 netbox/ipam/forms/filtersets.py:383 -#: netbox/ipam/forms/model_forms.py:474 netbox/netbox/navigation/menu.py:386 +#: netbox/ipam/forms/bulk_edit.py:421 netbox/ipam/forms/filtersets.py:383 +#: netbox/ipam/forms/model_forms.py:507 netbox/netbox/navigation/menu.py:386 #: netbox/templates/ipam/fhrpgroup.html:49 #: netbox/templates/wireless/inc/authentication_attrs.html:5 #: netbox/wireless/forms/bulk_edit.py:91 @@ -9347,26 +9378,26 @@ msgstr "认证秘钥" msgid "Authentication" msgstr "身份验证" -#: netbox/ipam/forms/bulk_edit.py:432 netbox/ipam/forms/model_forms.py:575 +#: netbox/ipam/forms/bulk_edit.py:436 netbox/ipam/forms/model_forms.py:608 msgid "Scope type" msgstr "作用域类型" -#: netbox/ipam/forms/bulk_edit.py:490 netbox/ipam/models/vlans.py:60 -msgid "VLAN ID ranges" -msgstr "VLAN ID 范围" - -#: netbox/ipam/forms/bulk_edit.py:498 netbox/ipam/forms/model_forms.py:578 -#: netbox/ipam/forms/model_forms.py:588 netbox/ipam/tables/vlans.py:71 -#: netbox/templates/ipam/vlangroup.html:38 +#: netbox/ipam/forms/bulk_edit.py:439 netbox/ipam/forms/bulk_edit.py:453 +#: netbox/ipam/forms/model_forms.py:611 netbox/ipam/forms/model_forms.py:621 +#: netbox/ipam/tables/vlans.py:71 netbox/templates/ipam/vlangroup.html:38 msgid "Scope" msgstr "作用域" -#: netbox/ipam/forms/bulk_edit.py:570 +#: netbox/ipam/forms/bulk_edit.py:446 netbox/ipam/models/vlans.py:60 +msgid "VLAN ID ranges" +msgstr "VLAN ID 范围" + +#: netbox/ipam/forms/bulk_edit.py:525 msgid "Site & Group" msgstr "站点 & 组" -#: netbox/ipam/forms/bulk_edit.py:584 netbox/ipam/forms/model_forms.py:659 -#: netbox/ipam/forms/model_forms.py:691 netbox/ipam/tables/services.py:19 +#: netbox/ipam/forms/bulk_edit.py:539 netbox/ipam/forms/model_forms.py:692 +#: netbox/ipam/forms/model_forms.py:724 netbox/ipam/tables/services.py:19 #: netbox/ipam/tables/services.py:49 netbox/templates/ipam/service.html:36 #: netbox/templates/ipam/servicetemplate.html:23 msgid "Ports" @@ -9393,8 +9424,8 @@ msgstr "VLAN 组(若存在)" msgid "Parent device of assigned interface (if any)" msgstr "指定接口的父设备(如果有)" -#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:488 -#: netbox/ipam/forms/model_forms.py:685 +#: netbox/ipam/forms/bulk_import.py:311 netbox/ipam/forms/bulk_import.py:512 +#: netbox/ipam/forms/model_forms.py:718 #: netbox/virtualization/filtersets.py:288 #: netbox/virtualization/filtersets.py:327 #: netbox/virtualization/forms/bulk_edit.py:200 @@ -9420,39 +9451,59 @@ msgstr "首选" msgid "Make this the primary IP for the assigned device" msgstr "设置为设备的首选 IP" -#: netbox/ipam/forms/bulk_import.py:365 +#: netbox/ipam/forms/bulk_import.py:330 +msgid "Is out-of-band" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:331 +msgid "Designate this as the out-of-band IP address for the assigned device" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:371 msgid "No device or virtual machine specified; cannot set as primary IP" msgstr "未指定设备或虚拟机;无法设置为首选 IP" -#: netbox/ipam/forms/bulk_import.py:369 +#: netbox/ipam/forms/bulk_import.py:375 +msgid "No device specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:379 +msgid "Cannot set out-of-band IP for virtual machines" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:383 msgid "No interface specified; cannot set as primary IP" msgstr "未指定接口;无法设置为首选 IP" -#: netbox/ipam/forms/bulk_import.py:398 +#: netbox/ipam/forms/bulk_import.py:387 +msgid "No interface specified; cannot set as out-of-band IP" +msgstr "" + +#: netbox/ipam/forms/bulk_import.py:422 msgid "Auth type" msgstr "认证类型" -#: netbox/ipam/forms/bulk_import.py:413 +#: netbox/ipam/forms/bulk_import.py:437 msgid "Scope type (app & model)" msgstr "作用域类型(应用程序&型号)" -#: netbox/ipam/forms/bulk_import.py:440 +#: netbox/ipam/forms/bulk_import.py:464 msgid "Assigned VLAN group" msgstr "分配的VLAN组" -#: netbox/ipam/forms/bulk_import.py:471 netbox/ipam/forms/bulk_import.py:497 +#: netbox/ipam/forms/bulk_import.py:495 netbox/ipam/forms/bulk_import.py:521 msgid "IP protocol" msgstr "IP 协议" -#: netbox/ipam/forms/bulk_import.py:485 +#: netbox/ipam/forms/bulk_import.py:509 msgid "Required if not assigned to a VM" msgstr "如果未分配给虚拟机,则为必需" -#: netbox/ipam/forms/bulk_import.py:492 +#: netbox/ipam/forms/bulk_import.py:516 msgid "Required if not assigned to a device" msgstr "如果未分配给设备,则为必需" -#: netbox/ipam/forms/bulk_import.py:517 +#: netbox/ipam/forms/bulk_import.py:541 #, python-brace-format msgid "{ip} is not assigned to this device/VM." msgstr "{ip} 未分配给此设备/虚拟机。" @@ -9534,7 +9585,7 @@ msgstr "指定给一个接口" msgid "DNS Name" msgstr "DNS名称" -#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:235 +#: netbox/ipam/forms/filtersets.py:416 netbox/ipam/models/vlans.py:251 #: netbox/ipam/tables/ip.py:176 netbox/ipam/tables/vlans.py:82 #: netbox/ipam/views.py:971 netbox/netbox/navigation/menu.py:193 #: netbox/netbox/navigation/menu.py:195 @@ -9545,13 +9596,13 @@ msgstr "VLANs" msgid "Contains VLAN ID" msgstr "包含 VLAN ID" -#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:176 +#: netbox/ipam/forms/filtersets.py:513 netbox/ipam/models/vlans.py:192 #: netbox/templates/ipam/vlan.html:31 msgid "VLAN ID" msgstr "VLAN ID" -#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:320 -#: netbox/ipam/forms/model_forms.py:713 netbox/ipam/forms/model_forms.py:739 +#: netbox/ipam/forms/filtersets.py:556 netbox/ipam/forms/model_forms.py:324 +#: netbox/ipam/forms/model_forms.py:746 netbox/ipam/forms/model_forms.py:772 #: netbox/ipam/tables/vlans.py:195 #: netbox/templates/virtualization/virtualdisk.html:21 #: netbox/templates/virtualization/virtualmachine.html:12 @@ -9562,7 +9613,7 @@ msgstr "VLAN ID" #: netbox/virtualization/forms/model_forms.py:220 #: netbox/virtualization/tables/virtualmachines.py:135 #: netbox/virtualization/tables/virtualmachines.py:190 -#: netbox/vpn/choices.py:45 netbox/vpn/forms/filtersets.py:293 +#: netbox/vpn/choices.py:53 netbox/vpn/forms/filtersets.py:293 #: netbox/vpn/forms/model_forms.py:160 netbox/vpn/forms/model_forms.py:171 #: netbox/vpn/forms/model_forms.py:273 netbox/vpn/forms/model_forms.py:454 msgid "Virtual Machine" @@ -9591,8 +9642,8 @@ msgstr "Site/VLAN 分配" msgid "IP Range" msgstr "IP范围" -#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:321 -#: netbox/ipam/forms/model_forms.py:473 +#: netbox/ipam/forms/model_forms.py:295 netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:506 #: netbox/templates/ipam/fhrpgroup.html:19 msgid "FHRP Group" msgstr "FHRP组" @@ -9601,75 +9652,87 @@ msgstr "FHRP组" msgid "Make this the primary IP for the device/VM" msgstr "将此IP设置为分配设备/虚拟机的首选 IP" -#: netbox/ipam/forms/model_forms.py:325 +#: netbox/ipam/forms/model_forms.py:314 +msgid "Make this the out-of-band IP for the device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:329 msgid "NAT IP (Inside)" msgstr "NAT IP(内部)地址" -#: netbox/ipam/forms/model_forms.py:384 +#: netbox/ipam/forms/model_forms.py:391 msgid "An IP address can only be assigned to a single object." msgstr "IP 地址只能分配给单个对象。" -#: netbox/ipam/forms/model_forms.py:390 netbox/ipam/models/ip.py:897 -msgid "" -"Cannot reassign IP address while it is designated as the primary IP for the " -"parent object" -msgstr "当 IP 地址被指定为父对象的首选 IP 时,无法重新分配 IP 地址" +#: netbox/ipam/forms/model_forms.py:398 +msgid "Cannot reassign primary IP address for the parent device/VM" +msgstr "" -#: netbox/ipam/forms/model_forms.py:400 +#: netbox/ipam/forms/model_forms.py:402 +msgid "Cannot reassign out-of-Band IP address for the parent device" +msgstr "" + +#: netbox/ipam/forms/model_forms.py:412 msgid "" "Only IP addresses assigned to an interface can be designated as primary IPs." msgstr "只有分配给接口的 IP 地址才能指定为首选 IP。" -#: netbox/ipam/forms/model_forms.py:475 +#: netbox/ipam/forms/model_forms.py:420 +msgid "" +"Only IP addresses assigned to a device interface can be designated as the " +"out-of-band IP for a device." +msgstr "" + +#: netbox/ipam/forms/model_forms.py:508 msgid "Virtual IP Address" msgstr "虚拟IP地址" -#: netbox/ipam/forms/model_forms.py:560 +#: netbox/ipam/forms/model_forms.py:593 msgid "Assignment already exists" msgstr "已被分配" -#: netbox/ipam/forms/model_forms.py:569 +#: netbox/ipam/forms/model_forms.py:602 #: netbox/templates/ipam/vlangroup.html:42 msgid "VLAN IDs" msgstr "VLAN ID" -#: netbox/ipam/forms/model_forms.py:587 +#: netbox/ipam/forms/model_forms.py:620 msgid "Child VLANs" msgstr "子类 VLANs" -#: netbox/ipam/forms/model_forms.py:664 netbox/ipam/forms/model_forms.py:696 +#: netbox/ipam/forms/model_forms.py:697 netbox/ipam/forms/model_forms.py:729 msgid "" "Comma-separated list of one or more port numbers. A range may be specified " "using a hyphen." msgstr "一个或多个端口号的列表,逗号分隔。可以使用连字符指定范围。" -#: netbox/ipam/forms/model_forms.py:669 +#: netbox/ipam/forms/model_forms.py:702 #: netbox/templates/ipam/servicetemplate.html:12 msgid "Service Template" msgstr "服务模版" -#: netbox/ipam/forms/model_forms.py:716 +#: netbox/ipam/forms/model_forms.py:749 msgid "Port(s)" msgstr "端口" -#: netbox/ipam/forms/model_forms.py:717 netbox/ipam/forms/model_forms.py:745 +#: netbox/ipam/forms/model_forms.py:750 netbox/ipam/forms/model_forms.py:778 #: netbox/templates/ipam/service.html:21 msgid "Service" msgstr "服务" -#: netbox/ipam/forms/model_forms.py:730 +#: netbox/ipam/forms/model_forms.py:763 msgid "Service template" msgstr "服务模版" -#: netbox/ipam/forms/model_forms.py:742 +#: netbox/ipam/forms/model_forms.py:775 msgid "From Template" msgstr "来自模版" -#: netbox/ipam/forms/model_forms.py:743 +#: netbox/ipam/forms/model_forms.py:776 msgid "Custom" msgstr "自定义" -#: netbox/ipam/forms/model_forms.py:773 +#: netbox/ipam/forms/model_forms.py:806 msgid "" "Must specify name, protocol, and port(s) if not using a service template." msgstr "如果不使用服务模板,则必须指定名称、协议和端口。" @@ -9941,6 +10004,12 @@ msgstr "{ip}是一个广播地址,不能分配给接口。" msgid "Duplicate IP address found in {table}: {ipaddress}" msgstr "在 {table}中发现重复的IP地址: {ipaddress}" +#: netbox/ipam/models/ip.py:897 +msgid "" +"Cannot reassign IP address while it is designated as the primary IP for the " +"parent object" +msgstr "当 IP 地址被指定为父对象的首选 IP 时,无法重新分配 IP 地址" + #: netbox/ipam/models/ip.py:903 msgid "Only IPv6 addresses can be assigned SLAAC status" msgstr "只能为IPv6地址分配SLAAC状态" @@ -9991,45 +10060,55 @@ msgstr "没有作用域id,无法设置作用域。" msgid "Cannot set scope_id without scope_type." msgstr "没有作用域类型,无法设置作用域。" -#: netbox/ipam/models/vlans.py:101 +#: netbox/ipam/models/vlans.py:105 +#, python-brace-format +msgid "Starting VLAN ID in range ({value}) cannot be less than {minimum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:111 +#, python-brace-format +msgid "Ending VLAN ID in range ({value}) cannot exceed {maximum}" +msgstr "" + +#: netbox/ipam/models/vlans.py:118 +#, python-brace-format +msgid "" +"Ending VLAN ID in range must be greater than or equal to the starting VLAN " +"ID ({range})" +msgstr "" + +#: netbox/ipam/models/vlans.py:124 msgid "Ranges cannot overlap." msgstr "范围不能重叠。" -#: netbox/ipam/models/vlans.py:106 -#, python-brace-format -msgid "" -"Maximum child VID must be greater than or equal to minimum child VID " -"({value})" -msgstr "儿童 VID 的最大值必须大于或等于最小孩子 VID ({value})" - -#: netbox/ipam/models/vlans.py:165 +#: netbox/ipam/models/vlans.py:181 msgid "The specific site to which this VLAN is assigned (if any)" msgstr "此VLAN所属的站点(如果有)" -#: netbox/ipam/models/vlans.py:173 +#: netbox/ipam/models/vlans.py:189 msgid "VLAN group (optional)" msgstr "VLAN组(可选)" -#: netbox/ipam/models/vlans.py:181 +#: netbox/ipam/models/vlans.py:197 msgid "Numeric VLAN ID (1-4094)" msgstr "VLAN ID(1-4094)" -#: netbox/ipam/models/vlans.py:199 +#: netbox/ipam/models/vlans.py:215 msgid "Operational status of this VLAN" msgstr "此VLAN的操作状态" -#: netbox/ipam/models/vlans.py:207 +#: netbox/ipam/models/vlans.py:223 msgid "The primary function of this VLAN" msgstr "此VLAN的主要功能" -#: netbox/ipam/models/vlans.py:250 +#: netbox/ipam/models/vlans.py:266 #, python-brace-format msgid "" "VLAN is assigned to group {group} (scope: {scope}); cannot also assign to " "site {site}." msgstr "VLAN 已分配给组 {group}(作用域:{scope}); 不能再分配给站点:{site}。" -#: netbox/ipam/models/vlans.py:259 +#: netbox/ipam/models/vlans.py:275 #, python-brace-format msgid "VID must be in ranges {ranges} for VLANs in group {group}" msgstr "VID 必须在范围内 {ranges} 对于组中的 VLAN {group}" @@ -10782,17 +10861,12 @@ msgstr "IPSec策略" msgid "IPSec Profiles" msgstr "IPSec 配置文件" -#: netbox/netbox/navigation/menu.py:243 -#: netbox/templates/dcim/device_edit.html:78 -msgid "Virtualization" -msgstr "虚拟化" - #: netbox/netbox/navigation/menu.py:251 #: netbox/templates/virtualization/virtualmachine.html:174 #: netbox/templates/virtualization/virtualmachine/base.html:32 #: netbox/templates/virtualization/virtualmachine_list.html:21 #: netbox/virtualization/tables/virtualmachines.py:104 -#: netbox/virtualization/views.py:388 +#: netbox/virtualization/views.py:386 msgid "Virtual Disks" msgstr "虚拟磁盘" @@ -10954,7 +11028,7 @@ msgstr "系统" #: netbox/netbox/navigation/menu.py:454 netbox/netbox/navigation/menu.py:502 #: netbox/templates/500.html:35 netbox/templates/account/preferences.html:22 -#: netbox/templates/core/plugin.html:12 +#: netbox/templates/core/plugin.html:13 #: netbox/templates/core/plugin_list.html:7 #: netbox/templates/core/plugin_list.html:12 msgid "Plugins" @@ -11194,19 +11268,19 @@ msgstr "渲染所选导出模板时出错 ({template}): {error}" msgid "Row {i}: Object with ID {id} does not exist" msgstr "第{i}行: ID为{id}的对象不存在" -#: netbox/netbox/views/generic/bulk_views.py:699 -#: netbox/netbox/views/generic/bulk_views.py:897 -#: netbox/netbox/views/generic/bulk_views.py:945 +#: netbox/netbox/views/generic/bulk_views.py:709 +#: netbox/netbox/views/generic/bulk_views.py:910 +#: netbox/netbox/views/generic/bulk_views.py:958 #, python-brace-format msgid "No {object_type} were selected." msgstr "没有 {object_type} 被选中。" -#: netbox/netbox/views/generic/bulk_views.py:779 +#: netbox/netbox/views/generic/bulk_views.py:788 #, python-brace-format msgid "Renamed {count} {object_type}" msgstr "重命名 {count} {object_type}" -#: netbox/netbox/views/generic/bulk_views.py:875 +#: netbox/netbox/views/generic/bulk_views.py:888 #, python-brace-format msgid "Deleted {count} {object_type}" msgstr "已删除 {count} {object_type}" @@ -11238,7 +11312,7 @@ msgstr "已同步 {count} {object_type}" msgid "{class_name} must implement get_children()" msgstr "{class_name}必须实现get_children()方法" -#: netbox/netbox/views/misc.py:44 +#: netbox/netbox/views/misc.py:46 msgid "" "There was an error loading the dashboard configuration. A default dashboard " "is in use." @@ -11580,9 +11654,7 @@ msgid "Circuit Type" msgstr "线路类型" #: netbox/templates/circuits/inc/circuit_termination.html:10 -#: netbox/templates/dcim/devicetype/component_templates.html:33 #: netbox/templates/dcim/manufacturer.html:11 -#: netbox/templates/dcim/moduletype/component_templates.html:29 #: netbox/templates/generic/bulk_add_component.html:22 #: netbox/templates/users/objectpermission.html:38 #: netbox/utilities/templates/buttons/add.html:4 @@ -11593,7 +11665,6 @@ msgstr "添加" #: netbox/templates/circuits/inc/circuit_termination.html:15 #: netbox/templates/circuits/inc/circuit_termination_fields.html:36 #: netbox/templates/dcim/inc/panels/inventory_items.html:32 -#: netbox/templates/dcim/moduletype/component_templates.html:20 #: netbox/templates/dcim/powerpanel.html:56 #: netbox/templates/extras/script_list.html:30 #: netbox/templates/generic/object_edit.html:47 @@ -11881,35 +11952,35 @@ msgstr "天" msgid "Indefinite" msgstr "无限期的" -#: netbox/templates/core/plugin.html:21 +#: netbox/templates/core/plugin.html:22 msgid "Not installed" msgstr "未安装" -#: netbox/templates/core/plugin.html:32 +#: netbox/templates/core/plugin.html:33 msgid "Overview" msgstr "概述" -#: netbox/templates/core/plugin.html:38 +#: netbox/templates/core/plugin.html:39 msgid "Install" msgstr "安装" -#: netbox/templates/core/plugin.html:50 +#: netbox/templates/core/plugin.html:51 msgid "Plugin Details" msgstr "插件详情" -#: netbox/templates/core/plugin.html:57 +#: netbox/templates/core/plugin.html:58 msgid "Summary" msgstr "摘要" -#: netbox/templates/core/plugin.html:75 +#: netbox/templates/core/plugin.html:76 msgid "License" msgstr "执照" -#: netbox/templates/core/plugin.html:95 +#: netbox/templates/core/plugin.html:96 msgid "Version History" msgstr "版本历史" -#: netbox/templates/core/plugin.html:106 +#: netbox/templates/core/plugin.html:107 msgid "Local Installation Instructions" msgstr "本地安装说明" @@ -12250,8 +12321,8 @@ msgstr "添加服务" #: netbox/templates/dcim/device/base.html:21 #: netbox/templates/dcim/device_list.html:9 #: netbox/templates/dcim/devicetype/base.html:18 +#: netbox/templates/dcim/inc/moduletype_buttons.html:9 #: netbox/templates/dcim/module.html:18 -#: netbox/templates/dcim/moduletype/base.html:18 #: netbox/templates/virtualization/virtualmachine/base.html:22 #: netbox/templates/virtualization/virtualmachine_list.html:8 msgid "Add Components" @@ -12324,20 +12395,24 @@ msgstr "配置" msgid "Context Data" msgstr "实例数据" -#: netbox/templates/dcim/device/render_config.html:53 -#: netbox/templates/virtualization/virtualmachine/render_config.html:53 +#: netbox/templates/dcim/device/render_config.html:55 +#: netbox/templates/virtualization/virtualmachine/render_config.html:55 msgid "Rendered Config" msgstr "提交配置" -#: netbox/templates/dcim/device/render_config.html:55 -#: netbox/templates/virtualization/virtualmachine/render_config.html:55 +#: netbox/templates/dcim/device/render_config.html:57 +#: netbox/templates/virtualization/virtualmachine/render_config.html:57 msgid "Download" msgstr "下载" -#: netbox/templates/dcim/device/render_config.html:61 -#: netbox/templates/virtualization/virtualmachine/render_config.html:61 -msgid "No configuration template found" -msgstr "找不到配置模板" +#: netbox/templates/dcim/device/render_config.html:64 +#: netbox/templates/virtualization/virtualmachine/render_config.html:64 +msgid "Error rendering template" +msgstr "" + +#: netbox/templates/dcim/device/render_config.html:70 +msgid "No configuration template has been assigned for this device." +msgstr "" #: netbox/templates/dcim/device_edit.html:44 msgid "Parent Bay" @@ -12359,7 +12434,6 @@ msgid "Local Config Context Data" msgstr "本地配置数据实例" #: netbox/templates/dcim/device_list.html:82 -#: netbox/templates/dcim/moduletype/component_templates.html:17 #: netbox/templates/generic/bulk_rename.html:57 #: netbox/templates/virtualization/virtualmachine/interfaces.html:11 #: netbox/templates/virtualization/virtualmachine/virtual_disks.html:11 @@ -12404,12 +12478,12 @@ msgid "VM Role" msgstr "虚拟机角色" #: netbox/templates/dcim/devicetype.html:18 -#: netbox/templates/dcim/moduletype.html:18 +#: netbox/templates/dcim/moduletype.html:29 msgid "Model Name" msgstr "模块名称" #: netbox/templates/dcim/devicetype.html:25 -#: netbox/templates/dcim/moduletype.html:22 +#: netbox/templates/dcim/moduletype.html:33 msgid "Part Number" msgstr "部件编码(PN)" @@ -12548,7 +12622,7 @@ msgstr "MAC 地址" msgid "Wireless Link" msgstr "无线连接" -#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:55 +#: netbox/templates/dcim/interface.html:218 netbox/vpn/choices.py:63 msgid "Peer" msgstr "对端" @@ -13149,7 +13223,7 @@ msgstr "您没有权限执行脚本" #: netbox/templates/extras/script.html:41 #: netbox/templates/extras/script.html:45 -#: netbox/templates/extras/script_list.html:86 +#: netbox/templates/extras/script_list.html:87 msgid "Run Script" msgstr "保存运行脚本计划" @@ -13162,27 +13236,32 @@ msgstr "加载脚本时出错" msgid "Script no longer exists in the source file." msgstr "源文件中没有该脚本。" -#: netbox/templates/extras/script_list.html:46 +#: netbox/templates/extras/script_list.html:47 msgid "Last Run" msgstr "上一次运行" -#: netbox/templates/extras/script_list.html:61 +#: netbox/templates/extras/script_list.html:62 msgid "Script is no longer present in the source file" msgstr "源文件中没有该脚本。" -#: netbox/templates/extras/script_list.html:74 +#: netbox/templates/extras/script_list.html:75 msgid "Never" msgstr "从不" -#: netbox/templates/extras/script_list.html:84 +#: netbox/templates/extras/script_list.html:85 msgid "Run Again" msgstr "重新运行" -#: netbox/templates/extras/script_list.html:138 +#: netbox/templates/extras/script_list.html:133 +#, python-format +msgid "Could not load scripts from module %(module)s" +msgstr "" + +#: netbox/templates/extras/script_list.html:141 msgid "No Scripts Found" msgstr "找不到脚本" -#: netbox/templates/extras/script_list.html:141 +#: netbox/templates/extras/script_list.html:144 #, python-format msgid "" "Get started by creating a script from " @@ -13493,7 +13572,7 @@ msgstr "所有通知" msgid "Select" msgstr "选择" -#: netbox/templates/inc/filter_list.html:42 +#: netbox/templates/inc/filter_list.html:43 #: netbox/utilities/templates/helpers/table_config_form.html:39 msgid "Reset" msgstr "重置" @@ -13968,6 +14047,10 @@ msgstr "资源" msgid "Add Virtual Disk" msgstr "增加虚拟硬盘" +#: netbox/templates/virtualization/virtualmachine/render_config.html:70 +msgid "No configuration template has been assigned for this virtual machine." +msgstr "" + #: netbox/templates/vpn/ikepolicy.html:10 #: netbox/templates/vpn/ipsecprofile.html:33 netbox/vpn/tables/crypto.py:166 msgid "IKE Policy" @@ -14982,13 +15065,13 @@ msgid "Memory (MB)" msgstr "内存 (MB)" #: netbox/virtualization/forms/bulk_edit.py:174 -msgid "Disk (GB)" -msgstr "磁盘 (GB)" +msgid "Disk (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_edit.py:334 #: netbox/virtualization/forms/filtersets.py:251 -msgid "Size (GB)" -msgstr "大小 (GB)" +msgid "Size (MB)" +msgstr "" #: netbox/virtualization/forms/bulk_import.py:44 msgid "Type of cluster" @@ -15155,68 +15238,80 @@ msgstr "虚拟磁盘" msgid "virtual disks" msgstr "虚拟磁盘" -#: netbox/virtualization/views.py:275 +#: netbox/virtualization/views.py:273 #, python-brace-format msgid "Added {count} devices to cluster {cluster}" msgstr "已添加 {count} 要集群的设备 {cluster}" -#: netbox/virtualization/views.py:310 +#: netbox/virtualization/views.py:308 #, python-brace-format msgid "Removed {count} devices from cluster {cluster}" msgstr "已移除 {count} 来自集群的设备 {cluster}" -#: netbox/vpn/choices.py:31 +#: netbox/vpn/choices.py:35 msgid "IPsec - Transport" msgstr "IPsec-传输模式" -#: netbox/vpn/choices.py:32 +#: netbox/vpn/choices.py:36 msgid "IPsec - Tunnel" msgstr "IPsec - Tunnel" -#: netbox/vpn/choices.py:33 +#: netbox/vpn/choices.py:37 msgid "IP-in-IP" msgstr "IP-in-IP" -#: netbox/vpn/choices.py:34 +#: netbox/vpn/choices.py:38 msgid "GRE" msgstr "GRE" -#: netbox/vpn/choices.py:56 +#: netbox/vpn/choices.py:39 +msgid "WireGuard" +msgstr "" + +#: netbox/vpn/choices.py:40 +msgid "OpenVPN" +msgstr "" + +#: netbox/vpn/choices.py:41 +msgid "L2TP" +msgstr "" + +#: netbox/vpn/choices.py:42 +msgid "PPTP" +msgstr "" + +#: netbox/vpn/choices.py:64 msgid "Hub" msgstr "中心节点" -#: netbox/vpn/choices.py:57 +#: netbox/vpn/choices.py:65 msgid "Spoke" msgstr "分支节点" -#: netbox/vpn/choices.py:80 +#: netbox/vpn/choices.py:88 msgid "Aggressive" msgstr "野蛮模式" -#: netbox/vpn/choices.py:81 +#: netbox/vpn/choices.py:89 msgid "Main" msgstr "主模式" -#: netbox/vpn/choices.py:92 +#: netbox/vpn/choices.py:100 msgid "Pre-shared keys" msgstr "预共享密钥" -#: netbox/vpn/choices.py:93 +#: netbox/vpn/choices.py:101 msgid "Certificates" msgstr "证书" -#: netbox/vpn/choices.py:94 +#: netbox/vpn/choices.py:102 msgid "RSA signatures" msgstr "RSA 签名" -#: netbox/vpn/choices.py:95 +#: netbox/vpn/choices.py:103 msgid "DSA signatures" msgstr "DSA 签名" -#: netbox/vpn/choices.py:178 netbox/vpn/choices.py:179 -#: netbox/vpn/choices.py:180 netbox/vpn/choices.py:181 -#: netbox/vpn/choices.py:182 netbox/vpn/choices.py:183 -#: netbox/vpn/choices.py:184 netbox/vpn/choices.py:185 #: netbox/vpn/choices.py:186 netbox/vpn/choices.py:187 #: netbox/vpn/choices.py:188 netbox/vpn/choices.py:189 #: netbox/vpn/choices.py:190 netbox/vpn/choices.py:191 @@ -15225,23 +15320,27 @@ msgstr "DSA 签名" #: netbox/vpn/choices.py:196 netbox/vpn/choices.py:197 #: netbox/vpn/choices.py:198 netbox/vpn/choices.py:199 #: netbox/vpn/choices.py:200 netbox/vpn/choices.py:201 +#: netbox/vpn/choices.py:202 netbox/vpn/choices.py:203 +#: netbox/vpn/choices.py:204 netbox/vpn/choices.py:205 +#: netbox/vpn/choices.py:206 netbox/vpn/choices.py:207 +#: netbox/vpn/choices.py:208 netbox/vpn/choices.py:209 #, python-brace-format msgid "Group {n}" msgstr "Group {n}" -#: netbox/vpn/choices.py:243 +#: netbox/vpn/choices.py:251 msgid "Ethernet Private LAN" msgstr "Ethernet Private LAN" -#: netbox/vpn/choices.py:244 +#: netbox/vpn/choices.py:252 msgid "Ethernet Virtual Private LAN" msgstr "Ethernet Virtual Private LAN" -#: netbox/vpn/choices.py:247 +#: netbox/vpn/choices.py:255 msgid "Ethernet Private Tree" msgstr "Ethernet Private Tree" -#: netbox/vpn/choices.py:248 +#: netbox/vpn/choices.py:256 msgid "Ethernet Virtual Private Tree" msgstr "Ethernet Virtual Private Tree" diff --git a/netbox/users/api/nested_serializers.py b/netbox/users/api/nested_serializers.py deleted file mode 100644 index 201e38901..000000000 --- a/netbox/users/api/nested_serializers.py +++ /dev/null @@ -1,53 +0,0 @@ -import warnings - -from drf_spectacular.utils import extend_schema_field -from rest_framework import serializers - -from core.models import ObjectType -from netbox.api.fields import ContentTypeField -from netbox.api.serializers import WritableNestedSerializer -from serializers_.nested import NestedGroupSerializer, NestedUserSerializer -from users.models import ObjectPermission, Token - -__all__ = [ - 'NestedGroupSerializer', - 'NestedObjectPermissionSerializer', - 'NestedTokenSerializer', - 'NestedUserSerializer', -] - -# TODO: Remove in v4.2 -warnings.warn( - "Dedicated nested serializers will be removed in NetBox v4.2. Use Serializer(nested=True) instead.", - DeprecationWarning -) - - -class NestedTokenSerializer(WritableNestedSerializer): - - class Meta: - model = Token - fields = ['id', 'url', 'display_url', 'display', 'key', 'write_enabled'] - - -class NestedObjectPermissionSerializer(WritableNestedSerializer): - object_types = ContentTypeField( - queryset=ObjectType.objects.all(), - many=True - ) - groups = serializers.SerializerMethodField(read_only=True) - users = serializers.SerializerMethodField(read_only=True) - - class Meta: - model = ObjectPermission - fields = [ - 'id', 'url', 'display_url', 'display', 'name', 'enabled', 'object_types', 'groups', 'users', 'actions' - ] - - @extend_schema_field(serializers.ListField) - def get_groups(self, obj): - return [g.name for g in obj.groups.all()] - - @extend_schema_field(serializers.ListField) - def get_users(self, obj): - return [u.username for u in obj.users.all()] diff --git a/netbox/users/migrations/0001_squashed_0011.py b/netbox/users/migrations/0001_squashed_0011.py index cad84201c..263604d34 100644 --- a/netbox/users/migrations/0001_squashed_0011.py +++ b/netbox/users/migrations/0001_squashed_0011.py @@ -8,7 +8,6 @@ import users.models class Migration(migrations.Migration): - initial = True dependencies = [ @@ -39,15 +38,33 @@ class Migration(migrations.Migration): ('password', models.CharField(max_length=128)), ('last_login', models.DateTimeField(blank=True, null=True)), ('is_superuser', models.BooleanField(default=False)), - ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()])), + ( + 'username', + models.CharField( + error_messages={'unique': 'A user with that username already exists.'}, + max_length=150, + unique=True, + validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], + ), + ), ('first_name', models.CharField(blank=True, max_length=150)), ('last_name', models.CharField(blank=True, max_length=150)), ('email', models.EmailField(blank=True, max_length=254)), ('is_staff', models.BooleanField(default=False)), ('is_active', models.BooleanField(default=True)), ('date_joined', models.DateTimeField(default=django.utils.timezone.now)), - ('groups', models.ManyToManyField(blank=True, related_name='user_set', related_query_name='user', to='auth.group')), - ('user_permissions', models.ManyToManyField(blank=True, related_name='user_set', related_query_name='user', to='auth.permission')), + ( + 'groups', + models.ManyToManyField( + blank=True, related_name='user_set', related_query_name='user', to='auth.group' + ), + ), + ( + 'user_permissions', + models.ManyToManyField( + blank=True, related_name='user_set', related_query_name='user', to='auth.permission' + ), + ), ], options={ 'verbose_name': 'user', @@ -64,7 +81,12 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), ('data', models.JSONField(default=dict)), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='config', to=settings.AUTH_USER_MODEL)), + ( + 'user', + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, related_name='config', to=settings.AUTH_USER_MODEL + ), + ), ], options={ 'verbose_name': 'User Preferences', @@ -78,10 +100,20 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(primary_key=True, serialize=False)), ('created', models.DateTimeField(auto_now_add=True)), ('expires', models.DateTimeField(blank=True, null=True)), - ('key', models.CharField(max_length=40, unique=True, validators=[django.core.validators.MinLengthValidator(40)])), + ( + 'key', + models.CharField( + max_length=40, unique=True, validators=[django.core.validators.MinLengthValidator(40)] + ), + ), ('write_enabled', models.BooleanField(default=True)), ('description', models.CharField(blank=True, max_length=200)), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tokens', to=settings.AUTH_USER_MODEL)), + ( + 'user', + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name='tokens', to=settings.AUTH_USER_MODEL + ), + ), ], ), migrations.CreateModel( @@ -91,11 +123,37 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=100)), ('description', models.CharField(blank=True, max_length=200)), ('enabled', models.BooleanField(default=True)), - ('actions', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=30), size=None)), + ( + 'actions', + django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=30), size=None), + ), ('constraints', models.JSONField(blank=True, null=True)), ('groups', models.ManyToManyField(blank=True, related_name='object_permissions', to='auth.Group')), - ('object_types', models.ManyToManyField(limit_choices_to=models.Q(models.Q(models.Q(('app_label__in', ['account', 'admin', 'auth', 'contenttypes', 'sessions', 'taggit', 'users']), _negated=True), models.Q(('app_label', 'auth'), ('model__in', ['group', 'user'])), models.Q(('app_label', 'users'), ('model__in', ['objectpermission', 'token'])), _connector='OR')), related_name='object_permissions', to='contenttypes.ContentType')), - ('users', models.ManyToManyField(blank=True, related_name='object_permissions', to=settings.AUTH_USER_MODEL)), + ( + 'object_types', + models.ManyToManyField( + limit_choices_to=models.Q( + models.Q( + models.Q( + ( + 'app_label__in', + ['account', 'admin', 'auth', 'contenttypes', 'sessions', 'taggit', 'users'], + ), + _negated=True, + ), + models.Q(('app_label', 'auth'), ('model__in', ['group', 'user'])), + models.Q(('app_label', 'users'), ('model__in', ['objectpermission', 'token'])), + _connector='OR', + ) + ), + related_name='object_permissions', + to='contenttypes.ContentType', + ), + ), + ( + 'users', + models.ManyToManyField(blank=True, related_name='object_permissions', to=settings.AUTH_USER_MODEL), + ), ], options={ 'verbose_name': 'permission', diff --git a/netbox/users/migrations/0002_squashed_0004.py b/netbox/users/migrations/0002_squashed_0004.py index 078721c48..275d7a7a9 100644 --- a/netbox/users/migrations/0002_squashed_0004.py +++ b/netbox/users/migrations/0002_squashed_0004.py @@ -5,11 +5,10 @@ import ipam.fields class Migration(migrations.Migration): - replaces = [ ('users', '0002_standardize_id_fields'), ('users', '0003_token_allowed_ips_last_used'), - ('users', '0004_netboxgroup_netboxuser') + ('users', '0004_netboxgroup_netboxuser'), ] dependencies = [ @@ -36,7 +35,9 @@ class Migration(migrations.Migration): migrations.AddField( model_name='token', name='allowed_ips', - field=django.contrib.postgres.fields.ArrayField(base_field=ipam.fields.IPNetworkField(), blank=True, null=True, size=None), + field=django.contrib.postgres.fields.ArrayField( + base_field=ipam.fields.IPNetworkField(), blank=True, null=True, size=None + ), ), migrations.AddField( model_name='token', @@ -45,8 +46,7 @@ class Migration(migrations.Migration): ), migrations.CreateModel( name='NetBoxGroup', - fields=[ - ], + fields=[], options={ 'verbose_name': 'Group', 'proxy': True, diff --git a/netbox/users/migrations/0005_alter_user_table.py b/netbox/users/migrations/0005_alter_user_table.py index 1163da0ae..2e9f699b3 100644 --- a/netbox/users/migrations/0005_alter_user_table.py +++ b/netbox/users/migrations/0005_alter_user_table.py @@ -19,7 +19,6 @@ def update_content_types(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('users', '0002_squashed_0004'), ('extras', '0113_customfield_rename_object_type'), @@ -33,24 +32,17 @@ class Migration(migrations.Migration): name='user', table=None, ), - # Convert the `id` column to a 64-bit integer (BigAutoField is implied by DEFAULT_AUTO_FIELD) - migrations.RunSQL("ALTER TABLE users_user ALTER COLUMN id TYPE bigint"), - + migrations.RunSQL('ALTER TABLE users_user ALTER COLUMN id TYPE bigint'), # Rename auth_user_* sequences - migrations.RunSQL("ALTER TABLE auth_user_groups_id_seq RENAME TO users_user_groups_id_seq"), - migrations.RunSQL("ALTER TABLE auth_user_id_seq RENAME TO users_user_id_seq"), - migrations.RunSQL("ALTER TABLE auth_user_user_permissions_id_seq RENAME TO users_user_user_permissions_id_seq"), - + migrations.RunSQL('ALTER TABLE auth_user_groups_id_seq RENAME TO users_user_groups_id_seq'), + migrations.RunSQL('ALTER TABLE auth_user_id_seq RENAME TO users_user_id_seq'), + migrations.RunSQL('ALTER TABLE auth_user_user_permissions_id_seq RENAME TO users_user_user_permissions_id_seq'), # Rename auth_user_* indexes - migrations.RunSQL("ALTER INDEX auth_user_pkey RENAME TO users_user_pkey"), + migrations.RunSQL('ALTER INDEX auth_user_pkey RENAME TO users_user_pkey'), # Hash is deterministic; generated via schema_editor._create_index_name() - migrations.RunSQL("ALTER INDEX auth_user_username_6821ab7c_like RENAME TO users_user_username_06e46fe6_like"), - migrations.RunSQL("ALTER INDEX auth_user_username_key RENAME TO users_user_username_key"), - + migrations.RunSQL('ALTER INDEX auth_user_username_6821ab7c_like RENAME TO users_user_username_06e46fe6_like'), + migrations.RunSQL('ALTER INDEX auth_user_username_key RENAME TO users_user_username_key'), # Update ContentTypes - migrations.RunPython( - code=update_content_types, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=update_content_types, reverse_code=migrations.RunPython.noop), ] diff --git a/netbox/users/migrations/0006_custom_group_model.py b/netbox/users/migrations/0006_custom_group_model.py index f958d242a..f70c1d58d 100644 --- a/netbox/users/migrations/0006_custom_group_model.py +++ b/netbox/users/migrations/0006_custom_group_model.py @@ -16,7 +16,6 @@ def update_custom_fields(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('users', '0005_alter_user_table'), ] @@ -29,7 +28,12 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), ('name', models.CharField(max_length=150, unique=True)), ('description', models.CharField(blank=True, max_length=200)), - ('permissions', models.ManyToManyField(blank=True, related_name='groups', related_query_name='group', to='auth.permission')), + ( + 'permissions', + models.ManyToManyField( + blank=True, related_name='groups', related_query_name='group', to='auth.permission' + ), + ), ], options={ 'ordering': ('name',), @@ -40,17 +44,10 @@ class Migration(migrations.Migration): ('objects', users.models.GroupManager()), ], ), - # Copy existing groups from the old table into the new one - migrations.RunSQL( - "INSERT INTO users_group (SELECT id, name, '' AS description FROM auth_group)" - ), - + migrations.RunSQL("INSERT INTO users_group (SELECT id, name, '' AS description FROM auth_group)"), # Update the sequence for group ID values - migrations.RunSQL( - "SELECT setval('users_group_id_seq', (SELECT MAX(id) FROM users_group))" - ), - + migrations.RunSQL("SELECT setval('users_group_id_seq', (SELECT MAX(id) FROM users_group))"), # Update the "groups" M2M fields on User & ObjectPermission migrations.AlterField( model_name='user', @@ -62,23 +59,12 @@ class Migration(migrations.Migration): name='groups', field=models.ManyToManyField(blank=True, related_name='object_permissions', to='users.group'), ), - # Delete any lingering group assignments for legacy permissions (from before NetBox v2.9) - migrations.RunSQL( - "DELETE from auth_group_permissions" - ), - + migrations.RunSQL('DELETE from auth_group_permissions'), # Delete groups from the old table - migrations.RunSQL( - "DELETE from auth_group" - ), - + migrations.RunSQL('DELETE from auth_group'), # Update custom fields - migrations.RunPython( - code=update_custom_fields, - reverse_code=migrations.RunPython.noop - ), - + migrations.RunPython(code=update_custom_fields, reverse_code=migrations.RunPython.noop), # Delete the proxy model migrations.DeleteModel( name='NetBoxGroup', diff --git a/netbox/users/migrations/0007_objectpermission_update_object_types.py b/netbox/users/migrations/0007_objectpermission_update_object_types.py index d3018a602..598b00b92 100644 --- a/netbox/users/migrations/0007_objectpermission_update_object_types.py +++ b/netbox/users/migrations/0007_objectpermission_update_object_types.py @@ -4,7 +4,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('core', '0010_gfk_indexes'), ('users', '0006_custom_group_model'), @@ -14,6 +13,23 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='objectpermission', name='object_types', - field=models.ManyToManyField(limit_choices_to=models.Q(models.Q(models.Q(('app_label__in', ['account', 'admin', 'auth', 'contenttypes', 'sessions', 'taggit', 'users']), _negated=True), models.Q(('app_label', 'auth'), ('model__in', ['group', 'user'])), models.Q(('app_label', 'users'), ('model__in', ['objectpermission', 'token'])), _connector='OR')), related_name='object_permissions', to='core.objecttype'), + field=models.ManyToManyField( + limit_choices_to=models.Q( + models.Q( + models.Q( + ( + 'app_label__in', + ['account', 'admin', 'auth', 'contenttypes', 'sessions', 'taggit', 'users'], + ), + _negated=True, + ), + models.Q(('app_label', 'auth'), ('model__in', ['group', 'user'])), + models.Q(('app_label', 'users'), ('model__in', ['objectpermission', 'token'])), + _connector='OR', + ) + ), + related_name='object_permissions', + to='core.objecttype', + ), ), ] diff --git a/netbox/users/migrations/0008_flip_objectpermission_assignments.py b/netbox/users/migrations/0008_flip_objectpermission_assignments.py index c61c8b124..11dea5819 100644 --- a/netbox/users/migrations/0008_flip_objectpermission_assignments.py +++ b/netbox/users/migrations/0008_flip_objectpermission_assignments.py @@ -2,7 +2,6 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ ('users', '0007_objectpermission_update_object_types'), ] @@ -24,52 +23,47 @@ class Migration(migrations.Migration): database_operations=[ # Rename table migrations.RunSQL( - "ALTER TABLE users_objectpermission_groups" - " RENAME TO users_group_object_permissions" + 'ALTER TABLE users_objectpermission_groups' ' RENAME TO users_group_object_permissions' ), migrations.RunSQL( - "ALTER TABLE users_objectpermission_groups_id_seq" - " RENAME TO users_group_object_permissions_id_seq" + 'ALTER TABLE users_objectpermission_groups_id_seq' + ' RENAME TO users_group_object_permissions_id_seq' ), - # Rename constraints migrations.RunSQL( - "ALTER TABLE users_group_object_permissions RENAME CONSTRAINT " - "users_objectpermissi_group_id_fb7ba6e0_fk_users_gro TO " - "users_group_object_p_group_id_90dd183a_fk_users_gro" + 'ALTER TABLE users_group_object_permissions RENAME CONSTRAINT ' + 'users_objectpermissi_group_id_fb7ba6e0_fk_users_gro TO ' + 'users_group_object_p_group_id_90dd183a_fk_users_gro' ), # Fix for #15698: Drop & recreate constraint which may not exist migrations.RunSQL( - "ALTER TABLE users_group_object_permissions DROP CONSTRAINT IF EXISTS " - "users_objectpermissi_objectpermission_id_2f7cc117_fk_users_obj" + 'ALTER TABLE users_group_object_permissions DROP CONSTRAINT IF EXISTS ' + 'users_objectpermissi_objectpermission_id_2f7cc117_fk_users_obj' ), migrations.RunSQL( - "ALTER TABLE users_group_object_permissions ADD CONSTRAINT " - "users_group_object_p_objectpermission_id_dd489dc4_fk_users_obj " - "FOREIGN KEY (objectpermission_id) REFERENCES users_objectpermission(id) " - "DEFERRABLE INITIALLY DEFERRED" + 'ALTER TABLE users_group_object_permissions ADD CONSTRAINT ' + 'users_group_object_p_objectpermission_id_dd489dc4_fk_users_obj ' + 'FOREIGN KEY (objectpermission_id) REFERENCES users_objectpermission(id) ' + 'DEFERRABLE INITIALLY DEFERRED' ), - # Rename indexes migrations.RunSQL( - "ALTER INDEX users_objectpermission_groups_pkey " - " RENAME TO users_group_object_permissions_pkey" + 'ALTER INDEX users_objectpermission_groups_pkey ' ' RENAME TO users_group_object_permissions_pkey' ), migrations.RunSQL( - "ALTER INDEX users_objectpermission_g_objectpermission_id_grou_3b62a39c_uniq " - " RENAME TO users_group_object_permi_group_id_objectpermissio_db1f8cbe_uniq" + 'ALTER INDEX users_objectpermission_g_objectpermission_id_grou_3b62a39c_uniq ' + ' RENAME TO users_group_object_permi_group_id_objectpermissio_db1f8cbe_uniq' ), migrations.RunSQL( - "ALTER INDEX users_objectpermission_groups_group_id_fb7ba6e0" - " RENAME TO users_group_object_permissions_group_id_90dd183a" + 'ALTER INDEX users_objectpermission_groups_group_id_fb7ba6e0' + ' RENAME TO users_group_object_permissions_group_id_90dd183a' ), migrations.RunSQL( - "ALTER INDEX users_objectpermission_groups_objectpermission_id_2f7cc117" - " RENAME TO users_group_object_permissions_objectpermission_id_dd489dc4" + 'ALTER INDEX users_objectpermission_groups_objectpermission_id_2f7cc117' + ' RENAME TO users_group_object_permissions_objectpermission_id_dd489dc4' ), - ] + ], ), - # Flip M2M assignments for ObjectPermission to Users migrations.SeparateDatabaseAndState( state_operations=[ @@ -86,49 +80,44 @@ class Migration(migrations.Migration): database_operations=[ # Rename table migrations.RunSQL( - "ALTER TABLE users_objectpermission_users" - " RENAME TO users_user_object_permissions" + 'ALTER TABLE users_objectpermission_users' ' RENAME TO users_user_object_permissions' ), migrations.RunSQL( - "ALTER TABLE users_objectpermission_users_id_seq" - " RENAME TO users_user_object_permissions_id_seq" + 'ALTER TABLE users_objectpermission_users_id_seq' ' RENAME TO users_user_object_permissions_id_seq' ), - # Rename constraints migrations.RunSQL( - "ALTER TABLE users_user_object_permissions RENAME CONSTRAINT " - "users_objectpermission_users_user_id_16c0905d_fk_auth_user_id TO " - "users_user_object_permissions_user_id_9d647aac_fk_users_user_id" + 'ALTER TABLE users_user_object_permissions RENAME CONSTRAINT ' + 'users_objectpermission_users_user_id_16c0905d_fk_auth_user_id TO ' + 'users_user_object_permissions_user_id_9d647aac_fk_users_user_id' ), # Fix for #15698: Drop & recreate constraint which may not exist migrations.RunSQL( - "ALTER TABLE users_user_object_permissions DROP CONSTRAINT IF EXISTS " - "users_objectpermissi_objectpermission_id_78a9c2e6_fk_users_obj" + 'ALTER TABLE users_user_object_permissions DROP CONSTRAINT IF EXISTS ' + 'users_objectpermissi_objectpermission_id_78a9c2e6_fk_users_obj' ), migrations.RunSQL( - "ALTER TABLE users_user_object_permissions ADD CONSTRAINT " - "users_user_object_pe_objectpermission_id_29b431b4_fk_users_obj " - "FOREIGN KEY (objectpermission_id) REFERENCES users_objectpermission(id) " - "DEFERRABLE INITIALLY DEFERRED" + 'ALTER TABLE users_user_object_permissions ADD CONSTRAINT ' + 'users_user_object_pe_objectpermission_id_29b431b4_fk_users_obj ' + 'FOREIGN KEY (objectpermission_id) REFERENCES users_objectpermission(id) ' + 'DEFERRABLE INITIALLY DEFERRED' ), - # Rename indexes migrations.RunSQL( - "ALTER INDEX users_objectpermission_users_pkey " - " RENAME TO users_user_object_permissions_pkey" + 'ALTER INDEX users_objectpermission_users_pkey ' ' RENAME TO users_user_object_permissions_pkey' ), migrations.RunSQL( - "ALTER INDEX users_objectpermission_u_objectpermission_id_user_3a7db108_uniq " - " RENAME TO users_user_object_permis_user_id_objectpermission_0a98550e_uniq" + 'ALTER INDEX users_objectpermission_u_objectpermission_id_user_3a7db108_uniq ' + ' RENAME TO users_user_object_permis_user_id_objectpermission_0a98550e_uniq' ), migrations.RunSQL( - "ALTER INDEX users_objectpermission_users_user_id_16c0905d" - " RENAME TO users_user_object_permissions_user_id_9d647aac" + 'ALTER INDEX users_objectpermission_users_user_id_16c0905d' + ' RENAME TO users_user_object_permissions_user_id_9d647aac' ), migrations.RunSQL( - "ALTER INDEX users_objectpermission_users_objectpermission_id_78a9c2e6" - " RENAME TO users_user_object_permissions_objectpermission_id_29b431b4" + 'ALTER INDEX users_objectpermission_users_objectpermission_id_78a9c2e6' + ' RENAME TO users_user_object_permissions_objectpermission_id_29b431b4' ), - ] + ], ), ] diff --git a/netbox/users/migrations/0009_update_group_perms.py b/netbox/users/migrations/0009_update_group_perms.py index f3b197492..7698fd1e7 100644 --- a/netbox/users/migrations/0009_update_group_perms.py +++ b/netbox/users/migrations/0009_update_group_perms.py @@ -18,17 +18,13 @@ def update_content_types(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('users', '0008_flip_objectpermission_assignments'), ] operations = [ # Update ContentTypes - migrations.RunPython( - code=update_content_types, - reverse_code=migrations.RunPython.noop - ), + migrations.RunPython(code=update_content_types, reverse_code=migrations.RunPython.noop), migrations.AlterField( model_name='objectpermission', name='object_types', diff --git a/netbox/users/tests/test_filtersets.py b/netbox/users/tests/test_filtersets.py index fdf25d970..8b683b346 100644 --- a/netbox/users/tests/test_filtersets.py +++ b/netbox/users/tests/test_filtersets.py @@ -286,9 +286,15 @@ class TokenTestCase(TestCase, BaseFilterSetTests): future_date = make_aware(datetime.datetime(3000, 1, 1)) past_date = make_aware(datetime.datetime(2000, 1, 1)) tokens = ( - Token(user=users[0], key=Token.generate_key(), expires=future_date, write_enabled=True, description='foobar1'), - Token(user=users[1], key=Token.generate_key(), expires=future_date, write_enabled=True, description='foobar2'), - Token(user=users[2], key=Token.generate_key(), expires=past_date, write_enabled=False), + Token( + user=users[0], key=Token.generate_key(), expires=future_date, write_enabled=True, description='foobar1' + ), + Token( + user=users[1], key=Token.generate_key(), expires=future_date, write_enabled=True, description='foobar2' + ), + Token( + user=users[2], key=Token.generate_key(), expires=past_date, write_enabled=False + ), ) Token.objects.bulk_create(tokens) diff --git a/netbox/users/tests/test_views.py b/netbox/users/tests/test_views.py index 8386364dd..8226a8be9 100644 --- a/netbox/users/tests/test_views.py +++ b/netbox/users/tests/test_views.py @@ -23,11 +23,16 @@ class UserTestCase( @classmethod def setUpTestData(cls): - users = ( - User(username='username1', first_name='first1', last_name='last1', email='user1@foo.com', password='pass1xxx'), - User(username='username2', first_name='first2', last_name='last2', email='user2@foo.com', password='pass2xxx'), - User(username='username3', first_name='first3', last_name='last3', email='user3@foo.com', password='pass3xxx'), + User( + username='username1', first_name='first1', last_name='last1', email='user1@foo.com', password='pass1xxx' + ), + User( + username='username2', first_name='first2', last_name='last2', email='user2@foo.com', password='pass2xxx' + ), + User( + username='username3', first_name='first3', last_name='last3', email='user3@foo.com', password='pass3xxx' + ), ) User.objects.bulk_create(users) diff --git a/netbox/users/urls.py b/netbox/users/urls.py index 0540eae1f..83f120702 100644 --- a/netbox/users/urls.py +++ b/netbox/users/urls.py @@ -1,40 +1,21 @@ from django.urls import include, path from utilities.urls import get_model_urls -from . import views +from . import views # noqa F401 app_name = 'users' urlpatterns = [ - # Tokens - path('tokens/', views.TokenListView.as_view(), name='token_list'), - path('tokens/add/', views.TokenEditView.as_view(), name='token_add'), - path('tokens/import/', views.TokenBulkImportView.as_view(), name='token_import'), - path('tokens/edit/', views.TokenBulkEditView.as_view(), name='token_bulk_edit'), - path('tokens/delete/', views.TokenBulkDeleteView.as_view(), name='token_bulk_delete'), + path('tokens/', include(get_model_urls('users', 'token', detail=False))), path('tokens//', include(get_model_urls('users', 'token'))), - # Users - path('users/', views.UserListView.as_view(), name='user_list'), - path('users/add/', views.UserEditView.as_view(), name='user_add'), - path('users/edit/', views.UserBulkEditView.as_view(), name='user_bulk_edit'), - path('users/import/', views.UserBulkImportView.as_view(), name='user_import'), - path('users/delete/', views.UserBulkDeleteView.as_view(), name='user_bulk_delete'), + path('users/', include(get_model_urls('users', 'user', detail=False))), path('users//', include(get_model_urls('users', 'user'))), - # Groups - path('groups/', views.GroupListView.as_view(), name='group_list'), - path('groups/add/', views.GroupEditView.as_view(), name='group_add'), - path('groups/edit/', views.GroupBulkEditView.as_view(), name='group_bulk_edit'), - path('groups/import/', views.GroupBulkImportView.as_view(), name='group_import'), - path('groups/delete/', views.GroupBulkDeleteView.as_view(), name='group_bulk_delete'), + path('groups/', include(get_model_urls('users', 'group', detail=False))), path('groups//', include(get_model_urls('users', 'group'))), - # Permissions - path('permissions/', views.ObjectPermissionListView.as_view(), name='objectpermission_list'), - path('permissions/add/', views.ObjectPermissionEditView.as_view(), name='objectpermission_add'), - path('permissions/edit/', views.ObjectPermissionBulkEditView.as_view(), name='objectpermission_bulk_edit'), - path('permissions/delete/', views.ObjectPermissionBulkDeleteView.as_view(), name='objectpermission_bulk_delete'), + path('permissions/', include(get_model_urls('users', 'objectpermission', detail=False))), path('permissions//', include(get_model_urls('users', 'objectpermission'))), ] diff --git a/netbox/users/views.py b/netbox/users/views.py index b2f9a8d04..ca928e582 100644 --- a/netbox/users/views.py +++ b/netbox/users/views.py @@ -12,6 +12,7 @@ from .models import Group, User, ObjectPermission, Token # Tokens # +@register_model_view(Token, 'list', path='', detail=False) class TokenListView(generic.ObjectListView): queryset = Token.objects.all() filterset = filtersets.TokenFilterSet @@ -24,6 +25,7 @@ class TokenView(generic.ObjectView): queryset = Token.objects.all() +@register_model_view(Token, 'add', detail=False) @register_model_view(Token, 'edit') class TokenEditView(generic.ObjectEditView): queryset = Token.objects.all() @@ -36,17 +38,20 @@ class TokenDeleteView(generic.ObjectDeleteView): queryset = Token.objects.all() +@register_model_view(Token, 'bulk_import', detail=False) class TokenBulkImportView(generic.BulkImportView): queryset = Token.objects.all() model_form = forms.TokenImportForm +@register_model_view(Token, 'bulk_edit', path='edit', detail=False) class TokenBulkEditView(generic.BulkEditView): queryset = Token.objects.all() table = tables.TokenTable form = forms.TokenBulkEditForm +@register_model_view(Token, 'bulk_delete', path='delete', detail=False) class TokenBulkDeleteView(generic.BulkDeleteView): queryset = Token.objects.all() table = tables.TokenTable @@ -56,6 +61,7 @@ class TokenBulkDeleteView(generic.BulkDeleteView): # Users # +@register_model_view(User, 'list', path='', detail=False) class UserListView(generic.ObjectListView): queryset = User.objects.all() filterset = filtersets.UserFilterSet @@ -77,6 +83,7 @@ class UserView(generic.ObjectView): } +@register_model_view(User, 'add', detail=False) @register_model_view(User, 'edit') class UserEditView(generic.ObjectEditView): queryset = User.objects.all() @@ -88,6 +95,13 @@ class UserDeleteView(generic.ObjectDeleteView): queryset = User.objects.all() +@register_model_view(User, 'bulk_import', detail=False) +class UserBulkImportView(generic.BulkImportView): + queryset = User.objects.all() + model_form = forms.UserImportForm + + +@register_model_view(User, 'bulk_edit', path='edit', detail=False) class UserBulkEditView(generic.BulkEditView): queryset = User.objects.all() filterset = filtersets.UserFilterSet @@ -95,11 +109,7 @@ class UserBulkEditView(generic.BulkEditView): form = forms.UserBulkEditForm -class UserBulkImportView(generic.BulkImportView): - queryset = User.objects.all() - model_form = forms.UserImportForm - - +@register_model_view(User, 'bulk_delete', path='delete', detail=False) class UserBulkDeleteView(generic.BulkDeleteView): queryset = User.objects.all() filterset = filtersets.UserFilterSet @@ -110,6 +120,7 @@ class UserBulkDeleteView(generic.BulkDeleteView): # Groups # +@register_model_view(Group, 'list', path='', detail=False) class GroupListView(generic.ObjectListView): queryset = Group.objects.annotate(users_count=Count('user')).order_by('name') filterset = filtersets.GroupFilterSet @@ -123,6 +134,7 @@ class GroupView(generic.ObjectView): template_name = 'users/group.html' +@register_model_view(Group, 'add', detail=False) @register_model_view(Group, 'edit') class GroupEditView(generic.ObjectEditView): queryset = Group.objects.all() @@ -134,11 +146,13 @@ class GroupDeleteView(generic.ObjectDeleteView): queryset = Group.objects.all() +@register_model_view(Group, 'bulk_import', detail=False) class GroupBulkImportView(generic.BulkImportView): queryset = Group.objects.all() model_form = forms.GroupImportForm +@register_model_view(Group, 'bulk_edit', path='edit', detail=False) class GroupBulkEditView(generic.BulkEditView): queryset = Group.objects.all() filterset = filtersets.GroupFilterSet @@ -146,6 +160,7 @@ class GroupBulkEditView(generic.BulkEditView): form = forms.GroupBulkEditForm +@register_model_view(Group, 'bulk_delete', path='delete', detail=False) class GroupBulkDeleteView(generic.BulkDeleteView): queryset = Group.objects.annotate(users_count=Count('user')).order_by('name') filterset = filtersets.GroupFilterSet @@ -156,6 +171,7 @@ class GroupBulkDeleteView(generic.BulkDeleteView): # ObjectPermissions # +@register_model_view(ObjectPermission, 'list', path='', detail=False) class ObjectPermissionListView(generic.ObjectListView): queryset = ObjectPermission.objects.all() filterset = filtersets.ObjectPermissionFilterSet @@ -169,6 +185,7 @@ class ObjectPermissionView(generic.ObjectView): template_name = 'users/objectpermission.html' +@register_model_view(ObjectPermission, 'add', detail=False) @register_model_view(ObjectPermission, 'edit') class ObjectPermissionEditView(generic.ObjectEditView): queryset = ObjectPermission.objects.all() @@ -180,6 +197,7 @@ class ObjectPermissionDeleteView(generic.ObjectDeleteView): queryset = ObjectPermission.objects.all() +@register_model_view(ObjectPermission, 'bulk_edit', path='edit', detail=False) class ObjectPermissionBulkEditView(generic.BulkEditView): queryset = ObjectPermission.objects.all() filterset = filtersets.ObjectPermissionFilterSet @@ -187,6 +205,7 @@ class ObjectPermissionBulkEditView(generic.BulkEditView): form = forms.ObjectPermissionBulkEditForm +@register_model_view(ObjectPermission, 'bulk_delete', path='delete', detail=False) class ObjectPermissionBulkDeleteView(generic.BulkDeleteView): queryset = ObjectPermission.objects.all() filterset = filtersets.ObjectPermissionFilterSet diff --git a/netbox/utilities/api.py b/netbox/utilities/api.py index 11b914811..6793c0526 100644 --- a/netbox/utilities/api.py +++ b/netbox/utilities/api.py @@ -129,7 +129,7 @@ def get_annotations_for_serializer(serializer_class, fields_to_include=None): for field_name, field in serializer_class._declared_fields.items(): if field_name in fields_to_include and type(field) is RelatedObjectCountField: - related_field = model._meta.get_field(field.relation).field + related_field = getattr(model, field.relation).field annotations[field_name] = count_related(related_field.model, related_field.name) return annotations diff --git a/netbox/utilities/conversion.py b/netbox/utilities/conversion.py index ee0175e7c..6ce32212a 100644 --- a/netbox/utilities/conversion.py +++ b/netbox/utilities/conversion.py @@ -11,9 +11,9 @@ __all__ = ( ) -def to_grams(weight, unit): +def to_grams(weight, unit) -> int: """ - Convert the given weight to kilograms. + Convert the given weight to integer grams. """ try: if weight < 0: @@ -22,13 +22,13 @@ def to_grams(weight, unit): raise TypeError(_("Invalid value '{weight}' for weight (must be a number)").format(weight=weight)) if unit == WeightUnitChoices.UNIT_KILOGRAM: - return weight * 1000 + return int(weight * 1000) if unit == WeightUnitChoices.UNIT_GRAM: - return weight + return int(weight) if unit == WeightUnitChoices.UNIT_POUND: - return weight * Decimal(453.592) + return int(weight * Decimal(453.592)) if unit == WeightUnitChoices.UNIT_OUNCE: - return weight * Decimal(28.3495) + return int(weight * Decimal(28.3495)) raise ValueError( _("Unknown unit {unit}. Must be one of the following: {valid_units}").format( unit=unit, diff --git a/netbox/utilities/error_handlers.py b/netbox/utilities/error_handlers.py index 5d2a46424..397098ded 100644 --- a/netbox/utilities/error_handlers.py +++ b/netbox/utilities/error_handlers.py @@ -49,7 +49,7 @@ def handle_rest_api_exception(request, *args, **kwargs): """ Handle exceptions and return a useful error message for REST API requests. """ - type_, error, traceback = sys.exc_info() + type_, error = sys.exc_info()[:2] data = { 'error': str(error), 'exception': type_.__name__, diff --git a/netbox/utilities/fields.py b/netbox/utilities/fields.py index ee71223cb..1d16a1d3f 100644 --- a/netbox/utilities/fields.py +++ b/netbox/utilities/fields.py @@ -5,7 +5,6 @@ from django.db import models from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ -from utilities.ordering import naturalize from .forms.widgets import ColorSelect from .validators import ColorValidator @@ -40,7 +39,7 @@ class NaturalOrderingField(models.CharField): """ description = "Stores a representation of its target field suitable for natural ordering" - def __init__(self, target_field, naturalize_function=naturalize, *args, **kwargs): + def __init__(self, target_field, naturalize_function, *args, **kwargs): self.target_field = target_field self.naturalize_function = naturalize_function super().__init__(*args, **kwargs) diff --git a/netbox/utilities/forms/fields/dynamic.py b/netbox/utilities/forms/fields/dynamic.py index 6666c0e4d..793494b4b 100644 --- a/netbox/utilities/forms/fields/dynamic.py +++ b/netbox/utilities/forms/fields/dynamic.py @@ -2,7 +2,7 @@ import django_filters from django import forms from django.conf import settings from django.forms import BoundField -from django.urls import reverse +from django.urls import reverse, reverse_lazy from utilities.forms import widgets from utilities.views import get_viewname @@ -66,6 +66,10 @@ class DynamicModelChoiceMixin: choice (DEPRECATED: pass `context={'disabled': '$fieldname'}` instead) context: A mapping of