From 3203177d158615ba472d667f53becd7738f48334 Mon Sep 17 00:00:00 2001
From: Hactazia <113508403+hactazia@users.noreply.github.com>
Date: Thu, 9 Jan 2025 00:44:15 +0100
Subject: [PATCH] Update fr localization, add localization for table filters
and Improve biography change highlighting (#1064)
* chore: add latest localization
* chore: add locations for table filters
* chore: Improve biography change highlighting
* fix: displays highlights correctly.
* fix: remove debug
---
html/src/app.js | 278 +++++++++++-------
html/src/app.scss | 15 +
html/src/localization/en/en.json | 78 ++++-
html/src/localization/fr/en.json | 390 +++++++++++++++++++++----
html/src/mixins/tabs/feed.pug | 9 +-
html/src/mixins/tabs/friendLog.pug | 4 +-
html/src/mixins/tabs/gameLog.pug | 6 +-
html/src/mixins/tabs/moderation.pug | 4 +-
html/src/mixins/tabs/notifications.pug | 10 +-
9 files changed, 606 insertions(+), 188 deletions(-)
diff --git a/html/src/app.js b/html/src/app.js
index 6ba3b0df..c2281a98 100644
--- a/html/src/app.js
+++ b/html/src/app.js
@@ -192,8 +192,8 @@ speechSynthesis.getVoices();
this.loginForm.savedCredentials =
(await configRepository.getString('savedCredentials')) !== null
? JSON.parse(
- await configRepository.getString('savedCredentials')
- )
+ await configRepository.getString('savedCredentials')
+ )
: {};
this.loginForm.lastUserLoggedIn =
await configRepository.getString('lastUserLoggedIn');
@@ -202,11 +202,11 @@ speechSynthesis.getVoices();
if (
!this.enablePrimaryPassword &&
(await configRepository.getString('lastUserLoggedIn')) !==
- null
+ null
) {
var user =
this.loginForm.savedCredentials[
- this.loginForm.lastUserLoggedIn
+ this.loginForm.lastUserLoggedIn
];
if (user?.loginParmas?.endpoint) {
API.endpointDomain = user.loginParmas.endpoint;
@@ -2026,7 +2026,7 @@ speechSynthesis.getVoices();
if (object === Object(object)) {
details = object;
}
- } catch (err) {}
+ } catch (err) { }
}
ref.details = details;
}
@@ -3835,7 +3835,7 @@ speechSynthesis.getVoices();
if (this.loginForm.lastUserLoggedIn) {
var user =
this.loginForm.savedCredentials[
- this.loginForm.lastUserLoggedIn
+ this.loginForm.lastUserLoggedIn
];
if (typeof user !== 'undefined') {
await webApiService.clearCookies();
@@ -4737,7 +4737,7 @@ speechSynthesis.getVoices();
});
worldName = args.ref.name;
}
- } catch (err) {}
+ } catch (err) { }
}
return worldName;
};
@@ -4760,7 +4760,7 @@ speechSynthesis.getVoices();
groupId
});
groupName = args.ref.name;
- } catch (err) {}
+ } catch (err) { }
return groupName;
};
@@ -5647,7 +5647,7 @@ speechSynthesis.getVoices();
props.currentAvatarThumbnailImageUrl[0] &&
props.currentAvatarThumbnailImageUrl[1] &&
props.currentAvatarThumbnailImageUrl[0] ===
- props.currentAvatarThumbnailImageUrl[1]
+ props.currentAvatarThumbnailImageUrl[1]
) {
imageMatches = true;
}
@@ -5706,7 +5706,7 @@ speechSynthesis.getVoices();
avatarInfo = await $app.getAvatarName(
currentAvatarImageUrl
);
- } catch (err) {}
+ } catch (err) { }
var previousAvatarInfo = {
ownerId: '',
avatarName: ''
@@ -5715,7 +5715,7 @@ speechSynthesis.getVoices();
previousAvatarInfo = await $app.getAvatarName(
previousCurrentAvatarImageUrl
);
- } catch (err) {}
+ } catch (err) { }
var feed = {
created_at: new Date().toJSON(),
type: 'Avatar',
@@ -5824,67 +5824,52 @@ speechSynthesis.getVoices();
};
/**
- * Function that find the differences between both strings, and return the differences and their position in the strings.
- * @param {*} s1 String 1
- * @param {*} s2 String 2
- * @returns
+ * Function to find the longest common subsequence between two strings
+ * @param {string} str1
+ * @param {string} str2
+ * @returns {number[][]} A matrix that contains the longest common subsequence between both strings
*/
- $app.methods.findDifferences = function (s1, s2) {
- const dp = $app.lcsMatrix(s1, s2);
- const differencesS1 = [];
- const differencesS2 = [];
- let i = s1.length;
- let j = s2.length;
-
- // Backtrack to find differences
- while (i > 0 && j > 0) {
- if (s1[i - 1] === s2[j - 1]) {
- i--;
- j--;
- } else if (dp[i - 1][j] >= dp[i][j - 1]) {
- differencesS1.push({ index: i - 1, char: s1[i - 1] }); // Deletion in s1
- i--;
- } else {
- differencesS2.push({ index: j - 1, char: s2[j - 1] }); // Insertion in s2
- j--;
+ $app.methods.longestCommonSubsequence = function longestCommonSubsequence(str1, str2) {
+ let lcs = [];
+ for (let i = 0; i <= str1.length; i++) {
+ lcs.push(new Array(str2.length + 1).fill(0));
+ }
+ for (let i = str1.length - 1; i >= 0; i--) {
+ for (let j = str2.length - 1; j >= 0; j--) {
+ if (str1[i] == str2[j]) {
+ lcs[i][j] = lcs[i + 1][j + 1] + 1;
+ } else {
+ lcs[i][j] = Math.max(lcs[i + 1][j], lcs[i][j + 1]);
+ }
}
}
+ return lcs;
+ }
- // Remaining characters in s1 (deletions)
- while (i > 0) {
- differencesS1.push({ index: i - 1, char: s1[i - 1] });
- i--;
+ /**
+ * Merge differences in both strings to get the longest common subsequence
+ * @param {{text: string, type: "add" | "remove" | "same"}[]} res
+ * @returns {{text: string, type: "add" | "remove" | "same"}[]} An array that contains the differences between both strings
+ */
+ $app.methods.regoupDifferences = function regoupDifferences(res) {
+ let regrouped = [];
+ let text = "";
+ let type = "";
+ for (let i = 0; i < res.length; i++) {
+ if (i == 0) {
+ text = res[i].text;
+ type = res[i].type;
+ } else if (res[i].type == type) {
+ text += res[i].text;
+ } else {
+ regrouped.push({ text: text, type: type });
+ text = res[i].text;
+ type = res[i].type;
+ }
}
-
- // Remaining characters in s2 (insertions)
- while (j > 0) {
- differencesS2.push({ index: j - 1, char: s2[j - 1] });
- j--;
- }
-
- return {
- differencesS1: differencesS1.reverse(), // Reverse to maintain original order
- differencesS2: differencesS2.reverse()
- };
- };
-
- $app.methods.findSequences = function (arr) {
- if (arr.length === 0) return [];
- return arr.reduce(
- (p, c, i) => {
- if (i === 0) return p;
- let lastSeq = p.pop();
- p.push(lastSeq);
- if (c - lastSeq[1] !== 1) {
- p.push([c, c]);
- } else {
- lastSeq[1] = c;
- }
- return p;
- },
- [[arr[0], arr[0]]]
- );
- };
+ regrouped.push({ text: text, type: type });
+ return regrouped;
+ }
/**
* Function that format the differences between two strings with HTML tags
@@ -5895,40 +5880,118 @@ speechSynthesis.getVoices();
* @param {*} markerEndTag
* @returns An array that contains both the string 1 and string 2, which the differences are formatted with HTML tags
*/
- $app.methods.formatDifference = function (
- s1,
- s2,
- markerStartTag = '',
- markerEndTag = ''
+ $app.methods.formatDifference = function getWordDifferences(
+ oldString,
+ newString,
+ markerAddition = '{{text}}',
+ markerDeletion = '{{text}}'
) {
- const texts = [s1, s2];
- const differs = $app.findDifferences(s1, s2);
- return Object.values(differs)
- .map((i) => $app.findSequences(i.map((j) => j.index)))
- .map((i, k) => {
- let stringBuilder = [];
- let lastPos = 0;
- let key = Date.now();
- i.forEach((j) => {
- stringBuilder.push(texts[k].substring(lastPos, j[0]));
- stringBuilder.push(
- `{{diffTag-${key}}}${texts[k].substring(j[0], j[1] + 1)}{{diffTagClose-${key}}}`
- );
- lastPos = j[1] + 1;
- });
- stringBuilder.push(texts[k].substr(lastPos, texts[k].length));
- let returnVal = stringBuilder
- .join('')
- .replaceAll(/&/g, '&')
- .replaceAll(//g, '>')
- .replaceAll(/"/g, '"')
- .replaceAll(/'/g, ''')
- .replaceAll(`{{diffTag-${key}}}`, markerStartTag)
- .replaceAll(`{{diffTagClose-${key}}}`, markerEndTag);
- return returnVal;
- });
- };
+ [oldString, newString] = [oldString, newString].map((s) => s
+ .replaceAll(/&/g, '&')
+ .replaceAll(//g, '>')
+ .replaceAll(/"/g, '"')
+ .replaceAll(/'/g, ''')
+ .replaceAll(/\n/g, '
')
+ );
+
+ const oldWords = oldString.split(/\s+/).flatMap((word) => word.split(/(
)/));
+ const newWords = newString.split(/\s+/).flatMap((word) => word.split(/(
)/));
+
+ function findLongestMatch(oldStart, oldEnd, newStart, newEnd) {
+ let bestOldStart = oldStart;
+ let bestNewStart = newStart;
+ let bestSize = 0;
+
+ const lookup = new Map();
+ for (let i = oldStart; i < oldEnd; i++) {
+ const word = oldWords[i];
+ if (!lookup.has(word)) lookup.set(word, []);
+ lookup.get(word).push(i);
+ }
+
+ for (let j = newStart; j < newEnd; j++) {
+ const word = newWords[j];
+ if (!lookup.has(word)) continue;
+
+ for (const i of lookup.get(word)) {
+ let size = 0;
+ while (
+ i + size < oldEnd &&
+ j + size < newEnd &&
+ oldWords[i + size] === newWords[j + size]
+ ) {
+ size++;
+ }
+ if (size > bestSize) {
+ bestOldStart = i;
+ bestNewStart = j;
+ bestSize = size;
+ }
+ }
+ }
+
+ return { oldStart: bestOldStart, newStart: bestNewStart, size: bestSize };
+ }
+
+ function buildDiff(oldStart, oldEnd, newStart, newEnd) {
+ const result = [];
+ const match = findLongestMatch(oldStart, oldEnd, newStart, newEnd);
+
+ if (match.size > 0) {
+ // Handle differences before the match
+ if (oldStart < match.oldStart || newStart < match.newStart) {
+ result.push(
+ ...buildDiff(oldStart, match.oldStart, newStart, match.newStart)
+ );
+ }
+
+ // Add the matched words
+ result.push(oldWords.slice(match.oldStart, match.oldStart + match.size).join(" "));
+
+ // Handle differences after the match
+ if (match.oldStart + match.size < oldEnd || match.newStart + match.size < newEnd) {
+ result.push(
+ ...buildDiff(
+ match.oldStart + match.size,
+ oldEnd,
+ match.newStart + match.size,
+ newEnd
+ )
+ );
+ }
+ } else {
+ function build(words, start, end, pattern) {
+ let r = [];
+ let ts = words.slice(start, end)
+ .filter((w) => w.length > 0)
+ .join(" ")
+ .split("
");
+ for (let i = 0; i < ts.length; i++) {
+ if (i > 0) r.push("
");
+ if (ts[i].length < 1) continue;
+ r.push(pattern.replace("{{text}}", ts[i]));
+ }
+ return r;
+ }
+
+ // Add deletions
+ if (oldStart < oldEnd)
+ result.push(...build(oldWords, oldStart, oldEnd, markerDeletion));
+
+ // Add insertions
+ if (newStart < newEnd)
+ result.push(...build(newWords, newStart, newEnd, markerAddition));
+ }
+
+ return result;
+ }
+
+ return buildDiff(0, oldWords.length, 0, newWords.length)
+ .join(" ")
+ .replace(/
[ ]+
/g, "
")
+ .replace(/
/g, "
");
+ }
// #endregion
// #region | App: gameLog
@@ -6178,8 +6241,8 @@ speechSynthesis.getVoices();
$app.methods.formatSeconds = function (duration) {
var pad = function (num, size) {
- return `000${num}`.slice(size * -1);
- },
+ return `000${num}`.slice(size * -1);
+ },
time = parseFloat(duration).toFixed(3),
hours = Math.floor(time / 60 / 60),
minutes = Math.floor(time / 60) % 60,
@@ -8348,7 +8411,7 @@ speechSynthesis.getVoices();
speechSynthesis.cancel();
if (
(await configRepository.getString('VRCX_notificationTTS')) ===
- 'Never' &&
+ 'Never' &&
this.notificationTTS !== 'Never'
) {
this.speak('Notification text-to-speech enabled');
@@ -10617,9 +10680,8 @@ speechSynthesis.getVoices();
if (type === 'search') {
try {
var response = await webApiService.execute({
- url: `${
- this.avatarRemoteDatabaseProvider
- }?${type}=${encodeURIComponent(search)}&n=5000`,
+ url: `${this.avatarRemoteDatabaseProvider
+ }?${type}=${encodeURIComponent(search)}&n=5000`,
method: 'GET',
headers: {
Referer: 'https://vrcx.app'
@@ -17472,7 +17534,7 @@ speechSynthesis.getVoices();
try {
var args = await API.getFavoriteWorlds(params);
worldLists.push([list.displayName, list.visibility, args.json]);
- } catch (err) {}
+ } catch (err) { }
}
this.userFavoriteWorlds = worldLists;
this.userDialog.isFavoriteWorldsLoading = false;
@@ -17644,7 +17706,7 @@ speechSynthesis.getVoices();
$app.methods.sortCurrentUserGroups = async function () {
var D = this.userDialog;
- var sortMethod = function () {};
+ var sortMethod = function () { };
switch (D.groupSorting.value) {
case 'alphabetical':
diff --git a/html/src/app.scss b/html/src/app.scss
index 9d214a50..cfae3c9d 100644
--- a/html/src/app.scss
+++ b/html/src/app.scss
@@ -937,3 +937,18 @@ i.x-status-icon.red {
.el-collapse-item .el-tag--mini {
line-height: 17px;
}
+
+.x-text-removed {
+ text-decoration: line-through;
+ color: #ff0000;
+ background-color: rgba(255, 0, 0, 0.2);
+ padding: 2px 2px;
+ border-radius: 4px;
+}
+
+.x-text-added {
+ color: rgb(76, 255, 80);
+ background-color: rgba(76, 255, 80, 0.2);
+ padding: 2px 2px;
+ border-radius: 4px;
+}
\ No newline at end of file
diff --git a/html/src/localization/en/en.json b/html/src/localization/en/en.json
index 5dd18f5d..f0e7fc12 100644
--- a/html/src/localization/en/en.json
+++ b/html/src/localization/en/en.json
@@ -34,11 +34,30 @@
"feed": {
"favorites_only_tooltip": "Filter favorites only",
"filter_placeholder": "Filter",
- "search_placeholder": "Search"
+ "search_placeholder": "Search",
+ "filters": {
+ "GPS": "GPS",
+ "Online": "Online",
+ "Offline": "Offline",
+ "Status": "Status",
+ "Avatar": "Avatar",
+ "Bio": "Bio"
+ }
},
"game_log": {
"filter_placeholder": "Filter",
- "search_placeholder": "Search"
+ "search_placeholder": "Search",
+ "filters": {
+ "Location": "Location",
+ "OnPlayerJoined": "Player joined",
+ "OnPlayerLeft": "Player left",
+ "PortalSpawn": "Portal spawn",
+ "VideoPlay": "Video play",
+ "Event": "Event",
+ "External": "External",
+ "StringLoad": "String load",
+ "ImageLoad": "Image load"
+ }
},
"player_list": {
"photon": {
@@ -125,17 +144,64 @@
},
"friend_log": {
"filter_placeholder": "Filter",
- "search_placeholder": "Search"
+ "search_placeholder": "Search",
+ "filters": {
+ "Friend": "New friend",
+ "Unfriend": "Unfriend",
+ "FriendRequest": "Friend request",
+ "CancelFriendRequest": "Cancel friend request",
+ "DisplayName": "Display name",
+ "TrustLevel": "Trust level"
+ }
},
"moderation": {
"filter_placeholder": "Filter",
"search_placeholder": "Search",
- "refresh_tooltip": "Refresh"
+ "refresh_tooltip": "Refresh",
+ "filters": {
+ "block": "Block",
+ "unblock": "Unblock",
+ "mute": "Mute",
+ "unmute": "Unmute",
+ "interactOn": "Interact On",
+ "interactOff": "Interact Off",
+ "muteChat": "Mute chat"
+ }
},
"notification": {
"filter_placeholder": "Filter",
"search_placeholder": "Search",
- "refresh_tooltip": "Refresh"
+ "refresh_tooltip": "Refresh",
+ "filters": {
+ "requestInvite": "Request Invite",
+ "invite": "Invite",
+ "requestInviteResponse": "Request Invite Response",
+ "inviteResponse": "Invite Response",
+ "friendRequest": "Friend Request",
+ "ignoredFriendRequest": "Ignored Friend Request",
+ "message": "Message",
+ "boop": "Boop",
+ "groupChange": "Group Change",
+ "group": {
+ "announcement": "Announcement",
+ "informative": "Informative",
+ "invite": "Invite",
+ "joinRequest": "Join Request",
+ "transfer": "Transfer",
+ "queueReady": "Queue Ready"
+ },
+ "moderation": {
+ "warning": {
+ "group": "Moderation Warning Group"
+ },
+ "report": {
+ "closed": "Moderation Report Closed"
+ }
+ },
+ "instance": {
+ "closed": "Instance Closed"
+ }
+ }
},
"friend_list": {
"header": "Friend List",
@@ -1942,4 +2008,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/html/src/localization/fr/en.json b/html/src/localization/fr/en.json
index 88023724..8322e264 100644
--- a/html/src/localization/fr/en.json
+++ b/html/src/localization/fr/en.json
@@ -21,7 +21,7 @@
"register": "Inscription",
"forgotPassword": "Mot de passe oublié ?",
"updater": "Updater",
- "proxy_settings": "Proxy settings",
+ "proxy_settings": "Paramètres du proxy",
"field": {
"username": "Nom d'utilisateur ou Email",
"password": "Mot de passe",
@@ -34,11 +34,30 @@
"feed": {
"favorites_only_tooltip": "Filtrer les favoris seulement",
"filter_placeholder": "Filtrer",
- "search_placeholder": "Rechercher"
+ "search_placeholder": "Rechercher",
+ "filters": {
+ "GPS": "GPS",
+ "Online": "En ligne",
+ "Offline": "Hors ligne",
+ "Status": "Statut",
+ "Avatar": "Avatar",
+ "Bio": "Bio"
+ }
},
"game_log": {
"filter_placeholder": "Filtrer",
- "search_placeholder": "Rechercher"
+ "search_placeholder": "Rechercher",
+ "filters": {
+ "Location": "Localisation",
+ "Event": "Événement",
+ "StringLoad": "Texte téléchargé",
+ "ImageLoad": "Image téléchargée",
+ "OnPlayerJoined": "Rejoint",
+ "OnPlayerLeft": "Quitté",
+ "PortalSpawn": "Portail",
+ "VideoPlay": "Vidéo",
+ "External": "Externe"
+ }
},
"player_list": {
"photon": {
@@ -90,17 +109,19 @@
"search": "Rechercher",
"vrchat_favorites": "Favoris VRChat",
"local_favorites": "Favoris locaux",
- "new_group": "Nouveau groupe"
+ "new_group": "Nouveau groupe",
+ "refresh": "Réactualiser",
+ "cancel_refresh": "Annuler la réactualisation"
},
"avatars": {
"header": "Avatars",
"search": "Rechercher",
"vrchat_favorites": "Favoris VRChat",
- "local_favorites": "Local Favorites (Requires VRC+)",
- "new_group": "Nouveau groupe"
+ "local_favorites": "Favoris locaux (Requires VRC+)",
+ "new_group": "Nouveau groupe",
+ "refresh": "Réactualiser",
+ "cancel_refresh": "Annuler la réactualisation"
},
- "bulk_unfavorite_mode": "Mode groupée de suppression des favoris",
- "bulk_unfavorite_selection": "Sélection groupée des favoris",
"refresh_tooltip": "Actualiser les favoris",
"export": "Exporter",
"import": "Importer",
@@ -113,21 +134,74 @@
"unavailable_tooltip": "Indisponible",
"private": "Privé",
"sort_by": "Trier par",
- "select_avatar_tooltip": "Sélectionner un avatar"
+ "select_avatar_tooltip": "Sélectionner un avatar",
+ "edit_mode": "Mode édition",
+ "copy": "Copier",
+ "clear": "Vider",
+ "bulk_unfavorite": "Mode suppression des favoris",
+ "copy_tooltip": "Copier",
+ "self_invite_tooltip": "S'inviter"
},
"friend_log": {
"filter_placeholder": "Filtrer",
- "search_placeholder": "Rechercher"
+ "search_placeholder": "Rechercher",
+ "filters": {
+ "Friend": "Nouvel ami",
+ "Unfriend": "Ami supprimé",
+ "FriendRequest": "Demande d'ami envoyée",
+ "CancelFriendRequest": "Demande d'ami annulée",
+ "DisplayName": "Nom d'affichage",
+ "TrustLevel": "Niveau de confiance"
+ }
},
"moderation": {
"filter_placeholder": "Filtrer",
"search_placeholder": "Rechercher",
- "refresh_tooltip": "Actualiser"
+ "refresh_tooltip": "Actualiser",
+ "filters": {
+ "block": "Bloqué",
+ "unblock": "Débloqué",
+ "mute": "Sourdine",
+ "unmute": "Son rétabli",
+ "interactOn": "Interaction activée",
+ "interactOff": "Interaction désactivée",
+ "muteChat": "Boîtes de dialogue désactivées"
+ }
},
"notification": {
"filter_placeholder": "Filtrer",
"search_placeholder": "Rechercher",
- "refresh_tooltip": "Actualiser"
+ "refresh_tooltip": "Actualiser",
+ "filters": {
+ "requestInvite": "Demande d'invitation",
+ "invite": "Invitation",
+ "requestInviteResponse": "Réponse à une demande d'invitation",
+ "inviteResponse": "Réponse à une invitation",
+ "friendRequest": "Demande d'ami",
+ "ignoredFriendRequest": "Demande d'ami ignorée",
+ "message": "Message",
+ "boop": "Boop",
+ "groupChange": "Changement de groupe",
+ "group": {
+ "announcement": "Annonce de groupe",
+ "informative": "Publication de groupe",
+ "invite": "Invitation de groupe",
+ "joinRequest": "Demande de rejoindre le groupe",
+ "transfer": "Transfert de groupe",
+ "queueReady": "File d'attente prête"
+ },
+ "moderation": {
+ "warning": {
+ "group": "Avertissement de modération de groupe"
+ },
+ "report": {
+ "closed": "Rapport de modération fermé"
+ }
+ },
+ "instance": {
+ "closed": "Instance fermée"
+ }
+ }
},
"friend_list": {
"header": "Liste des amis",
@@ -207,18 +281,22 @@
"vrcx_updater": {
"header": "Mise à jour de VRCX",
"change_build": "Changer de build",
- "auto_update": "Mise à jour automatique",
"auto_update_off": "Désactivé",
"auto_update_notify": "Me demander",
"auto_update_download": "Téléchargement automatique",
- "change_log": "Journal des modifications"
+ "change_log": "Journal des modifications",
+ "update_action": "Action de mise à jour"
},
"application": {
"header": "Application",
"startup": "Lancer au démarrage de Windows",
"minimized": "Lancer en arrière plan",
"tray": "Minimiser dans la barre des tâches",
- "proxy": "Proxy settings"
+ "proxy": "Proxy settings",
+ "disable_gpu_acceleration": "Désactiver l'accélération GPU",
+ "disable_gpu_acceleration_tooltip": "Ne changez cette option que si vous savez ce que vous faites, cette fonctionnalité casse la surcouche SteamVR, peut corriger des problèmes avec l'interface utilisateur, nécessite le redémarrage de VRCX.",
+ "disable_vr_overlay_gpu_acceleration": "Désactiver l'accélération GPU de l'overlay VR",
+ "disable_vr_overlay_gpu_acceleration_tooltip": "L'accélération GPU de l'overlay VR peut faire planter VRCX ou provoquer des fuites de mémoire VRAM, nécessite de redémarrer VRCX."
},
"favorites": {
"header": "Amis favoris",
@@ -231,19 +309,20 @@
},
"automation": {
"header": "Automatisation",
- "auto_state_change": "Changement de statut automatique",
"auto_state_change_tooltip": "Changer automatiquement de statut quand il y a d'autres personnes dans l'instance (Seul / Compagnie)",
- "auto_state_change_off": "Désactivé",
- "auto_state_change_active_or_ask_me": "Actif / Demandez-moi",
- "auto_state_change_active_or_busy": "Actif / Occupé",
- "auto_state_change_join_me_or_ask_me": "Rejoignez-moi / Demandez-moi",
- "auto_state_change_join_me_or_busy": "Rejoignez-moi / Ne pas déranger",
- "auto_state_change_ask_me_or_busy": "Demandez-moi / Occupé",
"auto_invite_request_accept": "Accepter automatiquement les demandes d'invitation",
"auto_invite_request_accept_tooltip": "Accepter automatiquement les demandes d'invitation des amis favoris",
"auto_invite_request_accept_off": "Désactivé",
"auto_invite_request_accept_favs": "Tous les favoris",
- "auto_invite_request_accept_selected_favs": "Favoris sélectionnés"
+ "auto_invite_request_accept_selected_favs": "Favoris sélectionnés",
+ "auto_change_status": "Changer automatiquement de statut",
+ "alone_condition": "Condition de statut seul",
+ "alone": "Seul",
+ "no_friends": "Pas d'amis",
+ "alone_status": "Statut seul",
+ "company_status": "Statut en compagnie",
+ "allowed_instance_types": "Types d'instances autorisés",
+ "instance_type_placeholder": "Choisir des types d'instances"
},
"legal_notice": {
"header": "Mentions légales",
@@ -292,23 +371,16 @@
"header": "Panneau latéral",
"sorting": {
"header": "Comportement du tri",
- "sort_default": "Default",
- "sort_private_to_bottom": "Joueurs en privé en fin de liste",
- "sort_by_status": "Trier par statut",
- "sort_by_status_and_private_to_bottom": "Sort by Status and Private to Bottom",
- "sort_by_location": "Sort by Location",
- "sort_favorite_by": "Trier les favoris par",
- "sort_favorite_by_alphabet": "alphabétique",
- "sort_favorite_by_online_time": "en ligne depuis",
- "sort_online_by": "Trier les en ligne par",
- "sort_online_by_alphabet": "alphabétique",
- "sort_online_by_online_time": "en ligne depuis",
- "sort_active_by": "Trier les actifs par",
- "sort_active_by_alphabet": "alphabétique",
- "sort_active_by_online_time": "en ligne depuis",
- "sort_offline_by": "Trier les hors ligne par",
- "sort_offline_by_alphabet": "alphabétique",
- "sort_offline_by_offline_time": "hors ligne depuis"
+ "alphabetical": "Alphabétique",
+ "private_to_bottom": "Privé en bas",
+ "status": "Statut",
+ "status_and_private_to_bottom": "Statut et privé en bas",
+ "location": "Localisation",
+ "last_active": "Dernière activité",
+ "last_seen": "Vu la dernière fois",
+ "time_in_instance": "Temps dans l'instance",
+ "placeholder": "Type de tri",
+ "dropdown_header": "Choisi un type de tri"
},
"width": "Largeur"
},
@@ -348,7 +420,9 @@
"desktop": "Mode bureau",
"inside_vr": "Durant la VR",
"outside_vr": "En dehors de la VR",
- "always": "En permanence"
+ "always": "En permanence",
+ "inside_vrchat": "Dans VRChat",
+ "outside_vrchat": "En dehors de VRChat"
},
"desktop_notifications": {
"header": "Notifications sur le bureau",
@@ -358,7 +432,10 @@
"text_to_speech": {
"header": "Text-To-Speech",
"when_to_play": "Quand la jouer",
- "tts_voice": "Voix de la synthèse vocale"
+ "tts_voice": "Voix de la synthèse vocale",
+ "use_memo_nicknames": "Utiliser les surnoms dans les mémos",
+ "play": "Jouer",
+ "tts_test_placeholder": "Cliquez pour tester"
}
}
},
@@ -419,10 +496,7 @@
"header": "Correction de l'arrêt de VRChat",
"description": "Arrêter VRChat après avoir quitté le jeu"
},
- "vrchat_osc_fix": {
- "header": "VRChat OSC Fix",
- "description": "Resuming and terminating the suspended install.exe process after exiting game"
- },
+ "vrchat_osc_fix": {},
"auto_cache_management": {
"header": "Gérer automatiquement le cache lors de la fermeture de VRChat",
"description": "Suppression automatique des anciennes versions du cache"
@@ -497,6 +571,22 @@
"portal_spawn": "Portail d'accès :",
"video_play": "Lecture de vidéo :",
"event": "Événement :"
+ },
+ "save_instance_prints_to_file": {
+ "header": "Enregistrement des Impressions d'instance dans un fichier",
+ "header_tooltip": "Nécessite l'option de lancement du VRChat « --enable-sdk-log-levels ».",
+ "description": "Enregistre les impressions générées dans votre dossier VRChat Pictures"
+ },
+ "save_instance_stickers_to_file": {
+ "header": "Enregistrer les autocollants d'instance dans un fichier",
+ "description": "Enregistrer les autocollants placés dans votre dossier VRChat Pictures"
+ },
+ "user_generated_content": {
+ "header": "Contenu généré par l'utilisateur",
+ "folder": "Ouvrir le dossier",
+ "description": "Ouvrez ou définissez le dossier dans lequel sont stockés les contenus tels que « Impressions » et « Autocollants ».",
+ "set_folder": "Définir un dossier",
+ "reset_override": "Réinitialiser"
}
},
"photon": {
@@ -590,7 +680,10 @@
"edit_pronouns": "Pronoms",
"report_hacking": "Signaler un piratage",
"unfriend": "Supprimer des amis",
- "logout": "Se déconnecter"
+ "logout": "Se déconnecter",
+ "share": "Partager",
+ "moderation_enable_chatbox": "Rétablir les boites de dialogue",
+ "moderation_disable_chatbox": "Désactiver les boites de dialogue"
},
"info": {
"header": "Infos",
@@ -636,14 +729,25 @@
"instance_full": "Complète",
"instance_closed": "Instance fermée",
"instance_hard_closed": "Instance fermée définitivement",
- "close_instance": "Fermer l'instance"
+ "close_instance": "Fermer l'instance",
+ "instance_age_gated": "Limitation d'âge"
},
"groups": {
"header": "Groupes",
"total_count": "{count} au total",
"own_groups": "Propres groupes",
"mutual_groups": "Groupes mutuels",
- "groups": "Groupes"
+ "groups": "Groupes",
+ "sort_by": "Trier par",
+ "edit_mode": "Mode édition",
+ "exit_edit_mode": "Quitter le mode édition",
+ "hold_shift": "Maintenez Maj enfoncée pour sélectionner plusieurs groupes",
+ "sorting": {
+ "alphabetical": "Alphabétique",
+ "members": "Membres",
+ "in_game": "En jeu"
+ },
+ "leave_group_tooltip": "Quitter le groupe"
},
"worlds": {
"header": "Mondes",
@@ -676,6 +780,11 @@
},
"json": {
"header": "JSON"
+ },
+ "badges": {
+ "assigned": "Attribués",
+ "hidden": "Cachés",
+ "showcased": "Mise en avant"
}
},
"world": {
@@ -690,7 +799,9 @@
"content_gore": "Gore",
"content_violence": "Violence",
"content_adult": "Adulte",
- "content_sex": "Sexuel"
+ "content_sex": "Sexuel",
+ "focus_view_disabled": "Vue focale désactivée",
+ "stickers_disabled": "Autocollants désactivés"
},
"actions": {
"delete_cache_tooltip": "Supprimer le monde du cache",
@@ -711,7 +822,11 @@
"download_package": "Télécharger le package Unity",
"publish_to_labs": "Publier comme Labs",
"unpublish": "Dépublier",
- "delete": "Supprimer"
+ "delete": "Supprimer",
+ "share": "Partager",
+ "new_instance_and_self_invite": "Créer une nouvelle instance et s'inviter",
+ "change_allowed_video_player_domains": "Changer les domaines de lecteur vidéo autorisés",
+ "delete_persistent_data": "Supprimer les données persistantes"
},
"instances": {
"header": "Instances",
@@ -780,7 +895,7 @@
"favorite_tooltip": "Favoris",
"unfavorite_tooltip": "Supprimer des favoris",
"refresh": "Actualiser",
- "select": "Sélectionner un avatar",
+ "select": "Sélectionner cet avatar",
"select_fallback": "Sélectionner l'avatar fallback",
"block": "Bloquer l'avatar",
"unblock": "Débloquer l'avatar",
@@ -850,7 +965,8 @@
"moderation_tools": "Outils de modération",
"leave": "Quitter le groupe",
"block": "Bloquer le groupe",
- "unblock": "Débloquer le groupe"
+ "unblock": "Débloquer le groupe",
+ "share": "Partager"
},
"info": {
"header": "Infos",
@@ -990,7 +1106,8 @@
"normal": "Normale",
"group": "Groupe",
"legacy": "Legacy",
- "roles": "Rôles"
+ "roles": "Rôles",
+ "ageGate": "Limitation d'âge"
},
"launch_options": {
"header": "Options de démarrage de VRChat",
@@ -1022,7 +1139,8 @@
"disable_discord_presence": "Désactiver la présence Discord",
"vrchat_docs": "Documentation de VRChat",
"cancel": "Annuler",
- "save": "Sauvegarder"
+ "save": "Sauvegarder",
+ "spout_resolution": "Résolution Spout"
},
"youtube_api": {
"header": "API YouTube",
@@ -1043,7 +1161,9 @@
"content_adult": "Adulte",
"content_sex": "Sexuel",
"cancel": "Annuler",
- "save": "Sauvegarder"
+ "save": "Sauvegarder",
+ "focus_view_disabled": "Désactiver la vue focale",
+ "stickers_disabled": "Désactiver les autocollants"
},
"set_avatar_tags": {
"header": "Modifier les tags de l'avatar",
@@ -1243,7 +1363,6 @@
},
"gallery_icons": {
"header": "Galerie et icônes",
- "description": "Recommended image size: 1200x900px (4:3)",
"gallery": "Galerie",
"icons": "Icônes",
"emojis": "Émojis",
@@ -1255,7 +1374,11 @@
"emoji_animation_fps": "FPS",
"emoji_animation_frame_count": "Nombre de frames",
"emoji_loop_pingpong": "Animé en boucle",
- "flipbook_info": "Sélectionnez une image PNG 1024x1024 pour l'utiliser comme emoji animé : 4, 16 ou 64 (64 FPS max, 64 frames max)."
+ "flipbook_info": "Sélectionnez une image PNG 1024x1024 pour l'utiliser comme emoji animé : 4, 16 ou 64 (64 FPS max, 64 frames max).",
+ "recommended_image_size": "Taille d'image recommandée",
+ "stickers": "Autocollants",
+ "prints": "Impressions",
+ "note": "Notes"
},
"change_content_image": {
"avatar": "Changer l'image de l'avatar",
@@ -1388,6 +1511,11 @@
"default_emojis": "Emojis par défaut",
"cancel": "Annuler",
"send": "Envoyer"
+ },
+ "allowed_video_player_domains": {
+ "header": "Domaines autorisés pour le lecteur vidéo",
+ "add_domain": "Ajouter un domaine",
+ "save": "Sauvegarder"
}
},
"prompt": {
@@ -1736,5 +1864,149 @@
"cpu": "CPU :",
"online": "En ligne :"
}
+ },
+ "confirm": {
+ "title": "Confirmation",
+ "confirm_button": "Confirmer",
+ "cancel_button": "Annuler",
+ "message": "Confirmer {command} ?"
+ },
+ "message": {
+ "vrcx_updater": {
+ "failed": "Échec de la vérification de la mise à jour, {message}"
+ },
+ "api_handler": {
+ "avatar_private_or_deleted": "Avatar privé ou supprimé"
+ },
+ "badge": {
+ "updated": "Badge mis à jour"
+ },
+ "instance": {
+ "closed": "Instance fermée",
+ "removed_form_queue": "Suppression de l'instance {worldName} de la file d'attente",
+ "not_allowed": "Vous n'êtes pas autorisé à rejoindre cette instance"
+ },
+ "avatar": {
+ "change_moderation_failed": "Échec de la modération de l'avatar",
+ "image_changed": "Image de l'avatar changée",
+ "image_invalid": "Image de l'avatar invalide"
+ },
+ "emoji": {
+ "uploaded": "Emoji envoyé"
+ },
+ "file": {
+ "not_image": "Le fichier n'est pas une image",
+ "too_large": "Le fichier est trop volumineux"
+ },
+ "print": {
+ "uploaded": "Impression envoyée"
+ },
+ "sticker": {
+ "uploaded": "Autocollant envoyé"
+ },
+ "gallery": {
+ "uploaded": "Image de la galerie envoyée",
+ "failed": "Échec de l'envoi de l'image de la galerie"
+ },
+ "world": {
+ "image_changed": "Image du monde changée",
+ "image_invalid": "Image du monde invalide"
+ },
+ "icon": {
+ "uploaded": "Icône envoyée"
+ },
+ "user": {
+ "moderated": "Utilisateur modéré"
+ },
+ "friend": {
+ "load_failed": "Échec du chargement de la liste d'amis, déconnexion..."
+ }
+ },
+ "api": {
+ "status_code": {
+ "100": "Continuer",
+ "101": "Changement de protocole",
+ "102": "Traitement",
+ "103": "Premiers indices",
+ "200": "OK",
+ "201": "Créé",
+ "202": "Accepté",
+ "203": "Information non autorisée",
+ "204": "Pas de contenu",
+ "205": "Réinitialiser le contenu",
+ "206": "Contenu partiel",
+ "207": "Multi-état",
+ "208": "Déjà signalé",
+ "226": "IM utilisé",
+ "300": "Choix multiples",
+ "301": "Déplacé de façon permanente",
+ "302": "Trouvé",
+ "303": "Voir autre",
+ "304": "Non modifié",
+ "305": "Utiliser un proxy",
+ "306": "Changer de proxy",
+ "307": "Redirection temporaire",
+ "308": "Redirection permanente",
+ "400": "Mauvaise requête",
+ "401": "Non autorisé",
+ "402": "Paiement requis",
+ "403": "Interdit",
+ "404": "Introuvable",
+ "405": "Méthode non autorisée",
+ "406": "Non acceptable",
+ "407": "Authentification proxy requise",
+ "408": "Temps de requête écoulé",
+ "409": "Conflit",
+ "410": "Parti",
+ "411": "Longueur requise",
+ "412": "Condition préalable échouée",
+ "413": "Charge utile trop grande",
+ "414": "URI trop longue",
+ "415": "Type de média non pris en charge",
+ "416": "Plage non satisfaisable",
+ "417": "Attente échouée",
+ "418": "Je suis une théière",
+ "421": "Requête mal dirigée",
+ "422": "Entité non traitable",
+ "423": "Verrouillé",
+ "424": "Dépendance échouée",
+ "425": "Trop tôt",
+ "426": "Mise à niveau requise",
+ "428": "Condition préalable requise",
+ "429": "Trop de requêtes",
+ "431": "Champs d'en-tête de requête trop grands",
+ "451": "Indisponible pour des raisons légales",
+ "500": "Erreur interne du serveur",
+ "501": "Non implémenté",
+ "502": "Mauvaise passerelle",
+ "503": "Service indisponible",
+ "504": "Temps d'attente de la passerelle écoulé",
+ "505": "Version HTTP non prise en charge",
+ "506": "La variante négocie également",
+ "507": "Espace de stockage insuffisant",
+ "508": "Boucle détectée",
+ "510": "Non étendu",
+ "511": "Authentification réseau requise",
+ "520": "Le serveur web retourne une erreur inconnue",
+ "521": "Le serveur web est en panne",
+ "522": "Temps de connexion écoulé",
+ "523": "Origine inaccessible",
+ "524": "Un délai d'attente s'est produit",
+ "525": "Échec de l'établissement de la liaison SSL",
+ "526": "Certificat SSL invalide",
+ "527": "Erreur du Railgun Listener à l'origine"
+ },
+ "error": {
+ "message": {
+ "error_message": "Message d'erreur",
+ "endpoint": "Endpoint",
+ "missing_credentials": "Credentials manquantes",
+ "avatar_private_or_deleted": "Avatar privé ou supprimé",
+ "vpn_in_use": "VRChat bloque actuellement la plupart des VPN. Veuillez désactiver tout VPN connecté et réessayer.",
+ "login_error": "Erreur de connexion",
+ "invalid_json_response": "Réponse JSON invalide",
+ "403_404_bailing_request": "En attente d'une autorisation dû à un récent 404/403"
+ }
+ }
}
-}
+}
\ No newline at end of file
diff --git a/html/src/mixins/tabs/feed.pug b/html/src/mixins/tabs/feed.pug
index c35f5c1d..6848093e 100644
--- a/html/src/mixins/tabs/feed.pug
+++ b/html/src/mixins/tabs/feed.pug
@@ -7,7 +7,7 @@ mixin feedTab()
el-tooltip(placement="bottom" :content="$t('view.feed.favorites_only_tooltip')" :disabled="hideTooltips")
el-switch(v-model="feedTable.vip" @change="feedTableLookup" active-color="#13ce66")
el-select(v-model="feedTable.filter" @change="feedTableLookup" multiple clearable style="flex:1;height:40px;" :placeholder="$t('view.feed.filter_placeholder')")
- el-option(v-once v-for="type in ['GPS', 'Online', 'Offline', 'Status', 'Avatar', 'Bio']" :key="type" :label="type" :value="type")
+ el-option(v-once v-for="type in ['GPS', 'Online', 'Offline', 'Status', 'Avatar', 'Bio']" :key="type" :label="$t('view.feed.filters.' + type)" :value="type")
el-input(v-model="feedTable.search" :placeholder="$t('view.feed.search_placeholder')" @keyup.native.13="feedTableLookup" @change="feedTableLookup" clearable style="flex:none;width:150px;margin:0 10px")
el-table-column(type="expand" width="20")
template(v-once #default="scope")
@@ -65,10 +65,7 @@ mixin feedTab()
i.x-user-status(:class="statusClass(scope.row.status)" style="margin:0 5px")
span(v-text="scope.row.statusDescription")
template(v-else-if="scope.row.type === 'Bio'")
- template(v-for="(bio,idx) in formatDifference(scope.row.previousBio, scope.row.bio)")
- pre(v-html="bio" style="font-family:inherit;font-size:12px;white-space:pre-wrap;margin:0 0.5em 0 0")
- span(v-if="idx === 0")
- i.el-icon-right
+ pre(v-html="formatDifference(scope.row.previousBio, scope.row.bio)" style="font-family:inherit;font-size:12px;white-space:pre-wrap;line-height:25px;line-height: 22px;")
el-table-column(:label="$t('table.feed.date')" prop="created_at" sortable="custom" width="120")
template(v-once #default="scope")
el-tooltip(placement="right")
@@ -76,6 +73,8 @@ mixin feedTab()
span {{ scope.row.created_at | formatDate('long') }}
span {{ scope.row.created_at | formatDate('short') }}
el-table-column(:label="$t('table.feed.type')" prop="type" width="70")
+ template(v-once #default="scope")
+ span.x-link(v-text="$t('view.feed.filters.' + scope.row.type)")
el-table-column(:label="$t('table.feed.user')" prop="displayName" width="180")
template(v-once #default="scope")
span.x-link(v-text="scope.row.displayName" @click="showUserDialog(scope.row.userId)" style="padding-right:10px")
diff --git a/html/src/mixins/tabs/friendLog.pug b/html/src/mixins/tabs/friendLog.pug
index 6444f308..f8a0fc9e 100644
--- a/html/src/mixins/tabs/friendLog.pug
+++ b/html/src/mixins/tabs/friendLog.pug
@@ -4,12 +4,14 @@ mixin friendLogTab()
template(#tool)
div(style="margin:0 0 10px;display:flex;align-items:center")
el-select(v-model="friendLogTable.filters[0].value" @change="saveTableFilters" multiple clearable style="flex:1" :placeholder="$t('view.friend_log.filter_placeholder')")
- el-option(v-once v-for="type in ['Friend', 'Unfriend', 'FriendRequest', 'CancelFriendRequest', 'DisplayName', 'TrustLevel']" :key="type" :label="type" :value="type")
+ el-option(v-once v-for="type in ['Friend', 'Unfriend', 'FriendRequest', 'CancelFriendRequest', 'DisplayName', 'TrustLevel']" :key="type" :label="$t('view.friend_log.filters.' + type)" :value="type")
el-input(v-model="friendLogTable.filters[1].value" :placeholder="$t('view.friend_log.search_placeholder')" style="flex:none;width:150px;margin-left:10px")
el-table-column(:label="$t('table.friendLog.date')" prop="created_at" sortable="custom" width="200")
template(v-once #default="scope")
span {{ scope.row.created_at | formatDate('long') }}
el-table-column(:label="$t('table.friendLog.type')" prop="type" width="150")
+ template(v-once #default="scope")
+ span(v-text="$t('view.friend_log.filters.' + scope.row.type)")
el-table-column(:label="$t('table.friendLog.user')" prop="displayName")
template(v-once #default="scope")
span(v-if="scope.row.type === 'DisplayName'") {{ scope.row.previousDisplayName }} #[i.el-icon-right]
diff --git a/html/src/mixins/tabs/gameLog.pug b/html/src/mixins/tabs/gameLog.pug
index 11f43e33..c77ce36c 100644
--- a/html/src/mixins/tabs/gameLog.pug
+++ b/html/src/mixins/tabs/gameLog.pug
@@ -7,7 +7,7 @@ mixin gameLogTab()
el-tooltip(placement="bottom" :content="$t('view.feed.favorites_only_tooltip')" :disabled="hideTooltips")
el-switch(v-model="gameLogTable.vip" @change="gameLogTableLookup" active-color="#13ce66")
el-select(v-model="gameLogTable.filter" @change="gameLogTableLookup" multiple clearable style="flex:1" :placeholder="$t('view.game_log.filter_placeholder')")
- el-option(v-once v-for="type in ['Location', 'OnPlayerJoined', 'OnPlayerLeft', 'PortalSpawn', 'VideoPlay', 'Event', 'External', 'StringLoad', 'ImageLoad']" :key="type" :label="type" :value="type")
+ el-option(v-once v-for="type in ['Location', 'OnPlayerJoined', 'OnPlayerLeft', 'PortalSpawn', 'VideoPlay', 'Event', 'External', 'StringLoad', 'ImageLoad']" :key="type" :label="$t('view.game_log.filters.' + type)" :value="type")
el-input(v-model="gameLogTable.search" :placeholder="$t('view.game_log.search_placeholder')" @keyup.native.13="gameLogTableLookup" @change="gameLogTableLookup" clearable style="flex:none;width:150px;margin:0 10px")
el-table-column(:label="$t('table.gameLog.date')" prop="created_at" sortable="custom" width="120")
template(v-once #default="scope")
@@ -17,8 +17,8 @@ mixin gameLogTab()
span {{ scope.row.created_at | formatDate('short') }}
el-table-column(:label="$t('table.gameLog.type')" prop="type" width="120")
template(v-once #default="scope")
- span.x-link(v-if="scope.row.location && scope.row.type !== 'Location'" v-text="scope.row.type" @click="showWorldDialog(scope.row.location)")
- span(v-else v-text="scope.row.type")
+ span.x-link(v-if="scope.row.location && scope.row.type !== 'Location'" v-text="$t('view.game_log.filters.' + scope.row.type)" @click="showWorldDialog(scope.row.location)")
+ span(v-else v-text="$t('view.game_log.filters.' + scope.row.type)")
el-table-column(:label="$t('table.gameLog.icon')" prop="isFriend" width="70")
template(v-once #default="scope")
template(v-if="gameLogIsFriend(scope.row)")
diff --git a/html/src/mixins/tabs/moderation.pug b/html/src/mixins/tabs/moderation.pug
index 6850448e..eeab9dbe 100644
--- a/html/src/mixins/tabs/moderation.pug
+++ b/html/src/mixins/tabs/moderation.pug
@@ -4,7 +4,7 @@ mixin moderationTab()
template(#tool)
div(style="margin:0 0 10px;display:flex;align-items:center")
el-select(v-model="playerModerationTable.filters[0].value" @change="saveTableFilters" multiple clearable style="flex:1" :placeholder="$t('view.moderation.filter_placeholder')")
- el-option(v-once v-for="type in ['block', 'unblock', 'mute', 'unmute', 'interactOn', 'interactOff', 'muteChat']" :key="type" :label="type" :value="type")
+ el-option(v-once v-for="type in ['block', 'unblock', 'mute', 'unmute', 'interactOn', 'interactOff', 'muteChat']" :key="type" :label="$t('view.moderation.filters.' + type)" :value="type")
el-input(v-model="playerModerationTable.filters[1].value" :placeholder="$t('view.moderation.search_placeholder')" style="flex:none;width:150px;margin:0 10px")
el-tooltip(placement="bottom" :content="$t('view.moderation.refresh_tooltip')" :disabled="hideTooltips")
el-button(type="default" :loading="API.isPlayerModerationsLoading" @click="API.refreshPlayerModerations()" icon="el-icon-refresh" circle style="flex:none")
@@ -15,6 +15,8 @@ mixin moderationTab()
span {{ scope.row.created | formatDate('long') }}
span {{ scope.row.created | formatDate('short') }}
el-table-column(:label="$t('table.moderation.type')" prop="type" width="100")
+ template(v-once #default="scope")
+ span(v-text="$t('view.moderation.filters.' + scope.row.type)")
el-table-column(:label="$t('table.moderation.source')" prop="sourceDisplayName")
template(v-once #default="scope")
span.x-link(v-text="scope.row.sourceDisplayName" @click="showUserDialog(scope.row.sourceUserId)")
diff --git a/html/src/mixins/tabs/notifications.pug b/html/src/mixins/tabs/notifications.pug
index 11b31111..3564ab15 100644
--- a/html/src/mixins/tabs/notifications.pug
+++ b/html/src/mixins/tabs/notifications.pug
@@ -4,7 +4,7 @@ mixin notificationsTab()
template(#tool)
div(style="margin:0 0 10px;display:flex;align-items:center")
el-select(v-model="notificationTable.filters[0].value" @change="saveTableFilters" multiple clearable style="flex:1" :placeholder="$t('view.notification.filter_placeholder')")
- el-option(v-once v-for="type in ['requestInvite', 'invite', 'requestInviteResponse', 'inviteResponse', 'friendRequest', 'ignoredFriendRequest', 'message', 'boop', 'groupChange', 'group.announcement', 'group.informative', 'group.invite', 'group.joinRequest', 'group.transfer', 'group.queueReady', 'moderation.warning.group', 'moderation.report.closed', 'instance.closed']" :key="type" :label="type" :value="type")
+ el-option(v-once v-for="type in ['requestInvite', 'invite', 'requestInviteResponse', 'inviteResponse', 'friendRequest', 'ignoredFriendRequest', 'message', 'boop', 'groupChange', 'group.announcement', 'group.informative', 'group.invite', 'group.joinRequest', 'group.transfer', 'group.queueReady', 'moderation.warning.group', 'moderation.report.closed', 'instance.closed']" :key="type" :label="$t('view.notification.filters.' + type)" :value="type")
el-input(v-model="notificationTable.filters[1].value" :placeholder="$t('view.notification.search_placeholder')" style="flex:none;width:150px;margin:0 10px")
el-tooltip(placement="bottom" :content="$t('view.notification.refresh_tooltip')" :disabled="hideTooltips")
el-button(type="default" :loading="API.isNotificationsLoading" @click="API.refreshNotifications()" icon="el-icon-refresh" circle style="flex:none")
@@ -19,14 +19,14 @@ mixin notificationsTab()
el-tooltip(v-if="scope.row.type === 'invite'" placement="top")
template(#content)
location(v-if="scope.row.details" :location="scope.row.details.worldId" :hint="scope.row.details.worldName" :grouphint="scope.row.details.groupName" :link="false")
- span.x-link(v-text="scope.row.type" @click="showWorldDialog(scope.row.details.worldId)")
+ span.x-link(v-text="$t('view.notification.filters.' + scope.row.type)" @click="showWorldDialog(scope.row.details.worldId)")
el-tooltip(v-else-if="scope.row.type === 'group.queueReady' || scope.row.type === 'instance.closed'" placement="top")
template(#content)
location(v-if="scope.row.location" :location="scope.row.location" :hint="scope.row.worldName" :grouphint="scope.row.groupName" :link="false")
- span.x-link(v-text="scope.row.type" @click="showWorldDialog(scope.row.location)")
+ span.x-link(v-text="$t('view.notification.filters.' + scope.row.type)" @click="showWorldDialog(scope.row.location)")
el-tooltip(v-else-if="scope.row.link" placement="top" :content="scope.row.linkText" :disabled="hideTooltips")
- span.x-link(v-text="scope.row.type" @click="openNotificationLink(scope.row.link)")
- span(v-else v-text="scope.row.type")
+ span.x-link(v-text="$t('view.notification.filters.' + scope.row.type)" @click="openNotificationLink(scope.row.link)")
+ span(v-else v-text="$t('view.notification.filters.' + scope.row.type)")
el-table-column(:label="$t('table.notification.user_group')" prop="senderUsername" width="150")
template(v-once #default="scope")
template(v-if="scope.row.type === 'groupChange'")