Translation support and minor login view changes #35

Open
rskthomas wants to merge 20 commits from feature/translation into main
20 changed files with 1708 additions and 175 deletions

View file

@ -2,35 +2,37 @@
{% load i18n %}
{% block content %}
<div class="row">
<div class="row mb-4">
<div class="col">
<h3>{{ subtitle }}</h3>
</div>
<div class="col-2">
<a href="{% url 'admin:new_user' %}" class="btn btn-green-admin">{% translate "Add new user" %}</a>
<div class="col-2 text-end">
<a href="{% url 'admin:new_user' %}" class="btn btn-green-admin "><i class="bi bi-person-plus"></i> {% trans "New user" %}</a>
</div>
</div>
<div class="row">
<div class="col">
<table class="table">
<thead>
<tr>
<th scope="col">Email</th>
<th>is Admin</th>
<th></th>
<th></th>
</tr>
<table class="table table-hover table-bordered">
<thead class="table-light">
<tr>
<th scope="col">{% trans "Email" %}</th>
<th scope="col">{% trans "Admin" %}</th>
<th scope="col" class="text-center">{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
<tr>
{% for u in users %}
<tr>
<td>{{ u.email }}</td>
<td>{{ u.is_admin }}</td>
<td><a href="{% url 'admin:edit_user' u.pk %}"><i class="bi bi-eye"></i></td>
<td><a href="{% url 'admin:delete_user' u.pk %}" class="text-danger" title="Remove"><i class="bi bi-trash"></i></td>
</tr>
{% endfor %}
<td>{% if u.is_admin %}{% trans "Yes" %}{% else %}{% trans "No" %}{% endif %}</td>
<td class="text-center">
<a href="{% url 'admin:edit_user' u.pk %}"><i class="bi bi-pencil me-4"></i></a>
<a href="{% url 'admin:delete_user' u.pk %}" class="text-danger" title="Remove"><i class="bi bi-trash"></i> </a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

View file

@ -1,4 +1,4 @@
{% load i18n static %}
{% load i18n static language_code %}
<!doctype html>
<html lang="en">
@ -7,7 +7,7 @@
{% block meta %}
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="robots" content="NONE,NOARCHIVE" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewp ort" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="Pangea">
{% endblock %}
@ -107,7 +107,7 @@
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if path == 'unassigned_devices' %}expanded{% else %}collapse{% endif %}" id="ul_devices" data-bs-parent="#sidebarMenu">
<li class="nav-item">
<a class="nav-link{% if path == 'unassigned_devices' %} active2{% endif %}" href="{% url 'dashboard:unassigned_devices' %}">
{% trans 'Unassigned devices' %}
{% trans 'Unassigned' %}
</a>
</li>
</ul>
@ -135,7 +135,7 @@
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if path in 'upload list' %}expanded{% else %}collapse{% endif %}" id="ul_evidences" data-bs-parent="#sidebarMenu">
<li class="nav-item">
<a class="nav-link{% if path == 'upload' %} active2{% endif %}" href="{% url 'evidence:upload' %}">
{% trans 'Upload one' %}
{% trans 'Upload' %}
</a>
</li>
<li class="nav-item">
@ -153,12 +153,12 @@
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if path in 'import add' %}expanded{% else %}collapse{% endif %}" id="ul_placeholders" data-bs-parent="#sidebarMenu">
<li class="nav-item">
<a class="nav-link{% if path == 'import' %} active2{% endif %}" href="{% url 'evidence:import' %}">
{% trans 'Upload Spreadsheet' %}
{% trans 'Import from spreadsheet' %}
</a>
</li>
<li class="nav-item">
<a class="nav-link{% if path == 'add' %} active2{% endif %}" href="{% url 'device:add' %}">
{% trans 'Create one' %}
{% trans 'Add device' %}
</a>
</li>
</ul>
@ -183,7 +183,7 @@
<form method="post" action="{% url 'dashboard:search' %}">
{% csrf_token %}
<div class="input-group rounded">
<input type="search" name="search" class="form-control rounded" placeholder="Search your device..." aria-label="Search" aria-describedby="search-addon" />
<input type="search" name="search" class="form-control rounded" placeholder="{% trans 'Search your device' %}" aria-label="Search" aria-describedby="search-addon" />
<span class="input-group-text border-0" id="search-addon">
<i class="fas fa-search"></i>
</span>
@ -207,10 +207,29 @@
</div>
</div>
<!-- Footer -->
<!-- Footer -->
<footer class="footer text-center mt-auto py-3">
<div class="container">
<span class="text-muted">{{ commit_id }}</span>
<div class="container d-flex justify-content-center align-items-center">
<span class="text-muted mx-auto">{{ commit_id }}</span>
<div class="dropdown ms-auto">
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<button class="btn btn-tertiary dropdown-toggle" type="button" id="languageDropdown" data-bs-toggle="dropdown" aria-expanded="false">
{% get_current_language as LANGUAGE_CODE %}
{% get_language_info_list for LANGUAGES as languages %}
{{ LANGUAGE_CODE|get_language_code:languages }}
</button>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="languageDropdown">
{% for lang in languages %}
<li>
<button class="dropdown-item" type="submit" name="language" value="{{ lang.code }}">{{ lang.name_local }}</button>
</li>
{% endfor %}
</ul>
</form>
<div>
</div>
</footer>

View file

@ -4,18 +4,18 @@
{% block content %}
<div class="row">
<div class="row mb-4">
<div class="col">
<h3>{{ subtitle }}</h3>
</div>
<div class="col text-center">
<div class="col d-flex justify-content-end align-items-center">
{% if lot %}
<a href="{% url 'lot:documents' object.id %}" type="button" class="btn btn-green-admin">
<a href="{% url 'lot:documents' object.id %}" type="button" class="btn btn-green-admin me-2">
<i class="bi bi-folder2"></i>
{% trans 'Documents' %}
</a>
{% endif %}
<a href="{# url 'dashboard:exports' object.id #}" type="button" class="btn btn-green-admin">
<a href="{# url 'dashboard:exports' object.id #}" type="button" class="btn btn-green-admin me-2">
<i class="bi bi-reply"></i>
{% trans 'Exports' %}
</a>
@ -28,59 +28,78 @@
</div>
</div>
<div class="dataTable-container">
<div class="dataTable-container mt-4">
<form method="post">
{% csrf_token %}
<table class="table">
<thead>
<tr>
<th scope="col" data-sortable="">
select
</th>
<th scope="col" data-sortable="">
shortid
</th>
<th scope="col" data-sortable="">
type
</th>
<th scope="col" data-sortable="">
manufacturer
</th>
<th scope="col" data-sortable="">
model
</th>
</tr>
</thead>
{% for dev in devices %}
<tbody>
<tr>
<td>
<input type="checkbox" name="devices" value="{{ dev.id }}" />
</td>
<td>
<a href="{% url 'device:details' dev.id %}">
{{ dev.shortid }}
</a>
</td>
<td>
{% csrf_token %}
<table class="table table-hover table-bordered">
<thead class="table-light">
<tr>
<th scope="col" class="text-center">
<input type="checkbox" id="select-all" />
</th>
<th scope="col" class="text-center">
{% trans "Short ID" %}
</th>
<th scope="col" class="text-center">
{% trans "Type" %}
</th>
<th scope="col" class="text-center">
{% trans "Manufacturer" %}
</th>
<th scope="col" class="text-center">
{% trans "Model" %}
</th>
</tr>
</thead>
<tbody>
{% for dev in devices %}
<tr>
<td class="text-center">
<input type="checkbox" name="devices" value="{{ dev.id }}" />
</td>
<td class="text-center">
<a href="{% url 'device:details' dev.id %}">
{{ dev.shortid }}
</a>
</td>
<td class="text-center">
{{ dev.type }}
</td>
<td>
</td>
<td class="text-center">
{{ dev.manufacturer }}
</td>
<td>
</td>
<td class="text-center">
{{ dev.model }}
</td>
</tr>
</tbody>
{% endfor %}
</table>
<button class="btn btn-green-admin" type="submit" value="{% url 'lot:del_devices' %}" name="url">Remove</button> <button class="btn btn-green-admin" type="submit" name="url" value="{% url 'lot:add_devices' %}">add</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="d-flex justify-content-start mt-5">
<button id="remove-button" class="btn btn-danger me-2" type="submit" value="{% url 'lot:del_devices' %}" name="url" disabled>
<i class="bi bi-trash"></i> {% trans 'Remove' %}
</button>
<button class="btn btn-success" type="submit" name="url" value="{% url 'lot:add_devices' %}">
{% trans 'Add' %}
</button>
</div>
</form>
</div>
<div class="row mt-3">
<div class="col">
{% render_pagination page total_pages limit %}
</div>
</div>
<script>
// Placeholder check-all js
document.getElementById('select-all').onclick = function() {
var checkboxes = document.querySelectorAll('input[type="checkbox"]');
for (var checkbox of checkboxes) {
checkbox.checked = this.checked;
}
}
</script>
{% endblock %}

