DNS app translation

This commit is contained in:
Eduardo Silva 2025-04-15 10:22:10 -03:00
parent 707188b89a
commit be7d00803f
5 changed files with 259 additions and 82 deletions

View File

@ -2,9 +2,10 @@ import re
from crispy_forms.bootstrap import FormActions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Fieldset, Div, Field, Submit, HTML
from crispy_forms.layout import Div, Field, Fieldset, HTML, Layout, Submit
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from .models import DNSFilterList
from .models import DNSSettings, StaticHost
@ -18,13 +19,14 @@ class DNSSettingsForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DNSSettingsForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.fields['dns_primary'].label = 'Primary Resolver'
self.fields['dns_secondary'].label = 'Secondary Resolver'
self.fields['dns_primary'].label = _('Primary Resolver')
self.fields['dns_secondary'].label = _('Secondary Resolver')
self.fields['dns_primary'].required = True
back_label = _('Back')
self.helper.form_method = 'post'
self.helper.layout = Layout(
Fieldset(
'Resolver Settings',
_('Resolver Settings'),
Div(
Field('dns_primary', css_class='form-control'),
Field('dns_secondary', css_class='form-control'),
@ -32,8 +34,8 @@ class DNSSettingsForm(forms.ModelForm):
),
),
FormActions(
Submit('save', 'Save', css_class='btn btn-primary'),
HTML('<a class="btn btn-outline-primary" href="/dns/">Back</a>'),
Submit('save', _('Save'), css_class='btn btn-primary'),
HTML(f'<a class="btn btn-outline-primary" href="/dns/">{back_label}</a>'),
)
)
@ -60,13 +62,17 @@ class StaticHostForm(forms.ModelForm):
super(StaticHostForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
self.fields['hostname'].label = _('Hostname')
self.fields['ip_address'].label = _('IP Address')
back_label = _('Back')
delete_label = _('Delete')
if self.instance.pk:
delete_html = "<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>Delete</a>"
delete_html = f"<a href='javascript:void(0)' class='btn btn-outline-danger' data-command='delete' onclick='openCommandDialog(this)'>{delete_label}</a>"
else:
delete_html = ''
self.helper.layout = Layout(
Fieldset(
'Static DNS',
_('Static DNS'),
Div(
Field('hostname', css_class='form-control'),
Field('ip_address', css_class='form-control'),
@ -74,8 +80,8 @@ class StaticHostForm(forms.ModelForm):
),
),
FormActions(
Submit('save', 'Save', css_class='btn btn-primary'),
HTML('<a class="btn btn-outline-primary" href="/dns/">Back</a> '),
Submit('save', _('Save'), css_class='btn btn-primary'),
HTML(f'<a class="btn btn-outline-primary" href="/dns/">{back_label}</a> '),
HTML(delete_html),
)
)
@ -100,18 +106,23 @@ class DNSFilterListForm(forms.ModelForm):
super(DNSFilterListForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
# Add a delete button if editing an existing instance
back_label = _('Back')
delete_label = _('Delete')
self.fields['name'].label = _('Name')
self.fields['description'].label = _('Description')
self.fields['list_url'].label = _('List URL')
if self.instance.pk:
delete_html = (
"<a href='javascript:void(0)' class='btn btn-outline-danger' "
"data-command='delete' onclick='openCommandDialog(this)'>Delete</a>"
f"data-command='delete' onclick='openCommandDialog(this)'>{delete_label}</a>"
)
self.fields['name'].widget.attrs['readonly'] = True
else:
delete_html = ''
self.helper.layout = Layout(
Fieldset(
'DNS Filter List Details',
_('DNS Filter List Details'),
Div(
Div(Field('name', css_class='form-control'), css_class='col-md-12'),
Div(Field('description', css_class='form-control'), css_class='col-md-12'),
@ -120,8 +131,8 @@ class DNSFilterListForm(forms.ModelForm):
),
),
FormActions(
Submit('save', 'Save', css_class='btn btn-primary'),
HTML('<a class="btn btn-outline-primary" href="/dns/">Back</a>'),
Submit('save', _('Save'), css_class='btn btn-primary'),
HTML(f'<a class="btn btn-outline-primary" href="/dns/">{back_label}</a>'),
HTML(delete_html),
)
)

View File

@ -5,12 +5,13 @@ import requests
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, get_object_or_404, redirect
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from user_manager.models import UserAcl
from .forms import DNSFilterListForm
from .forms import StaticHostForm, DNSSettingsForm
from .forms import DNSSettingsForm, StaticHostForm
from .functions import generate_dnsmasq_config
from .models import DNSFilterList, DNSSettings
from .models import StaticHost
@ -29,13 +30,13 @@ def export_dns_configuration():
@login_required
def view_apply_dns_config(request):
export_dns_configuration()
messages.success(request, 'DNS settings applied successfully')
messages.success(request, _('DNS settings applied successfully'))
return redirect('/dns/')
@login_required
def view_static_host_list(request):
dns_settings, _ = DNSSettings.objects.get_or_create(name='dns_settings')
dns_settings, dns_settings_created = DNSSettings.objects.get_or_create(name='dns_settings')
static_host_list = StaticHost.objects.all().order_by('hostname')
filter_lists = DNSFilterList.objects.all().order_by('-recommended', 'name')
if not filter_lists:
@ -64,10 +65,10 @@ def view_static_host_list(request):
)
filter_lists = DNSFilterList.objects.all().order_by('-recommended', 'name')
messages.success(request, 'Default DNS Filter List created successfully')
messages.success(request, _('Default DNS Filter List created successfully'))
if dns_settings.pending_changes:
messages.warning(request, 'Pending Changes|There are pending DNS changes that have not been applied')
messages.warning(request, _('Pending Changes|There are pending DNS changes that have not been applied'))
context = {
'dns_settings': dns_settings,
'static_host_list': static_host_list,
@ -80,19 +81,16 @@ def view_static_host_list(request):
def view_manage_dns_settings(request):
if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=50).exists():
return render(request, 'access_denied.html', {'page_title': 'Access Denied'})
dns_settings, _ = DNSSettings.objects.get_or_create(name='dns_settings')
dns_settings, dns_settings_created = DNSSettings.objects.get_or_create(name='dns_settings')
form = DNSSettingsForm(request.POST or None, instance=dns_settings)
if form.is_valid():
form.save()
return redirect('/dns/apply_config/')
form_description_content = '''
<strong>DNS Forwarders</strong>
<p>
All DNS queries will be forwarded to the primary resolver. If the primary resolver is not available, the secondary resolver will be used.
</p>
'''
description_title = _('DNS Forwarders')
description_message = _('All DNS queries will be forwarded to the primary resolver. If the primary resolver is not available, the secondary resolver will be used.')
form_description_content = f'<strong>{description_title}</strong><p>{description_message}</p>'
context = {
'dns_settings': dns_settings,
@ -109,7 +107,7 @@ def view_manage_dns_settings(request):
def view_manage_static_host(request):
if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=40).exists():
return render(request, 'access_denied.html', {'page_title': 'Access Denied'})
dns_settings, _ = DNSSettings.objects.get_or_create(name='dns_settings')
dns_settings, dns_settings_created = DNSSettings.objects.get_or_create(name='dns_settings')
if request.GET.get('uuid'):
static_dns = get_object_or_404(StaticHost, uuid=request.GET.get('uuid'))
if request.GET.get('action') == 'delete':
@ -117,10 +115,10 @@ def view_manage_static_host(request):
static_dns.delete()
dns_settings.pending_changes = True
dns_settings.save()
messages.success(request, 'Static DNS deleted successfully')
messages.success(request, _('Static DNS deleted successfully'))
return redirect('/dns/')
else:
messages.warning(request, 'Static DNS not deleted|Invalid confirmation')
messages.warning(request, _('Static DNS not deleted|Invalid confirmation'))
return redirect('/dns/')
else:
static_dns = None
@ -130,7 +128,7 @@ def view_manage_static_host(request):
form.save()
dns_settings.pending_changes = True
dns_settings.save()
messages.success(request, 'Static DNS saved successfully')
messages.success(request, _('Static DNS saved successfully'))
return redirect('/dns/')
context = {
@ -146,27 +144,27 @@ def view_manage_filter_list(request):
if not UserAcl.objects.filter(user=request.user, user_level__gte=40).exists():
return render(request, 'access_denied.html', {'page_title': 'Access Denied'})
dns_settings, _ = DNSSettings.objects.get_or_create(name='dns_settings')
dns_settings, dns_settings_created = DNSSettings.objects.get_or_create(name='dns_settings')
if request.GET.get('uuid'):
filter_list = get_object_or_404(DNSFilterList, uuid=request.GET.get('uuid'))
if request.GET.get('action') == 'delete':
if request.GET.get('confirmation') == 'delete':
if filter_list.enabled:
messages.warning(request, 'DNS Filter List not deleted | Filter List is enabled')
messages.warning(request, _('DNS Filter List not deleted | Filter List is enabled'))
return redirect('/dns/')
file_path = os.path.join("/etc/dnsmasq/", f"{filter_list.uuid}.conf")
if os.path.exists(file_path):
try:
os.remove(file_path)
except Exception as e:
messages.error(request, f"Error removing config file: {e}")
messages.error(request, _("Error removing config file: ") + e)
return redirect('/dns/')
filter_list.delete()
messages.success(request, 'DNS Filter List deleted successfully')
messages.success(request, _('DNS Filter List deleted successfully'))
return redirect('/dns/')
else:
messages.warning(request, 'DNS Filter List not deleted | Invalid confirmation')
messages.warning(request, _('DNS Filter List not deleted | Invalid confirmation'))
return redirect('/dns/')
else:
filter_list = None
@ -176,7 +174,7 @@ def view_manage_filter_list(request):
form.save()
dns_settings.pending_changes = True
dns_settings.save()
messages.success(request, 'DNS Filter List saved successfully')
messages.success(request, _('DNS Filter List saved successfully'))
return redirect('/dns/')
context = {
@ -193,7 +191,7 @@ def view_update_dns_list(request):
return render(request, 'access_denied.html', {'page_title': 'Access Denied'})
dns_list = get_object_or_404(DNSFilterList, uuid=request.GET.get('uuid'))
dns_settings, _ = DNSSettings.objects.get_or_create(name='dns_settings')
dns_settings, dns_settings_created = DNSSettings.objects.get_or_create(name='dns_settings')
file_path = os.path.join("/etc/dnsmasq/", f"{dns_list.uuid}.conf")
old_checksum = None
@ -203,7 +201,7 @@ def view_update_dns_list(request):
old_content = f.read()
old_checksum = hashlib.sha256(old_content).hexdigest()
except Exception as e:
messages.error(request, f"Failed to read existing config file: {e}")
messages.error(request, _("Failed to read existing config file: ") + e)
if dns_list.enabled:
dns_list.enabled = False
dns_list.save()
@ -221,7 +219,7 @@ def view_update_dns_list(request):
dns_list.save()
dns_settings.pending_changes = True
dns_settings.save()
messages.error(request, f"Failed to fetch the host list: {e}")
messages.error(request, _("Failed to fetch the host list: ") + e)
return redirect('/dns/')
new_checksum = hashlib.sha256(content.encode('utf-8')).hexdigest()
@ -231,7 +229,7 @@ def view_update_dns_list(request):
with open(file_path, "w") as f:
f.write(content)
except Exception as e:
messages.error(request, f"Failed to write config file: {e}")
messages.error(request, _("Failed to write config file: ") + e)
if dns_list.enabled:
dns_list.enabled = False
dns_list.save()
@ -256,7 +254,7 @@ def view_update_dns_list(request):
# Save changes to the DNSFilterList instance.
dns_list.save()
messages.success(request, 'DNS Filter List updated successfully')
messages.success(request, _('DNS Filter List updated successfully'))
return redirect('/dns/')
@ -265,7 +263,7 @@ def view_toggle_dns_list(request):
return render(request, 'access_denied.html', {'page_title': 'Access Denied'})
dns_list = get_object_or_404(DNSFilterList, uuid=request.GET.get('uuid'))
dns_settings, _ = DNSSettings.objects.get_or_create(name='dns_settings')
dns_settings, dns_settings_created = DNSSettings.objects.get_or_create(name='dns_settings')
file_path = os.path.join("/etc/dnsmasq/", f"{dns_list.uuid}.conf")
if request.GET.get('action') == 'enable':
@ -273,12 +271,12 @@ def view_toggle_dns_list(request):
dns_list.enabled = True
dns_list.save()
export_dns_configuration()
messages.success(request, 'DNS Filter List enabled successfully')
messages.success(request, _('DNS Filter List enabled successfully'))
else:
messages.error(request, 'DNS Filter List not enabled | No valid hosts found')
messages.error(request, _('DNS Filter List not enabled | No valid hosts found'))
else:
dns_list.enabled = False
dns_list.save()
export_dns_configuration()
messages.success(request, 'DNS Filter List disabled successfully')
messages.success(request, _('DNS Filter List disabled successfully'))
return redirect('/dns/')

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-14 17:19-0300\n"
"POT-Creation-Date: 2025-04-15 10:21-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"
@ -18,6 +18,148 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: dns/forms.py:22
msgid "Primary Resolver"
msgstr "Servidor Primário"
#: dns/forms.py:23
msgid "Secondary Resolver"
msgstr "Servidor Secundário"
#: dns/forms.py:25 dns/forms.py:67 dns/forms.py:109
#: templates/wireguard/wireguard_peer_list.html:166
msgid "Back"
msgstr "Voltar"
#: dns/forms.py:29
msgid "Resolver Settings"
msgstr "Resolução de DNS"
#: dns/forms.py:37 dns/forms.py:83 dns/forms.py:134
msgid "Save"
msgstr "Salvar"
#: dns/forms.py:65 templates/dns/static_host_list.html:17
msgid "Hostname"
msgstr "Endereço do Host"
#: dns/forms.py:66 templates/dns/static_host_list.html:18
#: templates/wireguard/wireguard_status.html:45
msgid "IP Address"
msgstr "Endereço IP"
#: dns/forms.py:68 dns/forms.py:110
#: templates/wireguard/wireguard_peer_list.html:185
msgid "Delete"
msgstr "Excluir"
#: dns/forms.py:75
msgid "Static DNS"
msgstr "DNS Estático"
#: dns/forms.py:111 templates/dns/static_host_list.html:68
msgid "Name"
msgstr "Nome"
#: dns/forms.py:112 templates/dns/static_host_list.html:69
msgid "Description"
msgstr "Descrição"
#: dns/forms.py:113
msgid "List URL"
msgstr "Endereço da Lista"
#: dns/forms.py:125
msgid "DNS Filter List Details"
msgstr "Detalhes da Lista de Filtro de DNS"
#: dns/views.py:33
msgid "DNS settings applied successfully"
msgstr "Configurações de DNS aplicadas com sucesso"
#: dns/views.py:68
msgid "Default DNS Filter List created successfully"
msgstr "Lista de Filtro de DNS padrão criada com sucesso"
#: dns/views.py:71
msgid ""
"Pending Changes|There are pending DNS changes that have not been applied"
msgstr ""
"Alterações Pendentes|Há alterações de DNS pendentes que não foram aplicadas"
#: dns/views.py:90
msgid "DNS Forwarders"
msgstr "Servidores DNS"
#: dns/views.py:91
msgid ""
"All DNS queries will be forwarded to the primary resolver. If the primary "
"resolver is not available, the secondary resolver will be used."
msgstr ""
"Todas as consultas DNS serão encaminhadas para o resolvedor primário. Se o "
"resolvedor primário não estiver disponível, o resolvedor secundário será "
"usado."
#: dns/views.py:118
msgid "Static DNS deleted successfully"
msgstr "DNS Estático excluído com sucesso"
#: dns/views.py:121
msgid "Static DNS not deleted|Invalid confirmation"
msgstr "DNS Estático não excluído|Confirmação inválida"
#: dns/views.py:131
msgid "Static DNS saved successfully"
msgstr "DNS Estático salvo com sucesso"
#: dns/views.py:154
msgid "DNS Filter List not deleted | Filter List is enabled"
msgstr "Lista de Filtro de DNS não excluída | Lista de Filtro está habilitada"
#: dns/views.py:161
msgid "Error removing config file: "
msgstr "Erro ao remover o arquivo de configuração: "
#: dns/views.py:164
msgid "DNS Filter List deleted successfully"
msgstr "Lista de Filtro de DNS excluída com sucesso"
#: dns/views.py:167
msgid "DNS Filter List not deleted | Invalid confirmation"
msgstr "Lista de Filtro de DNS não excluída | Confirmação inválida"
#: dns/views.py:177
msgid "DNS Filter List saved successfully"
msgstr "Lista de Filtro de DNS salva com sucesso"
#: dns/views.py:204
msgid "Failed to read existing config file: "
msgstr "Erro ao ler o arquivo de configuração existente: "
#: dns/views.py:222
msgid "Failed to fetch the host list: "
msgstr "Erro ao buscar a lista de hosts: "
#: dns/views.py:232
msgid "Failed to write config file: "
msgstr "Falha ao escrever o arquivo de configuração: "
#: dns/views.py:257
msgid "DNS Filter List updated successfully"
msgstr "Lista de Filtro de DNS atualizada com sucesso"
#: dns/views.py:274
msgid "DNS Filter List enabled successfully"
msgstr "Lista de Filtro de DNS habilitada com sucesso"
#: dns/views.py:276
msgid "DNS Filter List not enabled | No valid hosts found"
msgstr "Lista de Filtro de DNS não habilitada | Nenhum host válido encontrado"
#: dns/views.py:281
msgid "DNS Filter List disabled successfully"
msgstr "Lista de Filtro de DNS desabilitada com sucesso"
#: intl_tools/forms.py:11 templates/accounts/login.html:36
msgid "Language"
msgstr "Idioma"
@ -61,7 +203,7 @@ msgstr "Você foi desconectado com sucesso."
msgid "Login again"
msgstr "Acessar novamente"
#: templates/base.html:112
#: templates/base.html:112 templates/dns/static_host_list.html:72
msgid "Status"
msgstr "Estado"
@ -101,6 +243,47 @@ msgstr "Atualização Disponível"
msgid "Version"
msgstr "Versão"
#: templates/dns/static_host_list.html:9
msgid "Static Host List"
msgstr "Lista de Endereços Estáticos"
#: templates/dns/static_host_list.html:45
msgid "Add"
msgstr "Adicionar"
#: templates/dns/static_host_list.html:46
msgid "Settings"
msgstr "Configurações"
#: templates/dns/static_host_list.html:47
msgid "Apply"
msgstr "Aplicar"
#: templates/dns/static_host_list.html:59
msgid "DNS Filter Lists"
msgstr "Listas de Filtro de DNS"
#: templates/dns/static_host_list.html:70
msgid "Hosts"
msgstr "Endereços"
#: templates/dns/static_host_list.html:71
msgid "Last Update"
msgstr "Última Atualização"
#: templates/dns/static_host_list.html:73
msgid "Update"
msgstr "Atualizar"
#: templates/dns/static_host_list.html:74
#: templates/wireguard/wireguard_peer_list.html:196
msgid "Edit"
msgstr "Editar"
#: templates/dns/static_host_list.html:116
msgid "Add Filter List"
msgstr "Adicionar Lista de Filtro"
#: templates/wireguard/wireguard_peer_list.html:75
#: templates/wireguard/wireguard_peer_list.html:125
msgid "Throughput"
@ -152,10 +335,6 @@ msgstr "Sem histórico de tráfego, por favor aguarde alguns minutos"
msgid "Close QR Code"
msgstr "Fechar QR Code"
#: templates/wireguard/wireguard_peer_list.html:166
msgid "Back"
msgstr "Voltar"
#: templates/wireguard/wireguard_peer_list.html:168
msgid "VPN Invite Details"
msgstr "Detalhes do Convite para VPN"
@ -180,10 +359,6 @@ msgstr "Email"
msgid "WhatsApp"
msgstr "WhatsApp"
#: templates/wireguard/wireguard_peer_list.html:185
msgid "Delete"
msgstr "Excluir"
#: templates/wireguard/wireguard_peer_list.html:192
msgid "Close"
msgstr "Fechar"
@ -196,10 +371,6 @@ msgstr "Configuração"
msgid "QR Code"
msgstr "Código QR"
#: templates/wireguard/wireguard_peer_list.html:196
msgid "Edit"
msgstr "Editar"
#: templates/wireguard/wireguard_peer_list.html:204
msgid "No WireGuard Instances Found"
msgstr "Nenhuma Instância do WireGuard Encontrada"
@ -316,10 +487,6 @@ msgstr "Recarregar o serviço Wireguard"
msgid "Instance Traffic"
msgstr "Tráfego da Instância"
#: templates/wireguard/wireguard_status.html:45
msgid "IP Address"
msgstr "Endereço IP"
#: templates/wireguard/wireguard_status.html:46
msgid "Public Address"
msgstr "Endereço Público"
@ -336,7 +503,7 @@ msgstr "Peers"
msgid "WireGuard Status"
msgstr "Estado do WireGuard"
#: wireguard_peer/views.py:49
#: wireguard_peer/views.py:50
msgid "WireGuard Peer List"
msgstr "Lista de Peers do WireGuard"

View File

@ -1,11 +1,12 @@
{% extends 'base.html' %}
{% load i18n %}
{% block content %}
<div class='row'>
<div class='col-lg-6'>
<div class="card card-primary card-outline">
<div class="card-header">
<h3 class="card-title">Static Host List</h3>
<h3 class="card-title">{% trans 'Static Host List' %}</h3>
</div>
<div class="card-body">
<div class="row">
@ -13,8 +14,8 @@
<table class="table table-hover">
<thead>
<tr>
<th>Hostname</th>
<th>IP Address</th>
<th>{% trans 'Hostname' %}</th>
<th>{% trans 'IP Address' %}</th>
<th></th>
</tr>
</thead>
@ -41,9 +42,9 @@
<div class="row">
<div class="col-lg-12">
<a href="/dns/manage_static_host/" class="btn btn-primary">Add Static Host</a>
<a href="/dns/manage_settings/" class="btn btn-primary">DNS Settings</a>
<a href="/dns/apply_config/" class="btn btn-primary">Apply Config</a>
<a href="/dns/manage_static_host/" class="btn btn-primary">{% trans 'Add' %}</a>
<a href="/dns/manage_settings/" class="btn btn-primary">{% trans 'Settings' %}</a>
<a href="/dns/apply_config/" class="btn btn-primary">{% trans 'Apply' %}</a>
</div>
</div>
</div>
@ -55,7 +56,7 @@
<div class='col-lg-12'>
<div class="card card-primary card-outline">
<div class="card-header">
<h3 class="card-title">DNS Filter Lists</h3>
<h3 class="card-title">{% trans 'DNS Filter Lists' %}</h3>
</div>
<div class="card-body">
<div class="row">
@ -64,13 +65,13 @@
<thead>
<tr>
<th class="min-width"></th>
<th>Name</th>
<th>Description</th>
<th>Hosts</th>
<th>Last Update</th>
<th class="min-width">Status</th>
<th class="min-width">Update</th>
<th class="min-width">Edit</th>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Description' %}</th>
<th>{% trans 'Hosts' %}</th>
<th>{% trans 'Last Update' %}</th>
<th class="min-width">{% trans 'Status' %}</th>
<th class="min-width">{% trans 'Update' %}</th>
<th class="min-width">{% trans 'Edit' %}</th>
</tr>
</thead>
<tbody>
@ -111,7 +112,7 @@
</div>
<div class="row">
<div class="col-lg-12">
<a href="/dns/manage_filter_list/" class="btn btn-primary">Add Filter List</a>
<a href="/dns/manage_filter_list/" class="btn btn-primary">{% trans 'Add Filter List' %}</a>
</div>
</div>
</div>