feat(domains): Registrieren zeigt Nameserver aus AutoDNS nur zur Kontrolle (h3t)
- Nameserver schreibgeschuetzt in AutoDNS-Reihenfolge, ohne Eingabe - Hinweis mit Neu-lesen-Knopf, Zusammenfassung gesperrt ohne Nameserver - createOrder sendet keine Nameserver mehr Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,7 @@ const mockCreate = vi.fn();
|
||||
const mockSubmit = vi.fn();
|
||||
const mockCancel = vi.fn();
|
||||
const mockListContacts = vi.fn();
|
||||
const mockNameServers = vi.fn();
|
||||
|
||||
vi.mock('@/lib/domains-api', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@/lib/domains-api')>();
|
||||
@@ -37,6 +38,7 @@ vi.mock('@/lib/domains-api', async (importOriginal) => {
|
||||
submitOrder: (...a: unknown[]) => mockSubmit(...a),
|
||||
cancelOrder: (...a: unknown[]) => mockCancel(...a),
|
||||
listContacts: (...a: unknown[]) => mockListContacts(...a),
|
||||
getNameServers: (...a: unknown[]) => mockNameServers(...a),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -46,7 +48,7 @@ function status(over: Partial<DomainsStatus> = {}): DomainsStatus {
|
||||
configured: true,
|
||||
demoConfigured: true,
|
||||
liveConfigured: true,
|
||||
defaultNameServers: ['ns1.example.com', 'ns2.example.com'],
|
||||
defaultNameServers: [],
|
||||
...over,
|
||||
};
|
||||
}
|
||||
@@ -122,7 +124,7 @@ function summary(over: Partial<OrderSummary> = {}): OrderSummary {
|
||||
tech: { id: 22, displayName: 'Unsere Firma GmbH' },
|
||||
zone: { id: 22, displayName: 'Unsere Firma GmbH' },
|
||||
},
|
||||
nameServers: ['ns1.example.com', 'ns2.example.com'],
|
||||
nameServers: ['z.example.net', 'b.example.org', 'a.example.org'],
|
||||
periodYears: 1,
|
||||
version: '2026-10-08T10:00:00.000Z',
|
||||
...over,
|
||||
@@ -156,6 +158,10 @@ beforeEach(() => {
|
||||
mockCreate.mockReset().mockResolvedValue(summary());
|
||||
mockSubmit.mockReset().mockResolvedValue(order({ status: 'SUBMITTED', jobStatus: 'RUNNING' }));
|
||||
mockCancel.mockReset().mockResolvedValue(order({ status: 'CANCELED' }));
|
||||
mockNameServers.mockReset().mockResolvedValue({
|
||||
environment: 'DEMO',
|
||||
nameServers: ['z.example.net', 'b.example.org', 'a.example.org'],
|
||||
});
|
||||
mockListContacts.mockReset().mockResolvedValue({
|
||||
environment: 'DEMO',
|
||||
contacts: CONTACTS,
|
||||
@@ -207,7 +213,7 @@ describe('RegisterTab — Verfuegbarkeit', () => {
|
||||
});
|
||||
|
||||
describe('RegisterTab — Kontakte und Nameserver', () => {
|
||||
it('Voreinstellung: Admin = Inhaber, Technik/Zone = Kontakt der eigenen Firma; Nameserver aus den Einstellungen', async () => {
|
||||
it('Voreinstellung: Admin = Inhaber, Technik/Zone = Kontakt der eigenen Firma', async () => {
|
||||
renderTab();
|
||||
await checkFree();
|
||||
const owner = (await screen.findByLabelText('Inhaber')) as HTMLSelectElement;
|
||||
@@ -217,12 +223,6 @@ describe('RegisterTab — Kontakte und Nameserver', () => {
|
||||
expect((screen.getByLabelText('Admin-Kontakt') as HTMLSelectElement).value).toBe('33');
|
||||
expect((screen.getByLabelText('Technischer Kontakt') as HTMLSelectElement).value).toBe('22');
|
||||
expect((screen.getByLabelText('Zonenkontakt') as HTMLSelectElement).value).toBe('22');
|
||||
expect((screen.getByLabelText('Nameserver 1') as HTMLInputElement).value).toBe(
|
||||
'ns1.example.com',
|
||||
);
|
||||
expect((screen.getByLabelText('Nameserver 2') as HTMLInputElement).value).toBe(
|
||||
'ns2.example.com',
|
||||
);
|
||||
});
|
||||
|
||||
it('ohne Kontakt der eigenen Firma folgen Technik und Zone dem Inhaber', async () => {
|
||||
@@ -245,18 +245,67 @@ describe('RegisterTab — Kontakte und Nameserver', () => {
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('Nameserver lassen sich zwischen 2 und 6 hinzufuegen und entfernen', async () => {
|
||||
renderTab({ defaultNameServers: [] });
|
||||
it('zeigt die AutoDNS-Nameserver schreibgeschuetzt in AutoDNS-Reihenfolge', async () => {
|
||||
renderTab();
|
||||
await checkFree();
|
||||
await screen.findByLabelText('Inhaber');
|
||||
expect(screen.queryByRole('button', { name: 'Entfernen' })).toBeNull();
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Nameserver hinzufügen' }));
|
||||
}
|
||||
const items = await screen.findAllByRole('listitem');
|
||||
expect(items.map((li) => li.textContent)).toEqual([
|
||||
'Nameserver 1z.example.net',
|
||||
'Nameserver 2b.example.org',
|
||||
'Nameserver 3a.example.org',
|
||||
]);
|
||||
expect(screen.queryByLabelText('Nameserver 1')).toBeNull();
|
||||
expect(screen.queryByRole('textbox', { name: /Nameserver/ })).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: 'Nameserver hinzufügen' })).toBeNull();
|
||||
expect(screen.getByLabelText('Nameserver 6')).toBeTruthy();
|
||||
fireEvent.click(screen.getAllByRole('button', { name: 'Entfernen' })[0]);
|
||||
expect(screen.queryByLabelText('Nameserver 6')).toBeNull();
|
||||
});
|
||||
|
||||
it('keine Nameserver in AutoDNS: Hinweis, Zusammenfassung gesperrt, kein Entwurf', async () => {
|
||||
mockNameServers.mockRejectedValue(
|
||||
new DomainsRequestError(409, 'noDefaultNameServers', 'Serverseitiger Text.'),
|
||||
);
|
||||
renderTab();
|
||||
expect((await screen.findByRole('alert')).textContent).toContain(
|
||||
'In AutoDNS sind keine Standard-Nameserver hinterlegt',
|
||||
);
|
||||
await checkFree();
|
||||
const owner = await screen.findByLabelText('Inhaber');
|
||||
await waitFor(() => expect(mockListContacts).toHaveBeenCalled());
|
||||
fireEvent.change(owner, { target: { value: '11' } });
|
||||
const button = screen.getByRole('button', {
|
||||
name: 'Zusammenfassung anzeigen',
|
||||
}) as HTMLButtonElement;
|
||||
expect(button.disabled).toBe(true);
|
||||
fireEvent.click(button);
|
||||
expect(mockCreate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('AutoDNS nicht lesbar: Hinweis mit Servertext; "Erneut aus AutoDNS lesen" schaltet frei', async () => {
|
||||
mockNameServers.mockRejectedValueOnce(
|
||||
new DomainsRequestError(502, 'autodnsAuth', 'Anmeldung bei AutoDNS fehlgeschlagen.'),
|
||||
);
|
||||
renderTab();
|
||||
const alert = await screen.findByRole('alert');
|
||||
expect(alert.textContent).toContain(
|
||||
'Tessera konnte die Standard-Nameserver nicht aus AutoDNS lesen',
|
||||
);
|
||||
expect(alert.textContent).toContain('Anmeldung bei AutoDNS fehlgeschlagen.');
|
||||
await checkFree();
|
||||
const owner = await screen.findByLabelText('Inhaber');
|
||||
await waitFor(() => expect(mockListContacts).toHaveBeenCalled());
|
||||
fireEvent.change(owner, { target: { value: '11' } });
|
||||
expect(
|
||||
(screen.getByRole('button', { name: 'Zusammenfassung anzeigen' }) as HTMLButtonElement)
|
||||
.disabled,
|
||||
).toBe(true);
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Erneut aus AutoDNS lesen' }));
|
||||
await waitFor(() => expect(mockNameServers).toHaveBeenCalledTimes(2));
|
||||
await screen.findByText('z.example.net');
|
||||
expect(screen.queryByRole('alert')).toBeNull();
|
||||
expect(
|
||||
(screen.getByRole('button', { name: 'Zusammenfassung anzeigen' }) as HTMLButtonElement)
|
||||
.disabled,
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -270,14 +319,13 @@ describe('RegisterTab — Zusammenfassung und verbindliche Bestaetigung', () =>
|
||||
adminContactId: 11,
|
||||
techContactId: 22,
|
||||
zoneContactId: 22,
|
||||
nameServers: ['ns1.example.com', 'ns2.example.com'],
|
||||
});
|
||||
expect(screen.getByTestId('domains-environment-badge').textContent).toBe(
|
||||
'Demo-System (Testbetrieb)',
|
||||
);
|
||||
expect(screen.getByText('1 Jahr')).toBeTruthy();
|
||||
expect(screen.getByText(/4,90/)).toBeTruthy();
|
||||
expect(screen.getByText('ns1.example.com, ns2.example.com')).toBeTruthy();
|
||||
expect(screen.getByText('z.example.net, b.example.org, a.example.org')).toBeTruthy();
|
||||
expect(
|
||||
screen.getByText('Ich bestätige die Registrierung im Demo-System von AutoDNS (Testbetrieb).'),
|
||||
).toBeTruthy();
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
type DomainsOrder,
|
||||
DomainsRequestError,
|
||||
type DomainsStatus,
|
||||
getNameServers,
|
||||
listContacts,
|
||||
type OrderPrice,
|
||||
type OrderSummary,
|
||||
@@ -24,7 +25,13 @@ import {
|
||||
import { EnvironmentBadge } from './EnvironmentBadge';
|
||||
|
||||
const MIN_NAMESERVERS = 2;
|
||||
const MAX_NAMESERVERS = 6;
|
||||
|
||||
/** Standard-Nameserver aus AutoDNS: wird gelesen, ist da, fehlt dort oder liess sich nicht lesen. */
|
||||
type NameServerState =
|
||||
| { kind: 'loading' }
|
||||
| { kind: 'ok'; list: string[] }
|
||||
| { kind: 'missing' }
|
||||
| { kind: 'unreadable'; detail: string };
|
||||
|
||||
type Role = 'owner' | 'admin' | 'tech' | 'zone';
|
||||
const ROLES: Role[] = ['owner', 'admin', 'tech', 'zone'];
|
||||
@@ -39,15 +46,12 @@ export function formatPrice(price: OrderPrice, locale: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
function initialNameServers(defaults: string[]): string[] {
|
||||
const list = defaults.slice(0, MAX_NAMESERVERS);
|
||||
while (list.length < MIN_NAMESERVERS) list.push('');
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reiter "Registrieren" (L-04): Verfuegbarkeit -> Kontakte und Nameserver ->
|
||||
* Zusammenfassung -> verbindliche Bestaetigung. Der Knopf "Jetzt verbindlich
|
||||
* Reiter "Registrieren" (L-04): Verfuegbarkeit -> Kontakte (Nameserver nur zur
|
||||
* Kontrolle) -> Zusammenfassung -> verbindliche Bestaetigung. Die Nameserver
|
||||
* stammen aus dem AutoDNS-Benutzerprofil, werden schreibgeschuetzt gezeigt und
|
||||
* vom Server beim Entwurf selbst gelesen; fehlen sie, ist die Registrierung
|
||||
* gesperrt (h3t). Der Knopf "Jetzt verbindlich
|
||||
* registrieren" ist nur Komfort-Schutz gegen Doppelklick (`useRef` sperrt noch
|
||||
* vor dem naechsten Zeichnen); die eigentliche Sperre ist der atomare Anspruch
|
||||
* auf dem Server. Nach einem Fehler beim Abschicken bleibt der Knopf gesperrt,
|
||||
@@ -75,9 +79,8 @@ export function RegisterTab({
|
||||
const [contacts, setContacts] = useState<DomainsContact[] | null>(null);
|
||||
const [contactsLoading, setContactsLoading] = useState(false);
|
||||
const [chosen, setChosen] = useState<Partial<Record<Role, number>>>({});
|
||||
const [nameServers, setNameServers] = useState<string[]>(() =>
|
||||
initialNameServers(status.defaultNameServers),
|
||||
);
|
||||
const [nameServerState, setNameServerState] = useState<NameServerState>({ kind: 'loading' });
|
||||
const [nameServerReload, setNameServerReload] = useState(0);
|
||||
|
||||
const [creating, setCreating] = useState(false);
|
||||
const [summary, setSummary] = useState<OrderSummary | null>(null);
|
||||
@@ -110,6 +113,31 @@ export function RegisterTab({
|
||||
};
|
||||
}, [available, contacts, tc]);
|
||||
|
||||
// Standard-Nameserver aus AutoDNS lesen: beim Oeffnen, beim Systemwechsel und auf Wunsch.
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: Systemwechsel und Neuladen loesen das Lesen bewusst aus
|
||||
useEffect(() => {
|
||||
let alive = true;
|
||||
setNameServerState({ kind: 'loading' });
|
||||
getNameServers()
|
||||
.then((res) => {
|
||||
if (alive) setNameServerState({ kind: 'ok', list: res.nameServers });
|
||||
})
|
||||
.catch((e) => {
|
||||
if (!alive) return;
|
||||
if (e instanceof DomainsRequestError && e.code === 'noDefaultNameServers') {
|
||||
setNameServerState({ kind: 'missing' });
|
||||
} else {
|
||||
setNameServerState({
|
||||
kind: 'unreadable',
|
||||
detail: e instanceof DomainsRequestError ? e.message : tc('requestFailed'),
|
||||
});
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
alive = false;
|
||||
};
|
||||
}, [status.environment, nameServerReload, tc]);
|
||||
|
||||
const ownCompanyId = customers.find((c) => c.isOwnCompany)?.id ?? null;
|
||||
const ownCompanyContact = useMemo(
|
||||
() => (ownCompanyId ? contacts?.find((c) => c.customerId === ownCompanyId) : undefined),
|
||||
@@ -127,12 +155,12 @@ export function RegisterTab({
|
||||
|
||||
const groups = useMemo(() => groupByCustomer(contacts ?? [], customers), [contacts, customers]);
|
||||
|
||||
const filledNameServers = nameServers.map((n) => n.trim()).filter((n) => n.length > 0);
|
||||
const contactIds = ROLES.map(effective);
|
||||
const canSummarize =
|
||||
available &&
|
||||
contactIds.every((id) => id !== null) &&
|
||||
filledNameServers.length >= MIN_NAMESERVERS &&
|
||||
nameServerState.kind === 'ok' &&
|
||||
nameServerState.list.length >= MIN_NAMESERVERS &&
|
||||
!creating;
|
||||
|
||||
function resetAll() {
|
||||
@@ -141,7 +169,6 @@ export function RegisterTab({
|
||||
setAvailability(null);
|
||||
setError(null);
|
||||
setChosen({});
|
||||
setNameServers(initialNameServers(status.defaultNameServers));
|
||||
setSummary(null);
|
||||
setConfirmed(false);
|
||||
setSubmitting(false);
|
||||
@@ -176,7 +203,6 @@ export function RegisterTab({
|
||||
adminContactId,
|
||||
techContactId,
|
||||
zoneContactId,
|
||||
nameServers: filledNameServers,
|
||||
}),
|
||||
);
|
||||
setConfirmed(false);
|
||||
@@ -348,6 +374,25 @@ export function RegisterTab({
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{(nameServerState.kind === 'missing' || nameServerState.kind === 'unreadable') && (
|
||||
<div role="alert" className="rounded-lg border border-destructive/40 p-4 text-sm">
|
||||
<p className="text-foreground">
|
||||
{nameServerState.kind === 'missing'
|
||||
? t('nameServersMissing')
|
||||
: t('nameServersUnreadable')}
|
||||
</p>
|
||||
{nameServerState.kind === 'unreadable' && (
|
||||
<p className="mt-1 text-muted-foreground">{nameServerState.detail}</p>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className={`${SECONDARY_BUTTON} mt-3`}
|
||||
onClick={() => setNameServerReload((n) => n + 1)}
|
||||
>
|
||||
{t('nameServersRetry')}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<SettingsSection title={t('domainLabel')} description={t('intro')}>
|
||||
<div className="flex flex-wrap items-end gap-3">
|
||||
<div className="min-w-56 flex-1">
|
||||
@@ -472,45 +517,24 @@ export function RegisterTab({
|
||||
</button>
|
||||
}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
{nameServers.map((value, index) => {
|
||||
const label = t('nameServer', { number: index + 1 });
|
||||
return (
|
||||
// biome-ignore lint/suspicious/noArrayIndexKey: feste, nummerierte Eingabefelder
|
||||
<div key={index} className="flex items-center gap-2">
|
||||
<input
|
||||
type="text"
|
||||
aria-label={label}
|
||||
className={INPUT_CLASS}
|
||||
value={value}
|
||||
onChange={(e) =>
|
||||
setNameServers((prev) =>
|
||||
prev.map((n, i) => (i === index ? e.target.value : n)),
|
||||
)
|
||||
}
|
||||
/>
|
||||
{nameServers.length > MIN_NAMESERVERS && (
|
||||
<button
|
||||
type="button"
|
||||
className={SECONDARY_BUTTON}
|
||||
onClick={() => setNameServers((prev) => prev.filter((_, i) => i !== index))}
|
||||
>
|
||||
{t('removeNameServer')}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{nameServers.length < MAX_NAMESERVERS && (
|
||||
<button
|
||||
type="button"
|
||||
className={SECONDARY_BUTTON}
|
||||
onClick={() => setNameServers((prev) => [...prev, ''])}
|
||||
>
|
||||
{t('addNameServer')}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{nameServerState.kind === 'loading' && (
|
||||
<p className="text-sm text-muted-foreground">{t('nameServersLoading')}</p>
|
||||
)}
|
||||
{nameServerState.kind === 'ok' && (
|
||||
<ol className="space-y-1 text-sm">
|
||||
{nameServerState.list.map((host, index) => (
|
||||
<li key={host} className="flex gap-3">
|
||||
<span className="w-28 text-muted-foreground">
|
||||
{t('nameServer', { number: index + 1 })}
|
||||
</span>
|
||||
<span className="text-foreground">{host}</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
)}
|
||||
{(nameServerState.kind === 'missing' || nameServerState.kind === 'unreadable') && (
|
||||
<p className="text-sm text-muted-foreground">{t('nameServersBlocked')}</p>
|
||||
)}
|
||||
</SettingsSection>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -314,9 +314,20 @@ export interface CreateOrderInput {
|
||||
adminContactId: number;
|
||||
techContactId: number;
|
||||
zoneContactId: number;
|
||||
// Die Nameserver liest der Server selbst aus dem AutoDNS-Profil (h3t).
|
||||
}
|
||||
|
||||
/** Standard-Nameserver aus dem AutoDNS-Benutzerprofil, in der Reihenfolge von AutoDNS. */
|
||||
export interface DomainsNameServers {
|
||||
environment: DomainsEnvironment;
|
||||
nameServers: string[];
|
||||
}
|
||||
|
||||
/** Liest die Standard-Nameserver aus AutoDNS (nur zur Anzeige; der Server liest sie beim Entwurf neu). */
|
||||
export function getNameServers(): Promise<DomainsNameServers> {
|
||||
return request<DomainsNameServers>('/name-servers');
|
||||
}
|
||||
|
||||
export function checkAvailability(domain: string): Promise<AvailabilityResult> {
|
||||
return request<AvailabilityResult>('/availability', { method: 'POST', json: { domain } });
|
||||
}
|
||||
|
||||
@@ -2209,7 +2209,7 @@
|
||||
"confirmDeleteYes": "Endgültig löschen"
|
||||
},
|
||||
"register": {
|
||||
"intro": "Prüfen Sie, ob eine Domain frei ist, wählen Sie die Kontakte und Nameserver und registrieren Sie die Domain verbindlich bei AutoDNS.",
|
||||
"intro": "Prüfen Sie, ob eine Domain frei ist, wählen Sie die Kontakte und registrieren Sie die Domain verbindlich bei AutoDNS. Die Nameserver übernimmt Tessera aus AutoDNS.",
|
||||
"domainLabel": "Domain",
|
||||
"domainPlaceholder": "beispiel.de",
|
||||
"check": "Verfügbarkeit prüfen",
|
||||
@@ -2231,10 +2231,13 @@
|
||||
"zone": "Zonenkontakt"
|
||||
},
|
||||
"nameServersTitle": "Nameserver",
|
||||
"nameServersDescription": "Mindestens zwei, höchstens sechs. Die Nameserver müssen bei Ihrem Anbieter bereits eingerichtet sein, sonst scheitert die Registrierung.",
|
||||
"nameServersDescription": "Diese Standard-Nameserver sind in AutoDNS hinterlegt. Tessera verwendet sie unverändert und in dieser Reihenfolge; ändern lassen sie sich nur in AutoDNS.",
|
||||
"nameServer": "Nameserver {number}",
|
||||
"addNameServer": "Nameserver hinzufügen",
|
||||
"removeNameServer": "Entfernen",
|
||||
"nameServersLoading": "Nameserver werden aus AutoDNS gelesen …",
|
||||
"nameServersMissing": "In AutoDNS sind keine Standard-Nameserver hinterlegt. Bitte hinterlegen Sie mindestens zwei Nameserver als Standard in AutoDNS. Bis dahin ist keine Registrierung möglich.",
|
||||
"nameServersUnreadable": "Tessera konnte die Standard-Nameserver nicht aus AutoDNS lesen. Bis das gelingt, ist keine Registrierung möglich.",
|
||||
"nameServersRetry": "Erneut aus AutoDNS lesen",
|
||||
"nameServersBlocked": "Ohne Standard-Nameserver aus AutoDNS ist keine Registrierung möglich – siehe Hinweis oben.",
|
||||
"showSummary": "Zusammenfassung anzeigen",
|
||||
"creating": "Wird vorbereitet …",
|
||||
"summary": {
|
||||
|
||||
@@ -2209,7 +2209,7 @@
|
||||
"confirmDeleteYes": "Delete permanently"
|
||||
},
|
||||
"register": {
|
||||
"intro": "Check whether a domain is available, choose the contacts and name servers, and register the domain with AutoDNS as a binding order.",
|
||||
"intro": "Check whether a domain is available, choose the contacts, and register the domain with AutoDNS as a binding order. Tessera takes the name servers from AutoDNS.",
|
||||
"domainLabel": "Domain",
|
||||
"domainPlaceholder": "example.com",
|
||||
"check": "Check availability",
|
||||
@@ -2231,10 +2231,13 @@
|
||||
"zone": "Zone contact"
|
||||
},
|
||||
"nameServersTitle": "Name servers",
|
||||
"nameServersDescription": "At least two, at most six. The name servers must already be set up with your provider, otherwise the registration fails.",
|
||||
"nameServersDescription": "These default name servers are stored in AutoDNS. Tessera uses them unchanged and in this order; they can only be changed in AutoDNS.",
|
||||
"nameServer": "Name server {number}",
|
||||
"addNameServer": "Add name server",
|
||||
"removeNameServer": "Remove",
|
||||
"nameServersLoading": "Reading name servers from AutoDNS …",
|
||||
"nameServersMissing": "No default name servers are stored in AutoDNS. Please store at least two name servers as the default in AutoDNS. Until then, registration is not possible.",
|
||||
"nameServersUnreadable": "Tessera could not read the default name servers from AutoDNS. Until that works, registration is not possible.",
|
||||
"nameServersRetry": "Read from AutoDNS again",
|
||||
"nameServersBlocked": "Without default name servers from AutoDNS, registration is not possible – see the notice above.",
|
||||
"showSummary": "Show summary",
|
||||
"creating": "Preparing …",
|
||||
"summary": {
|
||||
|
||||
Reference in New Issue
Block a user