View file

@ -0,0 +1,11 @@
from django import template
from django.utils.translation import get_language_info
register = template.Library()
@register.filter
def get_language_code(language_code, languages):
for lang in languages:
if lang['code'] == language_code:
return lang['name_local'].lower()
return language_code.lower()

View file

@ -1,8 +1,8 @@
from django import forms
from utils.device import create_annotation, create_doc, create_index
from utils.save_snapshots import move_json, save_in_disk
from django.utils.translation import gettext_lazy as _
#TODO: translate device types
DEVICE_TYPES = [
("Desktop", "Desktop"),
("Laptop", "Laptop"),
@ -22,11 +22,11 @@ DEVICE_TYPES = [
class DeviceForm(forms.Form):
type = forms.ChoiceField(choices = DEVICE_TYPES, required=False)
amount = forms.IntegerField(required=False, initial=1)
custom_id = forms.CharField(required=False)
name = forms.CharField(required=False)
value = forms.CharField(required=False)
type = forms.ChoiceField(choices = DEVICE_TYPES, required=False, label= _(u"Type"))
amount = forms.IntegerField(required=False, initial=1, label= _(u"Amount"))
custom_id = forms.CharField(required=False, label=_(u"Custom id"))
name = forms.CharField(required=False, label= _(u"Name"))
value = forms.CharField(required=False, label=_(u"Value"))
class BaseDeviceFormSet(forms.BaseFormSet):

View file

@ -65,6 +65,9 @@ ENABLE_EMAIL = config("ENABLE_EMAIL", default=True, cast=bool)
EVIDENCES_DIR = config("EVIDENCES_DIR", default=os.path.join(BASE_DIR, "db"))
LOCALE_PATHS = [
os.path.join(BASE_DIR, 'locale'),
]
# Application definition
INSTALLED_APPS = [
@ -116,7 +119,13 @@ TEMPLATES = [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"django.template.context_processors.i18n",
],
'libraries':{
'get_language_code': 'dashboard.templatetags.language_code',
}
},
},
]
@ -169,8 +178,9 @@ if TIME_ZONE == "UTC":
USE_L10N = True
LANGUAGES = [
('es', 'Spanish'),
('en', 'English'),
('es', 'spanish'),
('en', 'english'),
('ca', 'català'),
]
# Static files (CSS, JavaScript, Images)

View file

