Skip to content

Commit 3df3d9e

Browse files
Merge pull request #29 from Netflix-Database/copilot/add-translations-profile-page
2 parents 79d16b1 + 39c87a3 commit 3df3d9e

6 files changed

Lines changed: 275 additions & 112 deletions

File tree

Assets/js/profile.js

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { getCountries } from './data/countries';
3131
import { languages } from './data/languages';
3232
import { createDialog, initDialog } from './dialog';
3333
import './settings/device';
34-
import { initLocalization } from './util/localization';
34+
import { applyLocalization, initLocalization } from './util/localization';
3535
import { validateMfaToken, validatePw } from './util/validation';
3636

3737
let currentUser;
@@ -231,12 +231,14 @@ LoginManager.isLoggedIn().then(async (e) => {
231231
if (currentUser['2fa'] && currentUser['2faType'] === 'App') document.getElementById('cp_2fa').classList.remove('d-none');
232232

233233
if (currentUser['2fa']) {
234-
document.getElementById('2fa_status').innerText = 'Enabled';
234+
document.getElementById('2fa_status').innerText = i18next.t('profile_enabled');
235235
document.getElementById('2fa_type').value = currentUser['2faType'] === 'App' ? 0 : currentUser['2faType'] === 'Mail' ? 1 : 2;
236236
document.getElementById('2fa_type').disabled = true;
237-
document.getElementById('2fa_enable').innerText = 'Disable';
237+
document.getElementById('2fa_enable').innerText = i18next.t('profile_disable');
238238
document.getElementById('2fa_enable').addEventListener('click', disable2fa);
239239
} else {
240+
document.getElementById('2fa_status').innerText = i18next.t('profile_disabled');
241+
document.getElementById('2fa_enable').innerText = i18next.t('profile_enable');
240242
document.getElementById('2fa_enable').addEventListener('click', enable2fa);
241243
}
242244

@@ -269,7 +271,7 @@ LoginManager.isLoggedIn().then(async (e) => {
269271
name.innerText = client.name;
270272
row.appendChild(name);
271273
const deleteBtn = document.createElement('button');
272-
deleteBtn.innerText = 'Delete';
274+
deleteBtn.innerText = i18next.t('profile_delete');
273275
deleteBtn.addEventListener('click', async () => await deleteTrustedSsoClient(client.id));
274276
row.appendChild(deleteBtn);
275277
document.getElementById('thirdPartyAppsContainer').appendChild(row);
@@ -313,24 +315,24 @@ async function buildPasskeys(keys) {
313315
itemText.appendChild(keyElement);
314316

315317
const lastLogin = document.createElement('p');
316-
lastLogin.innerText = `Last login: ${new Date(key.lastLogin).toLocaleString()}`;
318+
lastLogin.innerText = `${i18next.t('profile_lastLogin')} ${new Date(key.lastLogin).toLocaleString()}`;
317319
itemText.appendChild(lastLogin);
318320

319321
const createdAt = document.createElement('p');
320-
createdAt.innerText = `Created at: ${new Date(key.createdAt).toLocaleString()}`;
322+
createdAt.innerText = `${i18next.t('profile_createdAt')} ${new Date(key.createdAt).toLocaleString()}`;
321323
itemText.appendChild(createdAt);
322324

323325
item.appendChild(itemText);
324326

325327
const deleteBtn = document.createElement('button');
326-
deleteBtn.innerText = 'Delete';
328+
deleteBtn.innerText = i18next.t('profile_delete');
327329
deleteBtn.addEventListener('click', async () => await deletePasskey(key.id));
328330
item.appendChild(deleteBtn);
329331

330332
container.appendChild(item);
331333
});
332334

333-
if (keys.length === 0) container.innerHTML = '<p>No passkeys found!</p>';
335+
if (keys.length === 0) container.innerHTML = `<p>${i18next.t('profile_noPasskeys')}</p>`;
334336

335337
document.getElementById('createPasskey').onclick = async () => await createPasskey();
336338
}
@@ -342,7 +344,7 @@ async function deletePasskey(id) {
342344

343345
const container = document.getElementById('passkeysTable');
344346

345-
if (container.children.length === 0) container.innerHTML = '<p>No passkeys found!</p>';
347+
if (container.children.length === 0) container.innerHTML = `<p>${i18next.t('profile_noPasskeys')}</p>`;
346348
}
347349

348350
async function createPasskey() {
@@ -383,7 +385,7 @@ async function deleteTrustedSsoClient(clientId) {
383385

384386
const container = document.getElementById('thirdPartyAppsContainer');
385387

386-
if (container.children.length === 0) container.innerHTML = '<p>No third party apps connected!</p>';
388+
if (container.children.length === 0) container.innerHTML = `<p>${i18next.t('profile_noThirdPartyApps')}</p>`;
387389
}
388390

389391
async function createSsoCredentials() {
@@ -460,6 +462,8 @@ function createSSOClient(logoUrl, clientName, websiteUrl, clientId, clientSecret
460462
content.querySelector('#sso_addRedirect').addEventListener('click', async () => await addSSORedirect(clientId));
461463
content.querySelector('#sso_addAudience').addEventListener('click', async () => await addAudience(clientId));
462464

465+
applyLocalization(item);
466+
463467
const audiencesContainer = content.querySelector('#sso_audiences');
464468

465469
audiences.forEach((audience) => {
@@ -473,7 +477,7 @@ function createSSOClient(logoUrl, clientName, websiteUrl, clientId, clientSecret
473477
audienceItem.appendChild(audienceInput);
474478

475479
const deleteBtn = document.createElement('button');
476-
deleteBtn.innerText = 'Delete';
480+
deleteBtn.innerText = i18next.t('profile_delete');
477481
deleteBtn.addEventListener('click', async () => await deleteAudience(clientId, audience.id));
478482
audienceItem.appendChild(deleteBtn);
479483

@@ -493,7 +497,7 @@ function createSSOClient(logoUrl, clientName, websiteUrl, clientId, clientSecret
493497
redirectItem.appendChild(url);
494498

495499
const deleteBtn = document.createElement('button');
496-
deleteBtn.innerText = 'Delete';
500+
deleteBtn.innerText = i18next.t('profile_delete');
497501
deleteBtn.addEventListener('click', async () => await deleteSSORedirect(clientId, redirect.id));
498502
redirectItem.appendChild(deleteBtn);
499503

@@ -563,7 +567,7 @@ async function addAudience(clientId) {
563567
url.disabled = true;
564568
redirect.appendChild(url);
565569
const deleteBtn = document.createElement('button');
566-
deleteBtn.innerText = 'Delete';
570+
deleteBtn.innerText = i18next.t('profile_delete');
567571
deleteBtn.addEventListener('click', async () => await deleteAudienceReq(clientId, res.data.id));
568572
redirect.appendChild(deleteBtn);
569573

@@ -599,7 +603,7 @@ async function addSSORedirect(clientId) {
599603
url.disabled = true;
600604
redirect.appendChild(url);
601605
const deleteBtn = document.createElement('button');
602-
deleteBtn.innerText = 'Delete';
606+
deleteBtn.innerText = i18next.t('profile_delete');
603607
deleteBtn.addEventListener('click', async () => await deleteSSORedirect(clientId, res.data.id));
604608
redirect.appendChild(deleteBtn);
605609

@@ -632,11 +636,11 @@ async function doubleClickButton(e, func) {
632636
}
633637

634638
e.target.dataset.clicked = 'true';
635-
e.target.innerText = 'Confirm';
639+
e.target.innerText = i18next.t('profile_confirm');
636640

637641
setTimeout(() => {
638642
e.target.dataset.clicked = 'false';
639-
e.target.innerText = 'Delete Account';
643+
e.target.innerText = i18next.t('profile_deleteAccount');
640644
}, 3000);
641645
}
642646

@@ -647,8 +651,8 @@ function createApiKeyRow(label, client_id, scope) {
647651
const td = document.createElement('td');
648652
const deleteBtn = document.createElement('button');
649653
const regenBtn = document.createElement('button');
650-
deleteBtn.innerText = 'Delete';
651-
regenBtn.innerText = 'Regenerate';
654+
deleteBtn.innerText = i18next.t('profile_delete');
655+
regenBtn.innerText = i18next.t('profile_regenerate');
652656

653657
deleteBtn.addEventListener('click', () => deleteApiKey(client_id));
654658
regenBtn.addEventListener('click', () => regenerateApiKey(client_id));

Assets/js/settings/device.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import i18next from 'i18next';
12
import { deleteDevice } from '../data/auth/deleteDevice';
23
import { getDevices } from '../data/auth/getDevices';
34
import { logoutAllDevices } from '../data/auth/logoutAllDevices';
@@ -37,7 +38,7 @@ function createDevices(devices) {
3738

3839
if (devices.length === 0) {
3940
const noDevices = document.createElement('p');
40-
noDevices.innerText = 'No devices found.';
41+
noDevices.innerText = i18next.t('profile_noDevices');
4142
document.getElementById('devicesContainer').appendChild(noDevices);
4243
return;
4344
}
@@ -48,14 +49,14 @@ function createDevices(devices) {
4849
const name = document.createElement('h1');
4950
name.innerText = `${device.os} ${device.browser}`;
5051

51-
if (device.isCurrentDevice === true) name.innerText += ' (Current Device)';
52+
if (device.isCurrentDevice === true) name.innerText += ` ${i18next.t('profile_currentDevice')}`;
5253

5354
row.appendChild(name);
5455
const lastUsed = document.createElement('p');
55-
lastUsed.innerText = `Last used: ${new Date(device.lastLogin).toLocaleString()}`;
56+
lastUsed.innerText = `${i18next.t('profile_lastUsed')} ${new Date(device.lastLogin).toLocaleString()}`;
5657
row.appendChild(lastUsed);
5758
const logoutBtn = document.createElement('button');
58-
logoutBtn.innerText = 'Logout';
59+
logoutBtn.innerText = i18next.t('profile_logout');
5960
logoutBtn.addEventListener('click', async () => {
6061
await logoutDevice(device.id);
6162

@@ -67,7 +68,7 @@ function createDevices(devices) {
6768
row.appendChild(logoutBtn);
6869

6970
const deleteBtn = document.createElement('button');
70-
deleteBtn.innerText = 'Delete';
71+
deleteBtn.innerText = i18next.t('profile_delete');
7172
deleteBtn.addEventListener('click', async () => {
7273
await deleteDevice(device.id);
7374

Assets/js/util/localization.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function initLocalization() {
3535

3636
export function applyLocalization(area = document) {
3737
area.querySelectorAll('[i18n]').forEach((element) => {
38-
element.innerText = i18next.t(element.getAttribute('i18n')) + element.innerText;
38+
element.innerText = i18next.t(element.getAttribute('i18n'));
3939
});
4040

4141
area.querySelectorAll('[i18n-placeholder]').forEach((element) => {

Assets/locales/de.json

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,85 @@
11
{
2-
"lang": "Deutsch"
2+
"lang": "Deutsch",
3+
"brand": "Netdb",
4+
"login": "Anmelden",
5+
"productsTitle": "Produkte",
6+
"products": {},
7+
"status": "Status",
8+
"services": "Dienste",
9+
"contact": "Kontakt",
10+
"profile_back": "Zurück",
11+
"profile_accountManagement": "Kontoverwaltung",
12+
"profile_general": "Allgemein",
13+
"profile_personalInformation": "Persönliche Informationen",
14+
"profile_password": "Passwort",
15+
"profile_connectedAccounts": "Verknüpfte Konten",
16+
"profile_security": "Sicherheit",
17+
"profile_twoFactorAuth": "Zwei-Faktor-Authentifizierung",
18+
"profile_passkeys": "Passkeys",
19+
"profile_myDevices": "Meine Geräte",
20+
"profile_thirdPartyApps": "Drittanbieter-Apps",
21+
"profile_developer": "Entwickler",
22+
"profile_apiKeys": "API-Schlüssel",
23+
"profile_ssoCredentials": "SSO-Anmeldedaten", "profile_logout": "Abmelden",
24+
"profile_deleteAccount": "Konto löschen",
25+
"profile_dangerZone": "Gefahrenzone",
26+
"profile_disconnect": "Trennen",
27+
"profile_save": "Speichern",
28+
"profile_delete": "Löschen",
29+
"profile_create": "Erstellen",
30+
"profile_confirm": "Bestätigen",
31+
"profile_createNew": "Neu erstellen",
32+
"profile_add": "Hinzufügen",
33+
"profile_regenerate": "Neu generieren",
34+
"profile_status": "Status:",
35+
"profile_type": "Typ:",
36+
"profile_disabled": "Deaktiviert",
37+
"profile_enabled": "Aktiviert",
38+
"profile_authenticator": "Authenticator",
39+
"profile_emailType": "E-Mail",
40+
"profile_selectType": "Bitte Typ auswählen",
41+
"profile_enable": "Aktivieren",
42+
"profile_disable": "Deaktivieren",
43+
"profile_createPasskey": "Passkey erstellen",
44+
"profile_logoutAllDevices": "Alle Geräte abmelden",
45+
"profile_noThirdPartyApps": "Keine Drittanbieter-Apps verbunden!",
46+
"profile_label": "Bezeichnung",
47+
"profile_key": "Schlüssel",
48+
"profile_scope": "Bereich",
49+
"profile_actions": "Aktionen",
50+
"profile_singleSignOn": "Single Sign-On-Anmeldedaten",
51+
"profile_noSsoClients": "Keine SSO-Clients gefunden!",
52+
"profile_clientId": "Client-ID",
53+
"profile_clientSecret": "Client-Geheimnis",
54+
"profile_logoUrl": "Logo-URL",
55+
"profile_websiteUrl": "Website-URL",
56+
"profile_name": "Name",
57+
"profile_audiences": "Zielgruppen",
58+
"profile_redirects": "Weiterleitungen",
59+
"profile_createSsoClient": "Neuen SSO-Client erstellen",
60+
"profile_warning": "Warnung:",
61+
"profile_dangerWarning": "Das Löschen Ihres Kontos ist unwiderruflich. Alle Ihre Daten werden gelöscht und können nicht wiederhergestellt werden.",
62+
"profile_noPasskeys": "Keine Passkeys gefunden!",
63+
"profile_lastLogin": "Letzter Login:",
64+
"profile_createdAt": "Erstellt am:",
65+
"profile_currentDevice": "(Aktuelles Gerät)",
66+
"profile_noDevices": "Keine Geräte gefunden.",
67+
"profile_lastUsed": "Zuletzt verwendet:",
68+
"profile_placeholder_email": "E-Mail",
69+
"profile_placeholder_username": "Benutzername",
70+
"profile_placeholder_firstname": "Vorname",
71+
"profile_placeholder_lastname": "Nachname",
72+
"profile_placeholder_country": "Land",
73+
"profile_placeholder_preferredLanguage": "Bevorzugte Sprache",
74+
"profile_placeholder_oldPassword": "Altes Passwort",
75+
"profile_placeholder_newPassword": "Neues Passwort",
76+
"profile_placeholder_repeatPassword": "Passwort wiederholen",
77+
"profile_placeholder_2faToken": "2FA-Token",
78+
"profile_placeholder_label": "Bezeichnung",
79+
"profile_placeholder_scope": "Bereich",
80+
"profile_placeholder_password": "Passwort",
81+
"profile_placeholder_mfaToken": "MFA-Token",
82+
"profile_placeholder_name": "Name",
83+
"profile_placeholder_url": "URL",
84+
"profile_placeholder_logoUrl": "Logo-URL"
385
}

Assets/locales/en.json

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,81 @@
88
},
99
"status": "Status",
1010
"services": "Services",
11-
"contact": "Contact Us"
11+
"contact": "Contact Us",
12+
"profile_back": "Back",
13+
"profile_accountManagement": "Account Management",
14+
"profile_general": "General",
15+
"profile_personalInformation": "Personal Information",
16+
"profile_password": "Password",
17+
"profile_connectedAccounts": "Connected Accounts",
18+
"profile_security": "Security",
19+
"profile_twoFactorAuth": "Two Factor Authentication",
20+
"profile_passkeys": "Passkeys",
21+
"profile_myDevices": "My Devices",
22+
"profile_thirdPartyApps": "Third Party Apps",
23+
"profile_developer": "Developer",
24+
"profile_apiKeys": "API Keys",
25+
"profile_ssoCredentials": "SSO Credentials",
26+
"profile_logout": "Logout",
27+
"profile_deleteAccount": "Delete Account",
28+
"profile_dangerZone": "Danger Zone",
29+
"profile_disconnect": "Disconnect",
30+
"profile_save": "Save",
31+
"profile_delete": "Delete",
32+
"profile_create": "Create",
33+
"profile_confirm": "Confirm",
34+
"profile_createNew": "Create new",
35+
"profile_add": "Add",
36+
"profile_regenerate": "Regenerate",
37+
"profile_status": "Status:",
38+
"profile_type": "Type:",
39+
"profile_disabled": "Disabled",
40+
"profile_enabled": "Enabled",
41+
"profile_authenticator": "Authenticator",
42+
"profile_emailType": "Email",
43+
"profile_selectType": "Please select a type",
44+
"profile_enable": "Enable",
45+
"profile_disable": "Disable",
46+
"profile_createPasskey": "Create Passkey",
47+
"profile_logoutAllDevices": "Logout all devices",
48+
"profile_noThirdPartyApps": "No third party apps connected!",
49+
"profile_label": "Label",
50+
"profile_key": "Key",
51+
"profile_scope": "Scope",
52+
"profile_actions": "Actions",
53+
"profile_singleSignOn": "Single Sign On Credentials",
54+
"profile_noSsoClients": "No sso clients found!",
55+
"profile_clientId": "Client Id",
56+
"profile_clientSecret": "Client Secret",
57+
"profile_logoUrl": "Logo Url",
58+
"profile_websiteUrl": "Website Url",
59+
"profile_name": "Name",
60+
"profile_audiences": "Audiences",
61+
"profile_redirects": "Redirects",
62+
"profile_createSsoClient": "Create new SSO client",
63+
"profile_warning": "Warning:",
64+
"profile_dangerWarning": "Deleting your account is irreversible. All your data will be deleted and cannot be restored.",
65+
"profile_noPasskeys": "No passkeys found!",
66+
"profile_lastLogin": "Last login:",
67+
"profile_createdAt": "Created at:",
68+
"profile_currentDevice": "(Current Device)",
69+
"profile_noDevices": "No devices found.",
70+
"profile_lastUsed": "Last used:",
71+
"profile_placeholder_email": "Email",
72+
"profile_placeholder_username": "Username",
73+
"profile_placeholder_firstname": "Firstname",
74+
"profile_placeholder_lastname": "Lastname",
75+
"profile_placeholder_country": "Country",
76+
"profile_placeholder_preferredLanguage": "Preferred Language",
77+
"profile_placeholder_oldPassword": "Old Password",
78+
"profile_placeholder_newPassword": "New Password",
79+
"profile_placeholder_repeatPassword": "Repeat Password",
80+
"profile_placeholder_2faToken": "2fa Token",
81+
"profile_placeholder_label": "Label",
82+
"profile_placeholder_scope": "Scope",
83+
"profile_placeholder_password": "Password",
84+
"profile_placeholder_mfaToken": "MFA Token",
85+
"profile_placeholder_name": "Name",
86+
"profile_placeholder_url": "Url",
87+
"profile_placeholder_logoUrl": "LogoUrl"
1288
}

0 commit comments

Comments
 (0)