@ -16,6 +16,10 @@ Including another URLconf
"""
from django.urls import path, include
from django.conf.urls.i18n import i18n_patterns
from django.conf import settings
from django.conf.urls.static import static
from django.views.i18n import set_language
urlpatterns = [
# path('api/', include('snapshot.urls')),
@ -28,3 +32,11 @@ urlpatterns = [
path("lot/", include("lot.urls")),
path('api/', include('api.urls')),
]
urlpatterns += i18n_patterns(
path("language/", set_language, name='set_language'),
)
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View file

@ -5,6 +5,7 @@ RUN apt update && \
apt-get install -y \
python3-xapian \
git \
gettext \
sqlite3 \
jq \
&& rm -rf /var/lib/apt/lists/*

Binary file not shown.

View file

@ -0,0 +1,716 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-28 03:35-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: admin/templates/admin_panel.html:14
msgid "Institution"
msgstr "Institució"
#: admin/templates/admin_users.html:10
msgid "New user"
msgstr "Afegeix un nou usuari"
#: admin/templates/admin_users.html:19
msgid "Email"
msgstr "correu electrònic"
#: admin/templates/admin_users.html:20 admin/views.py:26
#: dashboard/templates/base.html:86
msgid "Admin"
msgstr "Administrador"
#: admin/templates/admin_users.html:21
msgid "Actions"
msgstr "Accions"
#: admin/templates/admin_users.html:28
msgid "Yes"
msgstr "Sí"
#: admin/templates/admin_users.html:28
msgid "No"
msgstr "No"
#: admin/templates/delete_user.html:33 admin/templates/institution.html:27
#: admin/templates/user.html:27 api/templates/new_token.html:27
#: device/templates/new_annotation.html:39 device/templates/new_device.html:81
#: device/templates/physical_properties.html:117
#: evidence/templates/ev_details.html:92
#: evidence/templates/ev_eraseserver.html:52 evidence/templates/upload.html:25
#: lot/templates/delete_lot.html:33 lot/templates/new_annotation.html:39
#: lot/templates/new_lot.html:27 user/templates/settings.html:27
msgid "Cancel"
msgstr "Cancel·la"
#: admin/templates/delete_user.html:34 api/tables.py:29
#: evidence/templates/ev_details.html:97 lot/templates/delete_lot.html:34
msgid "Delete"
msgstr "Elimina"
#: admin/templates/institution.html:28 admin/templates/user.html:28
#: api/templates/new_token.html:28 device/templates/new_annotation.html:40
#: device/templates/new_device.html:82
#: device/templates/physical_properties.html:118
#: evidence/templates/ev_details.html:93
#: evidence/templates/ev_eraseserver.html:53 evidence/templates/upload.html:26
#: lot/templates/new_annotation.html:40 lot/templates/new_lot.html:28
#: user/templates/settings.html:28
msgid "Save"
msgstr "Desa"
#: admin/views.py:27
msgid "admin"
msgstr "administrador"
#: admin/views.py:36 dashboard/templates/base.html:96
msgid "Users"
msgstr "Usuaris"
#: admin/views.py:37
msgid "admin / Users"
msgstr "administrador / Usuaris"
#: admin/views.py:49 user/views.py:18
msgid "User"
msgstr "Usuari"
#: admin/views.py:50
msgid "admin / User"
msgstr "administrador / Usuari"
#: admin/views.py:74
msgid "Delete user"
msgstr "Elimina usuari"
#: admin/views.py:91
msgid "Edit user"
msgstr "Edita usuari"
#: admin/views.py:110 admin/views.py:112
msgid "Edit institution"
msgstr "Edita institució"
#: api/tables.py:51
msgid "Token"
msgstr "Token"
#: api/tables.py:52 evidence/forms.py:65 evidence/templates/ev_details.html:18
#: evidence/templates/ev_eraseserver.html:18
msgid "Tag"
msgstr "Etiqueta"
#: api/templates/custom_table.html:65 dashboard/templates/pagination.html:13
msgid "Previous"
msgstr "Anterior"
#: api/templates/custom_table.html:91 dashboard/templates/pagination.html:38
#: login/templates/login.html:41
msgid "Next"
msgstr "Següent"
#: api/templates/token.html:13
msgid "Generate a new token"
msgstr "Genera un nou token"
#: api/views.py:144 api/views.py:178 api/views.py:196
msgid "Credential management"
msgstr "Gestió de credencials"
#: api/views.py:146
msgid "Managament Tokens"
msgstr "Tokens de gestió"
#: api/views.py:180 api/views.py:198
msgid "New Tokens"
msgstr "Nous Tokens"
#: dashboard/mixins.py:15
msgid "Permission denied. User is not authenticated"
msgstr "Permís denegat. L'usuari no està autenticat"
#: dashboard/templates/base.html:91
msgid "Panel"
msgstr "Panell"
#: dashboard/templates/base.html:105 evidence/templates/ev_details.html:15
#: evidence/templates/ev_eraseserver.html:15
msgid "Devices"
msgstr "Dispositius"
#: dashboard/templates/base.html:110
msgid "Unassigned"
msgstr "Sense assignar"
#: dashboard/templates/base.html:118 device/templates/details.html:24
msgid "Lots"
msgstr "Lots"
#: dashboard/templates/base.html:133 device/templates/details.html:30
#: evidence/views.py:28 evidence/views.py:87 evidence/views.py:174
msgid "Evidences"
msgstr "Evidències"
#: dashboard/templates/base.html:138
msgid "Upload"
msgstr "Carregar"
#: dashboard/templates/base.html:143
msgid "Old evidences"
msgstr "Evidències antigues"
#: dashboard/templates/base.html:151
msgid "Placeholders"
msgstr "Marcadors de posició"
#: dashboard/templates/base.html:156
msgid "Import from spreadsheet"
msgstr "Carrega full de càlcul"
#: dashboard/templates/base.html:161
msgid "Add device"
msgstr "Afegeix un dispositiu"
#: dashboard/templates/base.html:186
msgid "Search your device"
msgstr "Cerca dispositius"
#: dashboard/templates/unassigned_devices.html:15
#: device/templates/details.html:21 device/templates/details.html:150
#: lot/templates/documents.html:22
msgid "Documents"
msgstr "Documents"
#: dashboard/templates/unassigned_devices.html:20
msgid "Exports"
msgstr "Exportacions"
#: dashboard/templates/unassigned_devices.html:25
#: device/templates/details.html:111 lot/templates/annotations.html:22
msgid "Annotations"
msgstr "Annotations"
#: dashboard/templates/unassigned_devices.html:41
msgid "Short ID"
msgstr "identificació"
#: dashboard/templates/unassigned_devices.html:44 device/forms.py:25
#: evidence/templates/ev_details.html:38
msgid "Type"
msgstr "Tipus"
#: dashboard/templates/unassigned_devices.html:47
#: device/templates/details.html:71
msgid "Manufacturer"
msgstr "Fabricant"
#: dashboard/templates/unassigned_devices.html:50
#: device/templates/details.html:78
msgid "Model"
msgstr "Model"
#: dashboard/templates/unassigned_devices.html:80
msgid "Remove"
msgstr "Eliminar"
#: dashboard/templates/unassigned_devices.html:83
msgid "Add"
msgstr "Afegir"
#: dashboard/views.py:18
msgid "Unassigned Devices"
msgstr "Dispositius no assignats"
#: dashboard/views.py:28
msgid "Lot Devices"
msgstr "Dispositius del lot"
#: dashboard/views.py:52
msgid "Search Devices"
msgstr "Cerca dispositius"
#: device/forms.py:26
msgid "Amount"
msgstr "Quantitat"
#: device/forms.py:27
msgid "Custom id"
msgstr "Identificador personalitzat"
#: device/forms.py:28 user/models.py:10
msgid "Name"
msgstr "Nom"
#: device/forms.py:29 device/templates/details.html:119
#: device/templates/details.html:158 lot/templates/annotations.html:27
#: lot/templates/documents.html:27
msgid "Value"
msgstr "Valor"
#: device/templates/details.html:15
msgid "General details"
msgstr "Detalls generals"
#: device/templates/details.html:18
msgid "User annotations"
msgstr "Annotations de l'usuari"
#: device/templates/details.html:27
msgid "Components"
msgstr "Components"
#: device/templates/details.html:41
msgid "Details"
msgstr "Detalls"
#: device/templates/details.html:50
msgid "Is a erase server"
msgstr "És un servidor d'esborrat"
#: device/templates/details.html:85
msgid "Serial Number"
msgstr "Número de sèrie"
#: device/templates/details.html:93
msgid "Identifiers"
msgstr "Identificadors"
#: device/templates/details.html:107 lot/templates/annotations.html:17
msgid "Add new annotation"
msgstr "Afegeix una nova anotació"
#: device/templates/details.html:116 device/templates/details.html:155
#: lot/templates/annotations.html:26 lot/templates/documents.html:26
msgid "Key"
msgstr "Clau"
#: device/templates/details.html:122 device/templates/details.html:161
#: lot/templates/annotations.html:28
msgid "Created on"
msgstr "Creat el"
#: device/templates/details.html:146 lot/templates/documents.html:17
msgid "Add new document"
msgstr "Afegeix un nou document"
#: device/templates/details.html:197
msgid "Components last evidence"
msgstr "Última evidència dels components"
#: device/templates/details.html:218
msgid "List of evidences"
msgstr "Llista d'evidències"
#: device/templates/new_device.html:60
msgid "Component details"
msgstr "Detalls del component"
#: device/templates/new_device.html:65
msgid "Add component"
msgstr "Afegeix component"
#: device/views.py:23
msgid "New Device"
msgstr "Nou dispositiu"
#: device/views.py:69
msgid "Update Device"
msgstr "Actualitza dispositiu"
#: device/views.py:88
msgid "Device"
msgstr "Dispositiu"
#: device/views.py:172
msgid "New annotation"
msgstr "Nova anotació"
#: device/views.py:205 lot/views.py:147 lot/views.py:171
msgid "New Document"
msgstr "Nou document"
#: evidence/forms.py:16
msgid "File"
msgstr "Fitxer"
#: evidence/forms.py:39
msgid "The snapshot already exists"
msgstr "La instantània ja existeix"
#: evidence/forms.py:46
#, python-format
msgid "Error on '%(file_name)s': %(error)s"
msgstr "Error en '%(file_name)s': %(error)s"
#: evidence/forms.py:120
msgid "File to import"
msgstr "Fitxer a importar"
#: evidence/forms.py:138
#, python-format
msgid "Error on '%(file_name)s': Invalid File"
msgstr "Error en '%(file_name)s': Fitxer invàlid"
#: evidence/forms.py:147
msgid "The file you try to import is empty!"
msgstr "El fitxer que intentes importar està buit!"
#: evidence/forms.py:183
msgid "Is a Erase Server"
msgstr "És un servidor d'esborrat"
#: evidence/templates/ev_details.html:21
#: evidence/templates/ev_eraseserver.html:21
msgid "Erase Server"
msgstr "Servidor d'esborrat"
#: evidence/templates/ev_details.html:24
#: evidence/templates/ev_eraseserver.html:24
msgid "Download File"
msgstr "Descarrega fitxer"
#: evidence/templates/ev_details.html:41
msgid "Identificator"
msgstr "Identificador"
#: evidence/templates/ev_details.html:44
msgid "Data"
msgstr "Dades"
#: evidence/views.py:44
msgid "Upload Evidence"
msgstr "Carrega evidència"
#: evidence/views.py:51
msgid "Evidence uploaded successfully."
msgstr "Evidència carregada amb èxit."
#: evidence/views.py:63
msgid "Import Evidence"
msgstr "Importa evidència"
#: evidence/views.py:75
msgid "Evidence imported successfully."
msgstr "Evidència importada amb èxit."
#: login/templates/2fadmin.html:8
msgid "Two-factor Authentication"
msgstr "Autenticació de dos factors"
#: login/templates/2fadmin.html:15
msgid "We have sent you an email with a link that you have to click to log in."
msgstr ""
"T'hem enviat un correu electrònic amb un enllaç que has de fer clic per "
"iniciar sessió."
#: login/templates/2fadmin_email.html:3 login/templates/2fadmin_email.txt:2
#, python-format
msgid "You're receiving this email because you tried to access %(site_name)s."
msgstr ""
"Estàs rebent aquest correu electrònic perquè has intentat accedir a "
"%(site_name)s."
#: login/templates/2fadmin_email.html:7 login/templates/2fadmin_email.txt:4
msgid "Please go to the following page"
msgstr "Si us plau, ves a la pàgina següent"
#: login/templates/2fadmin_email.html:19 login/templates/2fadmin_email.txt:10
#: login/templates/activate_user_email.html:24
#: login/templates/activate_user_email.txt:15
#: login/templates/password_reset_email.html:23
#: login/templates/password_reset_email.txt:10
msgid "Thanks for using our site!"
msgstr "Gràcies per utilitzar el nostre lloc!"
#: login/templates/2fadmin_email.html:23 login/templates/2fadmin_email.txt:12
#: login/templates/password_reset_email.html:27
#: login/templates/password_reset_email.txt:12
#, python-format
msgid "The %(site_name)s team"
msgstr "L'equip de %(site_name)s"
#: login/templates/2fadmin_email.txt:8
#: login/templates/password_reset_email.html:19
#: login/templates/password_reset_email.txt:8
msgid "Your username, in case you've forgotten:"
msgstr "El teu nom d'usuari, per si l'has oblidat:"
#: login/templates/2fadmin_email_subject.txt:2
#, python-format
msgid "Authentication in %(site_name)s"
msgstr "Autenticació a %(site_name)s"
#: login/templates/activate_user_email.html:2
#: login/templates/activate_user_email.txt:3
msgid "DeviceHub"
msgstr "DeviceHub"
#: login/templates/activate_user_email.html:4
#: login/templates/activate_user_email.txt:5
#, python-format
msgid ""
"You're receiving this email because your user account at %(site)s has been "
"activated."
msgstr ""
"Estàs rebent aquest correu electrònic perquè el teu compte d'usuari a "
"%(site)s ha estat activat."
#: login/templates/activate_user_email.html:8
#: login/templates/activate_user_email.txt:7
msgid "Your username is:"
msgstr "El teu nom d'usuari és:"
#: login/templates/activate_user_email.html:12
#: login/templates/activate_user_email.txt:9
msgid "Please go to the following page and choose a password:"
msgstr "Si us plau, ves a la pàgina següent i tria una contrasenya:"
#: login/templates/activate_user_email.html:28
#: login/templates/activate_user_email.txt:17
#, python-format
msgid "The %(site)s team"
msgstr "L'equip de %(site)s"
#: login/templates/activate_user_subject.txt:2
msgid "IdHub"
msgstr "IdHub"
#: login/templates/activate_user_subject.txt:3
#, python-format
msgid "User activation on %(site)s"
msgstr "Activació d'usuari a %(site)s"
#: login/templates/login.html:7
msgid "Sign in"
msgstr "Inicia sessió"
#: login/templates/login.html:48
msgid "Forgot your password?"
msgstr "Has oblidat la teva contrasenya?"
#: login/templates/login2.html:45
msgid "Log in"
msgstr "Inicia sessió"
#: login/templates/login2.html:50
msgid "Forgot your password? Click here to recover"
msgstr "Has oblidat la teva contrasenya? Fes clic aquí per recuperar-la"
#: login/templates/password_reset.html:7
msgid "Password Reset"
msgstr "Restabliment de contrasenya"
#: login/templates/password_reset.html:9
msgid ""
"Enter your email address below, and we'll email instructions for setting a "
"new one."
msgstr ""
"Introdueix la teva adreça de correu electrònic a continuació i t'enviarem "
"instruccions per establir-ne una de nova."
#: login/templates/password_reset.html:15
msgid "Reset"
msgstr "Restableix"
#: login/templates/password_reset.html:21
#: login/templates/password_reset_complete.html:21
#: login/templates/password_reset_done.html:14
msgid "Back to login"
msgstr "Torna a iniciar sessió"
#: login/templates/password_reset_complete.html:10
msgid "Password reset complete"
msgstr "Restabliment de contrasenya complet"
#: login/templates/password_reset_complete.html:12
msgid "Your new password has been set. You may go ahead and log in now."
msgstr "La teva contrasenya ha estat establerta. Ara pots iniciar sessió."
#: login/templates/password_reset_confirm.html:9
msgid "Enter new password"
msgstr "Introdueix una nova contrasenya"
#: login/templates/password_reset_confirm.html:10
msgid ""
"Please enter your new password twice so we can verify you typed it in "
"correctly."
msgstr ""
"Si us plau, introdueix la teva nova contrasenya dues vegades perquè puguem "
"verificar que l'has escrit correctament."
#: login/templates/password_reset_confirm.html:21
msgid "Change my password"
msgstr "Canvia la meva contrasenya"
#: login/templates/password_reset_confirm.html:29
msgid "Password reset unsuccessful"
msgstr "Restabliment de contrasenya no reeixit"
#: login/templates/password_reset_confirm.html:30
msgid ""
"The password reset link was invalid, possibly because it has already been "
"used."
msgstr ""
"L'enllaç de restabliment de contrasenya no és vàlid, possiblement perquè ja "
"s'ha utilitzat."
#: login/templates/password_reset_confirm.html:31
msgid "Please request a new password reset."
msgstr "Si us plau, sol·licita un nou restabliment de contrasenya."
#: login/templates/password_reset_done.html:7
msgid "Password reset sent"
msgstr "Restabliment de contrasenya enviat"
#: login/templates/password_reset_done.html:8
msgid ""
"We've sent you an email with instructions to reset your password. If an "
"account with the provided email exists, you should receive it shortly."
msgstr ""
"T'hem enviat per correu electrònic instruccions per establir la teva "
"contrasenya, si existeix un compte amb el correu electrònic que has "
"introduït. Hauries de rebre-les en breu."
#: login/templates/password_reset_done.html:9
msgid ""
"If you don't receive an email, please check the email address you entered "
"and look in your spam folder."
msgstr ""
"Si no reps un correu electrònic, si us plau, assegura't que has introduït "
"l'adreça amb la qual et vas registrar i revisa la teva carpeta de correu "
"brossa."
#: login/templates/password_reset_email.html:3
#: login/templates/password_reset_email.txt:2
#, python-format
msgid ""
"You're receiving this email because you requested a password reset for your "
"user account at %(site_name)s."
msgstr ""
"Estàs rebent aquest correu electrònic perquè has sol·licitat un restabliment "
"de contrasenya per al teu compte d'usuari a %(site_name)s."
#: login/templates/password_reset_email.html:7
#: login/templates/password_reset_email.txt:4
msgid "Please go to the following page and choose a new password:"
msgstr "Si us plau, aneu a la pàgina següent i trieu una nova contrasenya:"
#: login/templates/password_reset_subject.txt:2
#, python-format
msgid "Password reset on %(site_name)s"
msgstr "Restabliment de la contrasenya a %(site_name)s"
#: login/views.py:20
msgid "Login"
msgstr "Inicia sessió"
#: login/views.py:45
msgid "Login error. Check credentials."
msgstr "Error d'inici de sessió. comprovar les credencials"
#: lot/templates/documents.html:28
msgid " Created on"
msgstr "Creat el"
#: lot/templates/lots.html:12
msgid "Hide closed lots"
msgstr "Amaga lots tancats"
#: lot/templates/lots.html:16
msgid "Show closed lots"
msgstr "Mostra lots tancats"
#: lot/templates/lots.html:22
msgid "Add new lot"
msgstr "Afegeix un nou lot"
#: lot/views.py:18
msgid "New lot"
msgstr "Nou lot"
#: lot/views.py:39
msgid "Delete lot"
msgstr "Elimina lot"
#: lot/views.py:58
msgid "Edit lot"
msgstr "Edita lot"
#: lot/views.py:84
msgid "Add to lots"
msgstr "Afegeix als lots"
#: lot/views.py:112
msgid "Remove from lots"
msgstr "Elimina dels lots"
#: lot/views.py:124 lot/views.py:125
msgid "lots"
msgstr "lots"
#: lot/views.py:194 lot/views.py:217
msgid "New Annotation"
msgstr "Nova anotació"
#: user/models.py:16
msgid "Logo"
msgstr "Logotip"
#: user/models.py:17
msgid "Location"
msgstr "Ubicació"
#: user/models.py:19
msgid "Responsable"
msgstr "Responsable"
#: user/models.py:25
msgid "Supervisor"
msgstr "Supervisor"
#: user/models.py:67
msgid "Email address"
msgstr "Adreça electrònica"
#: user/models.py:71
msgid "is active"
msgstr "està actiu"
#: user/models.py:72
msgid "is admin"
msgstr "és administrador"
#: user/models.py:73
msgid "First name"
msgstr "Nom"
#: user/models.py:74
msgid "Last name"
msgstr "Cognom"
#: user/templates/panel.html:17
msgid "Admin your Tokens"
msgstr "Administra els teus tokens"
#: user/templates/panel.html:22
msgid "Download a settings file"
msgstr "Descarrega un fitxer de configuració"
#: user/views.py:25
msgid "Download Settings"
msgstr "Descarrega configuració"

Binary file not shown.

View file

@ -0,0 +1,723 @@
# ALGÚN TÍTULO DESCRIPTIVO.
# Copyright (C) AÑO EL TITULAR DE LOS DERECHOS DE AUTOR DEL PAQUETE
# Este archivo se distribuye bajo la misma licencia que el paquete PACKAGE.
# PRIMER AUTOR <EMAIL@ADDRESS>, AÑO.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: VERSIÓN DEL PAQUETE\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-28 03:34-0300\n"
"PO-Revision-Date: AÑO-MO-DA HO:MI+ZONE\n"
"Last-Translator: NOMBRE COMPLETO <EMAIL@ADDRESS>\n"
"Language-Team: LENGUAJE <LL@li.org>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: admin/templates/admin_panel.html:14
msgid "Institution"
msgstr "Institución"
#: admin/templates/admin_users.html:10
msgid "New user"
msgstr "Nuevo usuario"
#: admin/templates/admin_users.html:19
msgid "Email"
msgstr "Email"
#: admin/templates/admin_users.html:20 admin/views.py:26
#: dashboard/templates/base.html:86
msgid "Admin"
msgstr "Administrador"
#: admin/templates/admin_users.html:21
msgid "Actions"
msgstr "Acciones"
#: admin/templates/admin_users.html:28
msgid "Yes"
msgstr "Sí"
#: admin/templates/admin_users.html:28
msgid "No"
msgstr "No"
#: admin/templates/delete_user.html:33 admin/templates/institution.html:27
#: admin/templates/user.html:27 api/templates/new_token.html:27
#: device/templates/new_annotation.html:39 device/templates/new_device.html:81
#: device/templates/physical_properties.html:117
#: evidence/templates/ev_details.html:92
#: evidence/templates/ev_eraseserver.html:52 evidence/templates/upload.html:25
#: lot/templates/delete_lot.html:33 lot/templates/new_annotation.html:39
#: lot/templates/new_lot.html:27 user/templates/settings.html:27
msgid "Cancel"
msgstr "Cancelar"
#: admin/templates/delete_user.html:34 api/tables.py:29
#: evidence/templates/ev_details.html:97 lot/templates/delete_lot.html:34
msgid "Delete"
msgstr "Eliminar"
#: admin/templates/institution.html:28 admin/templates/user.html:28
#: api/templates/new_token.html:28 device/templates/new_annotation.html:40
#: device/templates/new_device.html:82
#: device/templates/physical_properties.html:118
#: evidence/templates/ev_details.html:93
#: evidence/templates/ev_eraseserver.html:53 evidence/templates/upload.html:26
#: lot/templates/new_annotation.html:40 lot/templates/new_lot.html:28
#: user/templates/settings.html:28
msgid "Save"
msgstr "Guardar"
#: admin/views.py:27
msgid "admin"
msgstr "administrador"
#: admin/views.py:36 dashboard/templates/base.html:96
msgid "Users"
msgstr "Usuarios"
#: admin/views.py:37
msgid "admin / Users"
msgstr "administrador / Usuarios"
#: admin/views.py:49 user/views.py:18
msgid "User"
msgstr "Usuario"
#: admin/views.py:50
msgid "admin / User"
msgstr "administrador / Usuario"
#: admin/views.py:74
msgid "Delete user"
msgstr "Eliminar usuario"
#: admin/views.py:91
msgid "Edit user"
msgstr "Editar usuario"
#: admin/views.py:110 admin/views.py:112
msgid "Edit institution"
msgstr "Editar institución"
#: api/tables.py:51
msgid "Token"
msgstr "Token"
#: api/tables.py:52 evidence/forms.py:65 evidence/templates/ev_details.html:18
#: evidence/templates/ev_eraseserver.html:18
msgid "Tag"
msgstr "Etiqueta"
#: api/templates/custom_table.html:65 dashboard/templates/pagination.html:13
msgid "Previous"
msgstr "Anterior"
#: api/templates/custom_table.html:91 dashboard/templates/pagination.html:38
#: login/templates/login.html:41
msgid "Next"
msgstr "Siguiente"
#: api/templates/token.html:13
msgid "Generate a new token"
msgstr "Generar un nuevo token"
#: api/views.py:144 api/views.py:178 api/views.py:196
msgid "Credential management"
msgstr "Gestión de credenciales"
#: api/views.py:146
msgid "Managament Tokens"
msgstr "Tokens de gestión"
#: api/views.py:180 api/views.py:198
msgid "New Tokens"
msgstr "Nuevos Tokens"
#: dashboard/mixins.py:15
msgid "Permission denied. User is not authenticated"
msgstr "Permiso denegado. El usuario no está autenticado"
#: dashboard/templates/base.html:91
msgid "Panel"
msgstr "Panel"
#: dashboard/templates/base.html:105 evidence/templates/ev_details.html:15
#: evidence/templates/ev_eraseserver.html:15
msgid "Devices"
msgstr "Dispositivos"
#: dashboard/templates/base.html:110
msgid "Unassigned"
msgstr "Sin asignar"
#: dashboard/templates/base.html:118 device/templates/details.html:24
msgid "Lots"
msgstr "Lotes"
#: dashboard/templates/base.html:133 device/templates/details.html:30
#: evidence/views.py:28 evidence/views.py:87 evidence/views.py:174
msgid "Evidences"
msgstr "Evidencias"
#: dashboard/templates/base.html:138
msgid "Upload"
msgstr "Subir"
#: dashboard/templates/base.html:143
msgid "Old evidences"
msgstr "Evidencias antiguas"
#: dashboard/templates/base.html:151
msgid "Placeholders"
msgstr "Placeholders"
#: dashboard/templates/base.html:156
msgid "Import from spreadsheet"
msgstr "Importar desde hoja de cálculo"
#: dashboard/templates/base.html:161
msgid "Add device"
msgstr "Nuevo Dispositivo"
#: dashboard/templates/base.html:186
msgid "Search your device"
msgstr "Buscar dispositivos"
#: dashboard/templates/unassigned_devices.html:15
#: device/templates/details.html:21 device/templates/details.html:150
#: lot/templates/documents.html:22
msgid "Documents"
msgstr "Documentos"
#: dashboard/templates/unassigned_devices.html:20
msgid "Exports"
msgstr "Exportar"
#: dashboard/templates/unassigned_devices.html:25
#: device/templates/details.html:111 lot/templates/annotations.html:22
msgid "Annotations"
msgstr "Anotaciones"
#: dashboard/templates/unassigned_devices.html:41
msgid "Short ID"
msgstr ""
#: dashboard/templates/unassigned_devices.html:44 device/forms.py:25
#: evidence/templates/ev_details.html:38
msgid "Type"
msgstr "Tipo"
#: dashboard/templates/unassigned_devices.html:47
#: device/templates/details.html:71
msgid "Manufacturer"
msgstr "Fabricante"
#: dashboard/templates/unassigned_devices.html:50
#: device/templates/details.html:78
msgid "Model"
msgstr "Modelo"
#: dashboard/templates/unassigned_devices.html:80
msgid "Remove"
msgstr "Eliminar"
#: dashboard/templates/unassigned_devices.html:83
msgid "Add"
msgstr "Agregar"
#: dashboard/views.py:18
msgid "Unassigned Devices"
msgstr "Sin asignar"
#: dashboard/views.py:28
msgid "Lot Devices"
msgstr "Dispositivos del lote"
#: dashboard/views.py:52
#, fuzzy
#| msgid "Search your device"
msgid "Search Devices"
msgstr "Buscar dispositivos"
#: device/forms.py:26
msgid "Amount"
msgstr "Cantidad"
#: device/forms.py:27
msgid "Custom id"
msgstr "Identificador personalizado"
#: device/forms.py:28 user/models.py:10
msgid "Name"
msgstr "Nombre"
#: device/forms.py:29 device/templates/details.html:119
#: device/templates/details.html:158 lot/templates/annotations.html:27
#: lot/templates/documents.html:27
msgid "Value"
msgstr "Valor"
#: device/templates/details.html:15
msgid "General details"
msgstr "Detalles generales"
#: device/templates/details.html:18
msgid "User annotations"
msgstr "Anotaciones del usuario"
#: device/templates/details.html:27
msgid "Components"
msgstr "Componentes"
#: device/templates/details.html:41
msgid "Details"
msgstr "Detalles"
#: device/templates/details.html:50
msgid "Is a erase server"
msgstr "Es un servidor de borrado"
#: device/templates/details.html:85
msgid "Serial Number"
msgstr "Número de serie"
#: device/templates/details.html:93
msgid "Identifiers"
msgstr "Identificadores"
#: device/templates/details.html:107 lot/templates/annotations.html:17
msgid "Add new annotation"
msgstr "Agregar nueva anotación"
#: device/templates/details.html:116 device/templates/details.html:155
#: lot/templates/annotations.html:26 lot/templates/documents.html:26
msgid "Key"
msgstr "Clave"
#: device/templates/details.html:122 device/templates/details.html:161
#: lot/templates/annotations.html:28
msgid "Created on"
msgstr "Creado el"
#: device/templates/details.html:146 lot/templates/documents.html:17
msgid "Add new document"
msgstr "Agregar nuevo documento"
#: device/templates/details.html:197
msgid "Components last evidence"
msgstr "Última evidencia de componentes"
#: device/templates/details.html:218
msgid "List of evidences"
msgstr "Lista de evidencias"
#: device/templates/new_device.html:60
msgid "Component details"
msgstr "Detalles del componente"
#: device/templates/new_device.html:65
msgid "Add component"
msgstr "Agregar componente"
#: device/views.py:23
msgid "New Device"
msgstr "Nuevo dispositivo"
#: device/views.py:69
msgid "Update Device"
msgstr "Actualizar dispositivo"
#: device/views.py:88
msgid "Device"
msgstr "Dispositivo"
#: device/views.py:172
msgid "New annotation"
msgstr "Nueva anotación"
#: device/views.py:205 lot/views.py:147 lot/views.py:171
#, fuzzy
#| msgid "Documents"
msgid "New Document"
msgstr "Nuevo Documento"
#: evidence/forms.py:16
msgid "File"
msgstr "Archivo"
#: evidence/forms.py:39
msgid "The snapshot already exists"
msgstr "La instantánea ya existe"
#: evidence/forms.py:46
#, python-format
msgid "Error on '%(file_name)s': %(error)s"
msgstr "Error en '%(file_name)s': %(error)s"
#: evidence/forms.py:120
msgid "File to import"
msgstr "Archivo a importar"
#: evidence/forms.py:138
#, python-format
msgid "Error on '%(file_name)s': Invalid File"
msgstr "Error en '%(file_name)s': Archivo inválido"
#: evidence/forms.py:147
msgid "The file you try to import is empty!"
msgstr "¡El archivo que intentas importar está vacío!"
#: evidence/forms.py:183
msgid "Is a Erase Server"
msgstr "Es un servidor de borrado"
#: evidence/templates/ev_details.html:21
#: evidence/templates/ev_eraseserver.html:21
msgid "Erase Server"
msgstr "Servidor de borrado"
#: evidence/templates/ev_details.html:24
#: evidence/templates/ev_eraseserver.html:24
msgid "Download File"
msgstr "Descargar archivo"
#: evidence/templates/ev_details.html:41
msgid "Identificator"
msgstr "Identificador"
#: evidence/templates/ev_details.html:44
msgid "Data"
msgstr "Datos"
#: evidence/views.py:44
msgid "Upload Evidence"
msgstr "Subir evidencia"
#: evidence/views.py:51
msgid "Evidence uploaded successfully."
msgstr "Evidencia subida exitosamente."
#: evidence/views.py:63
msgid "Import Evidence"
msgstr "Importar evidencia"
#: evidence/views.py:75
msgid "Evidence imported successfully."
msgstr "Evidencia importada exitosamente."
#: login/templates/2fadmin.html:8
msgid "Two-factor Authentication"
msgstr "Autenticación de dos factores"
#: login/templates/2fadmin.html:15
msgid "We have sent you an email with a link that you have to click to log in."
msgstr ""
"Te hemos enviado un correo electrónico con un enlace que debes hacer clic "
"para iniciar sesión."
#: login/templates/2fadmin_email.html:3 login/templates/2fadmin_email.txt:2
#, python-format
msgid "You're receiving this email because you tried to access %(site_name)s."
msgstr ""
"Estás recibiendo este correo electrónico porque intentaste acceder a "
"%(site_name)s."
#: login/templates/2fadmin_email.html:7 login/templates/2fadmin_email.txt:4
msgid "Please go to the following page"
msgstr "Por favor, ve a la siguiente página"
#: login/templates/2fadmin_email.html:19 login/templates/2fadmin_email.txt:10
#: login/templates/activate_user_email.html:24
#: login/templates/activate_user_email.txt:15
#: login/templates/password_reset_email.html:23
#: login/templates/password_reset_email.txt:10
msgid "Thanks for using our site!"
msgstr "¡Gracias por usar nuestro sitio!"
#: login/templates/2fadmin_email.html:23 login/templates/2fadmin_email.txt:12
#: login/templates/password_reset_email.html:27
#: login/templates/password_reset_email.txt:12
#, python-format
msgid "The %(site_name)s team"
msgstr "El equipo de %(site_name)s"
#: login/templates/2fadmin_email.txt:8
#: login/templates/password_reset_email.html:19
#: login/templates/password_reset_email.txt:8
msgid "Your username, in case you've forgotten:"
msgstr "Tu nombre de usuario, en caso de que lo hayas olvidado:"
#: login/templates/2fadmin_email_subject.txt:2
#, python-format
msgid "Authentication in %(site_name)s"
msgstr "Autenticación en %(site_name)s"
#: login/templates/activate_user_email.html:2
#: login/templates/activate_user_email.txt:3
msgid "DeviceHub"
msgstr "DeviceHub"
#: login/templates/activate_user_email.html:4
#: login/templates/activate_user_email.txt:5
#, python-format
msgid ""
"You're receiving this email because your user account at %(site)s has been "
"activated."
msgstr ""
"Estás recibiendo este correo electrónico porque tu cuenta de usuario en "
"%(site)s ha sido activada."
#: login/templates/activate_user_email.html:8
#: login/templates/activate_user_email.txt:7
msgid "Your username is:"
msgstr "Tu nombre de usuario es:"
#: login/templates/activate_user_email.html:12
#: login/templates/activate_user_email.txt:9
msgid "Please go to the following page and choose a password:"
msgstr "Por favor, ve a la siguiente página y elige una contraseña:"
#: login/templates/activate_user_email.html:28
#: login/templates/activate_user_email.txt:17
#, python-format
msgid "The %(site)s team"
msgstr "El equipo de %(site)s"
#: login/templates/activate_user_subject.txt:2
msgid "IdHub"
msgstr "IdHub"
#: login/templates/activate_user_subject.txt:3
#, python-format
msgid "User activation on %(site)s"
msgstr "Activación de usuario en %(site)s"
#: login/templates/login.html:7
msgid "Sign in"
msgstr "Iniciar sesión"
#: login/templates/login.html:48
msgid "Forgot your password?"
msgstr "¿Olvidaste tu contraseña?"
#: login/templates/login2.html:45
msgid "Log in"
msgstr "Iniciar sesión"
#: login/templates/login2.html:50
msgid "Forgot your password? Click here to recover"
msgstr "¿Olvidaste tu contraseña? Haz clic aquí para recuperarla"
#: login/templates/password_reset.html:7
#, fuzzy
#| msgid "Password reset"
msgid "Password Reset"
msgstr "Restablecimiento de contraseña"
#: login/templates/password_reset.html:9
msgid ""
"Enter your email address below, and we'll email instructions for setting a "
"new one."
msgstr ""
"Ingresa tu dirección de correo electrónico a continuación y te enviaremos "
"instrucciones para establecer una nueva."
#: login/templates/password_reset.html:15
msgid "Reset"
msgstr "Reestablecer"
#: login/templates/password_reset.html:21
#: login/templates/password_reset_complete.html:21
#: login/templates/password_reset_done.html:14
msgid "Back to login"
msgstr "Volver a iniciar sesión"
#: login/templates/password_reset_complete.html:10
msgid "Password reset complete"
msgstr "Restablecimiento de contraseña completo"
#: login/templates/password_reset_complete.html:12
msgid "Your new password has been set. You may go ahead and log in now."
msgstr "Tu nueva contraseña ha sido establecida. Ahora puedes iniciar sesión."
#: login/templates/password_reset_confirm.html:9
msgid "Enter new password"
msgstr "Ingresa nueva contraseña"
#: login/templates/password_reset_confirm.html:10
msgid ""
"Please enter your new password twice so we can verify you typed it in "
"correctly."
msgstr ""
"Por favor, ingresa tu nueva contraseña dos veces para que podamos verificar "
"que la escribiste correctamente."
#: login/templates/password_reset_confirm.html:21
msgid "Change my password"
msgstr "Cambiar mi contraseña"
#: login/templates/password_reset_confirm.html:29
msgid "Password reset unsuccessful"
msgstr "Restablecimiento de contraseña fallido"
#: login/templates/password_reset_confirm.html:30
msgid ""
"The password reset link was invalid, possibly because it has already been "
"used."
msgstr ""
"El enlace para restablecer la contraseña no es válido, posiblemente porque "
"ya ha sido utilizado."
#: login/templates/password_reset_confirm.html:31
msgid "Please request a new password reset."
msgstr "Por favor, solicita un nuevo restablecimiento de contraseña."
#: login/templates/password_reset_done.html:7
msgid "Password reset sent"
msgstr "Restablecimiento de contraseña enviado"
#: login/templates/password_reset_done.html:8
msgid ""
"We've sent you an email with instructions to reset your password. If an "
"account with the provided email exists, you should receive it shortly."
msgstr ""
"Te hemos enviado por correo electrónico las instrucciones para establecer tu "
"contraseña. Si existe una cuenta con el correo electrónico que ingresaste, "
"deberías recibirlas en breve."
#: login/templates/password_reset_done.html:9
msgid ""
"If you don't receive an email, please check the email address you entered "
"and look in your spam folder."
msgstr ""
"Si no recibes un correo electrónico, por favor asegúrate de haber ingresado "
"la dirección con la que te registraste y revisa tu carpeta de spam."
#: login/templates/password_reset_email.html:3
#: login/templates/password_reset_email.txt:2
#, python-format
msgid ""
"You're receiving this email because you requested a password reset for your "
"user account at %(site_name)s."
msgstr ""
"Estás recibiendo este correo electrónico porque solicitaste un "
"restablecimiento de contraseña para tu cuenta de usuario en %(site_name)s."
#: login/templates/password_reset_email.html:7
#: login/templates/password_reset_email.txt:4
msgid "Please go to the following page and choose a new password:"
msgstr "Por favor, ve a la siguiente página y elige una nueva contraseña:"
#: login/templates/password_reset_subject.txt:2
#, python-format
msgid "Password reset on %(site_name)s"
msgstr "Restablecimiento de contraseña en %(site_name)s"
#: login/views.py:20
msgid "Login"
msgstr "Iniciar sesión"
#: login/views.py:45
msgid "Login error. Check credentials."
msgstr "Error al iniciar sesión. Verifica tus credenciales."
#: lot/templates/documents.html:28
#, fuzzy
#| msgid "Created on"
msgid " Created on"
msgstr "Creado el"
#: lot/templates/lots.html:12
msgid "Hide closed lots"
msgstr "Ocultar lotes cerrados"
#: lot/templates/lots.html:16
msgid "Show closed lots"
msgstr "Mostrar lotes cerrados"
#: lot/templates/lots.html:22
msgid "Add new lot"
msgstr "Agregar nuevo lote"
#: lot/views.py:18
msgid "New lot"
msgstr "Nuevo lote"
#: lot/views.py:39
msgid "Delete lot"
msgstr "Eliminar lote"
#: lot/views.py:58
msgid "Edit lot"
msgstr "Editar lote"
#: lot/views.py:84
msgid "Add to lots"
msgstr "Agregar a los lotes"
#: lot/views.py:112
msgid "Remove from lots"
msgstr "Eliminar de los lotes"
#: lot/views.py:124 lot/views.py:125
msgid "lots"
msgstr "lotes"
#: lot/views.py:194 lot/views.py:217
msgid "New Annotation"
msgstr "Nueva anotación"
#: user/models.py:16
msgid "Logo"
msgstr "Logotipo"
#: user/models.py:17
msgid "Location"
msgstr "Ubicación"
#: user/models.py:19
msgid "Responsable"
msgstr "Responsable"
#: user/models.py:25
msgid "Supervisor"
msgstr "Supervisor"
#: user/models.py:67
msgid "Email address"
msgstr "Dirección de correo electrónico"
#: user/models.py:71
msgid "is active"
msgstr "está activo"
#: user/models.py:72
msgid "is admin"
msgstr "es administrador"
#: user/models.py:73
msgid "First name"
msgstr "Nombre"
#: user/models.py:74
msgid "Last name"
msgstr "Apellido"
#: user/templates/panel.html:17
msgid "Admin your Tokens"
msgstr "Administra tus tokens"
#: user/templates/panel.html:22
msgid "Download a settings file"
msgstr "Descargar un archivo de configuración"
#: user/views.py:25
msgid "Download Settings"
msgstr "Descargar configuración"

View file

@ -1,46 +1,68 @@
{% extends "login_base.html" %}
{% load i18n static %}
{% load i18n static language_code %}
{% block login_content %}
<div class="pt-2 pb-3">
<h5 class="card-title text-center pb-0 fs-4 help"> {% trans "Sign in" %}</h5>
</div>
<form action="{% url 'login:login' %}" method="post" class="row g-3 needs-validation" novalidate>
{% csrf_token %}
<div class="col-12">
<div class="col-12 mb-">
<input type="email" name="username" maxlength="100" autocapitalize="off"
autocorrect="off" class="form-control textinput textInput" id="yourEmail" required
autocorrect="off" class="form-control textinput textInput {% if form.username.errors %}is-invalid{% endif %}" id="yourEmail" required
autofocus placeholder="{{ form.username.label }}"
{% if form.username.value %}value="{{ form.username.value }}" {% endif %}>
<div class="invalid-feedback">Please enter your email.</div>
{% if form.username.errors %}
<p class="text-error">
{{ form.username.errors|striptags }}
</p>
<div class="invalid-feedback d-block">
{{ form.username.errors|striptags }}
</div>
{% endif %}
</div>
<div class="col-12">
<div class="col-12 mb-3">
<div class="input-group">
<input type="password" name="password" maxlength="100" autocapitalize="off"
autocorrect="off" class="form-control textinput textInput" id="id_password"
placeholder="{{ form.password.label }}" required>
<input type="password" name="password" maxlength="100" autocapitalize="off"
autocorrect="off" class="form-control textinput textInput {% if form.password.errors %}is-invalid{% endif %}" id="id_password"
placeholder="{{ form.password.label }}" required>
<i class="input-group-text bi bi-eye" id="togglePassword" style="cursor: pointer"></i>
</div>
{% if form.password.errors %}
<p class="text-error">
{{ form.password.errors|striptags }}
</p>
{% endif %}
<i class="input-group-text bi bi-eye" id="togglePassword" style="cursor: pointer">
</i>
<div class="invalid-feedback d-block">
{{ form.password.errors|striptags }}
</div>
<div class="invalid-feedback">Please enter your password!</div>
{% endif %}
</div>
<input name="next" type="hidden" value="{{ success_url }}">
<div class="col-12">
<button class="btn btn-primary w-100" type="submit">Next</button>
</div>
<div class="col-12 mb-3">
<button class="btn btn-primary w-100" type="submit">{% trans "Next" %}</button>
</div>
</form>
<div id="login-footer" class="mt-3">
<a href="{% url 'login:password_reset' %}" data-toggle="modal" data-target="#forgotPasswordModal">{% trans "Forgot your password? Click here to recover" %}</a>
<div id="login-footer" class="d-flex justify-content-between align-items-center mt-4">
<a href="{% url 'login:password_reset' %}" data-toggle="modal" data-target="#forgotPasswordModal">{% trans "Forgot your password?" %}</a>
<div class="dropdown ms-auto">
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<button class="btn btn-tertiary dropdown-toggle" type="button" id="languageDropdown" data-bs-toggle="dropdown" aria-expanded="false">
{% get_current_language as LANGUAGE_CODE %}
{% get_language_info_list for LANGUAGES as languages %}
{{ LANGUAGE_CODE|get_language_code:languages }}
</button>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="languageDropdown">
{% for lang in languages %}
<li>
<button class="dropdown-item" type="submit" name="language" value="{{ lang.code }}">{{ lang.name_local }}</button>
</li>
{% endfor %}
</ul>
</form>
</div>
</div>
{% endblock %}
{% endblock %}

View file

@ -45,7 +45,7 @@
<div class="container">
<section class="section register min-vh-100 d-flex flex-column align-items-center justify-content-center py-4">
<section class="section register min-vh-100 d-flex flex-column align-items-center justify-content-center">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-4 col-md-6 d-flex flex-column align-items-center justify-content-center">
@ -57,51 +57,37 @@
</a>
</div><!-- End Logo -->
<div class="card mb-3 shadow p-3 mb-5 bg-body rounded">
<div class="card shadow bg-body rounded">
<div class="card-body">
<div class="pt-2 pb-3">
<h5 class="card-title text-center pb-0 fs-4 help">Sign in</h5>
</div>
{% block login_content %}
{% endblock login_content %}
</div>
</div>
{% if messages %}
<div class="col-12 mt-3">
{% for message in messages %}
<div class="alert alert-danger show text-center" role="alert">
{{message}}
</div>
{% endfor %}
</div>
{% endif %}
<div class="credits">
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<div class="container-fluid">
<div class="row">
<main class="col-md-12 bt-5">
{% block messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags|default:'info' }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
{% endblock messages %}
</main>
</div>
</div>
<!-- Footer -->
<footer class="footer text-center">
<footer class="footer text-center fixed-bottom bg-light py-3">
<div class="container">
<span class="text-muted">{{ commit_id }}</span>
</div>

View file

@ -2,26 +2,23 @@
{% load i18n django_bootstrap5 %}
{% block login_content %}
<div class="well">
<div class="row-fluid">
<h2>{% trans 'Password reset' %}</h2>
<span>{% trans "Forgotten your password? Enter your email address below, and we'll email instructions for setting a new one." %}</span>
</div>
<div class="card-body">
<div class="pt-2 pb-3">
<h4 class="card-title text-center pb-2 help"> {% trans "Password Reset" %}</h5>
</div>
<p class="text-center text-muted fs-6">{% trans "Enter your email address below, and we'll email instructions for setting a new one." %}</p>
<form action="{% url 'login:password_reset' %}" method="post" class="mt-4">
{% csrf_token %}
{% bootstrap_form form layout='floating' %}
{% bootstrap_form_errors form type='non_fields' %}
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary">{% trans 'Reset' %}</button>
</div>
</form>
</div>
<div class="well">
<div class="row-fluid">
<div>
<form action="{% url 'login:password_reset' %}" role="form" method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% bootstrap_form_errors form type='non_fields' %}
<div class="form-actions-no-box">
<input type="submit" name="submit" value="{% trans 'Reset my password' %}" class="btn btn-primary form-control" id="submit-id-submit">
</div>
</form>
</div>
</div><!-- /.row-fluid -->
</div><!--/.well-->
{% endblock %}
<div class="text-center mt-3">
<a href="{% url 'login:login' %}" class="btn btn-link text-secondary">{% trans 'Back to login' %}</a>
</div>
{% endblock %}

View file

@ -6,11 +6,19 @@
<div class="row-fluid">
<div class="well" style="width: 800px; margin: auto auto 50px auto">
<div class="row-fluid">
<h2>{% trans 'Password reset complete' %}</h2>
<p>{% trans 'Your password has been set. You may go ahead and log in now.' %}</p>
<a href="{% url 'login:login' %}">{% trans 'Login' %}</a>
<h2 class="card-title ">{% trans 'Password reset complete' %}</h2>
<p class="text-muted fs-6 mt-4">{% trans 'Your new password has been set. You may go ahead and log in now.' %}</p>
</div>
</div><!--/.well-->
</div><!-- /.row-fluid -->
<div class="text-end mt-3">
<a href="{% url 'login:login' %}" class="btn btn-link text-secondary">{% trans 'Back to login' %}</a>
</div>
</div><!-- /.container-fluid -->
{% endblock %}

View file

@ -4,12 +4,14 @@
{% block login_content %}
<div class="well">
<div class="row-fluid">
<h2>{% trans 'Password reset sent' %}</h2>
<p>{% trans "We've emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly." %}</p>
<p>{% trans "If you don't receive an email, please make sure you've entered the address you registered with, and check your spam folder." %}</p>
<h4 class="card-title text-center text-bold">{% trans 'Password reset sent' %}</h4>
<p class="text-center text-muted mt-4 fs-7">{% trans "We've sent you an email with instructions to reset your password. If an account with the provided email exists, you should receive it shortly." %}</p>
<p class="text-center text-muted fs-7">{% trans "If you don't receive an email, please check the email address you entered and look in your spam folder." %}</p>
</div><!-- /.row-fluid -->
<div class="text-center mt-3">
<a href="{% url 'login:login' %}" class="btn btn-link text-primary">{% trans 'Back to login' %}</a>
</div>
</div><!--/.well-->
{% endblock %}

View file

@ -1,5 +1,6 @@
import logging
from django.contrib import messages
from django.conf import settings
from django.urls import reverse_lazy
from django.contrib.auth import views as auth_views
@ -39,6 +40,10 @@ class LoginView(auth_views.LoginView):
return redirect(reverse_lazy("login:login"))
return redirect(self.extra_context['success_url'])
def form_invalid(self, form):
messages.error(self.request, _("Login error. Check credentials."))
return self.render_to_response(self.get_context_data(form=form), status=401)
def LogoutView(request):

View file

@ -14,18 +14,18 @@
<a href="{% url 'lot:add_annotation' lot.pk %}" class="btn btn-primary">
<i class="bi bi-plus"></i>
Add new annotation
{%trans "Add new annotation"%}
<span class="caret"></span>
</a>
</div>
<h5 class="card-title mt-2">Annotations</h5>
<h5 class="card-title mt-2">{% trans "Annotations" %}</h5>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Key</th>
<th scope="col">Value</th>
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Created on</th>
<th scope="col">{%trans "Key"%}</th>
<th scope="col">{%trans "Value"%}</th>
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">{%trans "Created on" %}</th>
<th></th>
<th></th>
</tr>

View file

@ -14,18 +14,18 @@
<a href="{% url 'lot:add_document' lot.pk %}" class="btn btn-primary">
<i class="bi bi-plus"></i>
Add new document
{% trans "Add new document"%}
<span class="caret"></span>
</a>
</div>
<h5 class="card-title mt-2">Documents</h5>
<h5 class="card-title mt-2">{%trans "Documents"%}</h5>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Key</th>
<th scope="col">Value</th>
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Created on</th>
<th scope="col">{% trans "Key"%}</th>
<th scope="col">{% trans "Value"%}</th>
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">{%trans " Created on" %}</th>
<th></th>
<th></th>
</tr>