feat(i18n): fix French translations and add locale-aware date formatting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Tanguy Mazé
2025-11-30 00:58:58 +01:00
parent d7a5d9f5f0
commit 12b34bfada
31 changed files with 251 additions and 59 deletions

View File

@@ -14,7 +14,7 @@ import RSection from "@/components/common/RSection.vue";
import romApi from "@/services/api/rom";
import storeAuth from "@/stores/auth";
import type { DetailedRom } from "@/stores/roms";
import { getTextForStatus, getEmojiForStatus } from "@/utils";
import { getTextForStatus, getEmojiForStatus, getI18nKeyForStatus } from "@/utils";
const { t } = useI18n();
const props = defineProps<{ rom: DetailedRom }>();
@@ -301,7 +301,7 @@ watch(
getEmojiForStatus(item.raw as RomUserStatus)
}}</span
><span class="ml-2">{{
getTextForStatus(item.raw as RomUserStatus)
t(getI18nKeyForStatus(item.raw as RomUserStatus) || '')
}}</span>
</template>
<template #item="{ item }">
@@ -310,7 +310,7 @@ watch(
getEmojiForStatus(item.raw as RomUserStatus)
}}</span
><span class="ml-2">{{
getTextForStatus(item.raw as RomUserStatus)
t(getI18nKeyForStatus(item.raw as RomUserStatus) || '')
}}</span>
</v-list-item>
</template>

View File

@@ -2,6 +2,7 @@
import type { Emitter } from "mitt";
import { storeToRefs } from "pinia";
import { inject, ref } from "vue";
import { useI18n } from "vue-i18n";
import type { SaveSchema } from "@/__generated__";
import EmptySaves from "@/components/common/EmptyStates/EmptySaves.vue";
import storeAuth from "@/stores/auth";
@@ -10,6 +11,7 @@ import type { Events } from "@/types/emitter";
import { formatBytes, formatTimestamp } from "@/utils";
import { getEmptyCoverImage } from "@/utils/covers";
const { t, locale } = useI18n();
const auth = storeAuth();
const { scopes } = storeToRefs(auth);
const props = defineProps<{ rom: DetailedRom }>();
@@ -181,7 +183,7 @@ function onCardClick(save: SaveSchema, event: MouseEvent) {
</v-col>
<v-col cols="12">
<v-chip size="x-small" label>
Updated: {{ formatTimestamp(save.updated_at) }}
{{ t("rom.updated") }}: {{ formatTimestamp(save.updated_at, locale) }}
</v-chip>
</v-col>
</v-row>

View File

@@ -2,6 +2,7 @@
import type { Emitter } from "mitt";
import { storeToRefs } from "pinia";
import { inject, ref } from "vue";
import { useI18n } from "vue-i18n";
import type { StateSchema } from "@/__generated__";
import EmptySates from "@/components/common/EmptyStates/EmptyStates.vue";
import storeAuth from "@/stores/auth";
@@ -10,6 +11,7 @@ import type { Events } from "@/types/emitter";
import { formatBytes, formatTimestamp } from "@/utils";
import { getEmptyCoverImage } from "@/utils/covers";
const { t, locale } = useI18n();
const auth = storeAuth();
const { scopes } = storeToRefs(auth);
const props = defineProps<{ rom: DetailedRom }>();
@@ -183,7 +185,7 @@ function onCardClick(state: StateSchema, event: MouseEvent) {
</v-col>
<v-col cols="12">
<v-chip size="x-small" label>
Updated: {{ formatTimestamp(state.updated_at) }}
{{ t("rom.updated") }}: {{ formatTimestamp(state.updated_at, locale) }}
</v-chip>
</v-col>
</v-row>

View File

@@ -1,6 +1,7 @@
<script setup lang="ts">
import { storeToRefs } from "pinia";
import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { useDisplay } from "vuetify";
import FavBtn from "@/components/common/Game/FavBtn.vue";
import MissingFromFSIcon from "@/components/common/MissingFromFSIcon.vue";
@@ -11,9 +12,10 @@ import type { DetailedRom } from "@/stores/roms";
const props = defineProps<{ rom: DetailedRom }>();
const { smAndDown } = useDisplay();
const { locale } = useI18n();
const releaseDate = new Date(
Number(props.rom.metadatum.first_release_date),
).toLocaleDateString("en-US", {
).toLocaleDateString(locale.value.replace("_", "-"), {
day: "2-digit",
month: "short",
year: "numeric",

View File

@@ -5,10 +5,13 @@ import {
formatDuration,
} from "date-fns";
import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { formatTimestamp } from "@/utils";
import { TaskStatusItem, type TaskStatusResponse } from "@/utils/tasks";
import TaskProgressDisplay from "./tasks/TaskProgressDisplay.vue";
const { locale } = useI18n();
const props = defineProps<{
task: TaskStatusResponse;
}>();
@@ -89,6 +92,7 @@ const taskDistanceFromNow = computed(() => {
:title="
formatTimestamp(
task.started_at || task.enqueued_at || task.created_at,
locale,
)
"
>

View File

@@ -13,7 +13,7 @@ import storeUsers, { type User } from "@/stores/users";
import type { Events } from "@/types/emitter";
import { defaultAvatarPath, formatTimestamp, getRoleIcon } from "@/utils";
const { t } = useI18n();
const { t, locale } = useI18n();
const userSearch = ref("");
const emitter = inject<Emitter<Events>>("emitter");
const usersStore = storeUsers();
@@ -156,7 +156,7 @@ onMounted(() => {
</v-list-item>
</template>
<template #item.last_active="{ item }">
{{ formatTimestamp(item.last_active) }}
{{ formatTimestamp(item.last_active, locale) }}
</template>
<template #item.enabled="{ item }">
<v-switch

View File

@@ -2,14 +2,16 @@
import { useLocalStorage } from "@vueuse/core";
import { identity } from "lodash";
import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { type SimpleRom } from "@/stores/roms";
import {
languageToEmoji,
regionToEmoji,
getEmojiForStatus,
getTextForStatus,
getI18nKeyForStatus,
} from "@/utils";
const { t } = useI18n();
const props = defineProps<{ rom: SimpleRom }>();
const showRegions = useLocalStorage("settings.showRegions", true);
const showLanguages = useLocalStorage("settings.showLanguages", true);
@@ -54,7 +56,7 @@ const playingStatus = computed(() => {
v-if="playingStatus && showStatus"
class="translucent mr-1 mt-1 px-2"
density="compact"
:title="getTextForStatus(playingStatus)"
:title="t(getI18nKeyForStatus(playingStatus) || '')"
>
{{ getEmojiForStatus(playingStatus) }}
</v-chip>

View File

@@ -10,7 +10,7 @@ import type { Events } from "@/types/emitter";
import { formatBytes, formatTimestamp } from "@/utils";
import { getEmptyCoverImage } from "@/utils/covers";
const { t } = useI18n();
const { t, locale } = useI18n();
const { mdAndUp } = useDisplay();
const show = ref(false);
const rom = ref<DetailedRom | null>(null);
@@ -85,7 +85,7 @@ function closeDialog() {
{{ formatBytes(save.file_size_bytes) }}
</v-chip>
<v-chip size="x-small" label>
Updated: {{ formatTimestamp(save.updated_at) }}
{{ t("rom.updated") }}: {{ formatTimestamp(save.updated_at, locale) }}
</v-chip>
</v-row>
</v-card-text>

View File

@@ -10,7 +10,7 @@ import type { Events } from "@/types/emitter";
import { formatBytes, formatTimestamp } from "@/utils";
import { getEmptyCoverImage } from "@/utils/covers";
const { t } = useI18n();
const { t, locale } = useI18n();
const { mdAndUp } = useDisplay();
const show = ref(false);
const rom = ref<DetailedRom | null>(null);
@@ -85,7 +85,7 @@ function closeDialog() {
{{ formatBytes(state.file_size_bytes) }}
</v-chip>
<v-chip size="x-small" label>
Updated: {{ formatTimestamp(state.updated_at) }}
{{ t("rom.updated") }}: {{ formatTimestamp(state.updated_at, locale) }}
</v-chip>
</v-row>
</v-card-text>

View File

@@ -3,6 +3,7 @@ import { useLocalStorage } from "@vueuse/core";
import type { Emitter } from "mitt";
import { storeToRefs } from "pinia";
import { computed, inject } from "vue";
import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router";
import AdminMenu from "@/components/common/Game/AdminMenu.vue";
import PlayBtn from "@/components/common/Game/PlayBtn.vue";
@@ -19,6 +20,8 @@ import storeRoms, { type SimpleRom } from "@/stores/roms";
import type { Events } from "@/types/emitter";
import { formatBytes, languageToEmoji, regionToEmoji } from "@/utils";
const { locale } = useI18n();
withDefaults(
defineProps<{
showPlatformIcon?: boolean;
@@ -330,7 +333,7 @@ function updateOptions({ sortBy }: { sortBy: SortBy }) {
</div>
<div class="game-list-table-cell d-table-cell px-4">
<span v-if="item.created_at" class="text-no-wrap">{{
new Date(item.created_at).toLocaleDateString("en-US", {
new Date(item.created_at).toLocaleDateString(locale.replace("_", "-"), {
day: "2-digit",
month: "short",
year: "numeric",
@@ -341,7 +344,7 @@ function updateOptions({ sortBy }: { sortBy: SortBy }) {
<div class="game-list-table-cell d-table-cell px-4">
<span v-if="item.metadatum.first_release_date" class="text-no-wrap">{{
new Date(item.metadatum.first_release_date).toLocaleDateString(
"en-US",
locale.replace("_", "-"),
{
day: "2-digit",
month: "short",

View File

@@ -44,7 +44,7 @@ const romsStore = storeRoms();
const heartbeatStore = storeHeartbeat();
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const { t, locale } = useI18n();
const rom = ref<DetailedRomSchema | null>(null);
const playerState = ref<PlayerState>("loading");
@@ -69,7 +69,7 @@ const releaseDate = computed(() => {
if (!rom.value?.metadatum.first_release_date) return null;
return new Date(
Number(rom.value.metadatum.first_release_date),
).toLocaleDateString("en-US", {
).toLocaleDateString(locale.value.replace("_", "-"), {
day: "2-digit",
month: "short",
year: "numeric",

View File

@@ -91,5 +91,15 @@
"unmatch": "Odpojit ROM",
"unmatch-success": "ROM úspěšně odpojena",
"unselect-all": "Zrušit výběr všeho",
"update-success": "ROM úspěšně aktualizována!"
"update-success": "ROM úspěšně aktualizována!",
"save-data": "Uložená data",
"status-backlogged": "Odloženo",
"status-now-playing": "Právě hraji",
"status-incomplete": "Nedokončeno",
"status-finished": "Dokončeno",
"status-completed-100": "Dokončeno na 100%",
"status-retired": "Opuštěno",
"status-never-playing": "Nikdy nebudu hrát",
"status-hidden": "Skryté",
"updated": "Aktualizováno"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "Zuweisung aufheben",
"unmatch-success": "ROM-Zuweisung erfolgreich aufgehoben",
"unselect-all": "Alles abwählen",
"update-success": "ROM erfolgreich aktualisiert!"
"update-success": "ROM erfolgreich aktualisiert!",
"save-data": "Speicherdaten",
"status-backlogged": "Vorgemerkt",
"status-now-playing": "Wird gespielt",
"status-incomplete": "Unvollständig",
"status-finished": "Beendet",
"status-completed-100": "100% abgeschlossen",
"status-retired": "Aufgegeben",
"status-never-playing": "Nie spielen",
"status-hidden": "Versteckt",
"updated": "Aktualisiert"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "Unmatch ROM",
"unmatch-success": "ROM unmatched successfully",
"unselect-all": "Unselect all",
"update-success": "ROM updated successfully!"
"update-success": "ROM updated successfully!",
"save-data": "Save data",
"status-backlogged": "Backlogged",
"status-now-playing": "Now Playing",
"status-incomplete": "Incomplete",
"status-finished": "Finished",
"status-completed-100": "Completed 100%",
"status-retired": "Retired",
"status-never-playing": "Never Playing",
"status-hidden": "Hidden",
"updated": "Updated"
}

View File

@@ -91,5 +91,15 @@
"community-notes": "Community Notes",
"confirm-delete-note": "Are you sure you want to delete the note \"{title}\"?",
"unmatch-success": "ROM unmatched successfully",
"update-success": "ROM updated successfully!"
"update-success": "ROM updated successfully!",
"save-data": "Save data",
"status-backlogged": "Backlogged",
"status-now-playing": "Now Playing",
"status-incomplete": "Incomplete",
"status-finished": "Finished",
"status-completed-100": "Completed 100%",
"status-retired": "Retired",
"status-never-playing": "Never Playing",
"status-hidden": "Hidden",
"updated": "Updated"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "Desvincular ROM",
"unmatch-success": "ROM desvinculada con éxito",
"unselect-all": "Deseleccionar todos",
"update-success": "¡ROM actualizada con éxito!"
"update-success": "¡ROM actualizada con éxito!",
"save-data": "Datos guardados",
"status-backlogged": "Pendiente",
"status-now-playing": "Jugando",
"status-incomplete": "Incompleto",
"status-finished": "Terminado",
"status-completed-100": "Completado 100%",
"status-retired": "Abandonado",
"status-never-playing": "Nunca jugar",
"status-hidden": "Oculto",
"updated": "Actualizado"
}

View File

@@ -13,7 +13,7 @@
"collections": "Collections",
"community-notes": "Notes de la Communauté",
"companies": "Entreprises",
"completion": "Achèvement",
"completion": "Complétion",
"completionist": "Complétionniste",
"confirm-delete-note": "Êtes-vous sûr de vouloir supprimer la note \"{title}\" ?",
"copy-link": "Copier le lien de téléchargement",
@@ -62,18 +62,18 @@
"note-content": "Contenu de la Note",
"note-title": "Titre de la Note",
"note-title-exists": "Une note avec ce titre existe déjà",
"now-playing": "En cours de lecture",
"now-playing": "En train de jouer",
"personal": "Personnel",
"private": "Privée",
"public": "Publique",
"public-notes": "Notes publiques",
"rating": "Évaluation",
"rating": "Note",
"refresh-metadata": "Actualiser les métadonnées",
"regions": "Régions",
"related-content": "Contenu connexe",
"remove-from-collection": "Retirer de la collection",
"remove-from-favorites": "Retirer des favoris",
"remove-from-playing": "Retirer de jouant",
"remove-from-playing": "Retirer des jeux en cours",
"removing-from-collection": "Retrait de {n} ROMs de la collection",
"removing-title": "Suppression de {n} jeu de RomM | Suppression de {n} jeux de RomM",
"rename-file-details": "Le fichier sera renommé de {from} à {to}. Les tags du nom de fichier ne seront pas affectés.",
@@ -91,5 +91,15 @@
"unmatch": "Dissocier le ROM",
"unmatch-success": "ROM dissociée avec succès",
"unselect-all": "Désélectionner tous",
"update-success": "ROM mise à jour avec succès !"
"update-success": "ROM mise à jour avec succès !",
"save-data": "Sauvegardes",
"status-backlogged": "En attente",
"status-now-playing": "En train de jouer",
"status-incomplete": "Incomplet",
"status-finished": "Terminé",
"status-completed-100": "Complété à 100%",
"status-retired": "Abandonné",
"status-never-playing": "Jamais joué",
"status-hidden": "Caché",
"updated": "Mis à jour"
}

View File

@@ -81,7 +81,7 @@
"show-stats": "Afficher les statistiques",
"show-stats-desc": "Afficher le résumé des statistiques sur la page d'accueil",
"show-status": "Afficher le statut",
"show-status-desc": "Afficher les icônes de statut dans la galerie (en attente, en cours de lecture, terminé, etc.)",
"show-status-desc": "Afficher les icônes de statut dans la galerie (en attente, en train de jouer, terminé, etc.)",
"show-virtual-collections": "Afficher les collections générées automatiquement",
"show-virtual-collections-desc": "Affiché sur la page d'accueil et dans la barre latérale des collections.",
"stopped": "Arrêté",

View File

@@ -91,5 +91,15 @@
"unmatch": "Nem egyező ROM",
"unmatch-success": "A ROM sikeresen nem egyeztetettként lett jelölve",
"unselect-all": "Minden kijelölés visszavonása",
"update-success": "A ROM frissítése sikeresen megtörtént!"
"update-success": "A ROM frissítése sikeresen megtörtént!",
"save-data": "Mentések",
"status-backlogged": "Függőben",
"status-now-playing": "Most játszom",
"status-incomplete": "Befejezetlen",
"status-finished": "Befejezett",
"status-completed-100": "100%-ban teljesített",
"status-retired": "Félretett",
"status-never-playing": "Soha nem játszom",
"status-hidden": "Rejtett",
"updated": "Frissítve"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "Rimuovi associazione rom",
"unmatch-success": "Associazione ROM rimossa con successo",
"unselect-all": "Deseleziona tutto",
"update-success": "ROM aggiornata con successo!"
"update-success": "ROM aggiornata con successo!",
"save-data": "Dati di salvataggio",
"status-backlogged": "In attesa",
"status-now-playing": "In gioco",
"status-incomplete": "Incompleto",
"status-finished": "Finito",
"status-completed-100": "Completato 100%",
"status-retired": "Abbandonato",
"status-never-playing": "Mai giocare",
"status-hidden": "Nascosto",
"updated": "Aggiornato"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "検索結果無し",
"unmatch-success": "ROMの関連付けが正常に解除されました",
"unselect-all": "すべて選択解除",
"update-success": "ROMが正常に更新されました"
"update-success": "ROMが正常に更新されました",
"save-data": "セーブデータ",
"status-backlogged": "未処理",
"status-now-playing": "プレイ中",
"status-incomplete": "未完了",
"status-finished": "クリア済み",
"status-completed-100": "100%完了",
"status-retired": "中断",
"status-never-playing": "プレイしない",
"status-hidden": "非表示",
"updated": "更新日時"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "DB 대응 해제",
"unmatch-success": "ROM 연결이 성공적으로 해제되었습니다",
"unselect-all": "모두 선택 해제",
"update-success": "ROM이 성공적으로 업데이트되었습니다!"
"update-success": "ROM이 성공적으로 업데이트되었습니다!",
"save-data": "저장 데이터",
"status-backlogged": "나중에 플레이",
"status-now-playing": "현재 플레이 중",
"status-incomplete": "미완료",
"status-finished": "완료",
"status-completed-100": "100% 완료",
"status-retired": "중단",
"status-never-playing": "플레이 안 함",
"status-hidden": "숨김",
"updated": "업데이트"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "Odłącz ROM",
"unmatch-success": "ROM został pomyślnie odłączony",
"unselect-all": "Odznacz wszystkie",
"update-success": "ROM został pomyślnie zaktualizowany!"
"update-success": "ROM został pomyślnie zaktualizowany!",
"save-data": "Dane zapisu",
"status-backlogged": "Zaległe",
"status-now-playing": "Aktualnie grane",
"status-incomplete": "Nieukończone",
"status-finished": "Ukończone",
"status-completed-100": "Ukończone w 100%",
"status-retired": "Porzucone",
"status-never-playing": "Nigdy nie gram",
"status-hidden": "Ukryte",
"updated": "Zaktualizowano"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "Desvincular ROM",
"unmatch-success": "ROM desvinculada com sucesso",
"unselect-all": "Desselecionar todos",
"update-success": "ROM atualizada com sucesso!"
"update-success": "ROM atualizada com sucesso!",
"save-data": "Dados salvos",
"status-backlogged": "Em espera",
"status-now-playing": "Jogando agora",
"status-incomplete": "Incompleto",
"status-finished": "Terminado",
"status-completed-100": "Completado 100%",
"status-retired": "Abandonado",
"status-never-playing": "Nunca jogar",
"status-hidden": "Oculto",
"updated": "Atualizado"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "Dissociază ROM-ul",
"unmatch-success": "ROM-ul a fost disociat cu succes",
"unselect-all": "Deselectează toate",
"update-success": "ROM-ul a fost actualizat cu succes!"
"update-success": "ROM-ul a fost actualizat cu succes!",
"save-data": "Date salvate",
"status-backlogged": "În așteptare",
"status-now-playing": "Joc acum",
"status-incomplete": "Incomplet",
"status-finished": "Terminat",
"status-completed-100": "Completat 100%",
"status-retired": "Abandonat",
"status-never-playing": "Nu voi juca niciodată",
"status-hidden": "Ascuns",
"updated": "Actualizat"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "Отменить совпадение",
"unmatch-success": "Связь с ROM успешно отменена",
"unselect-all": "Отменить выбор всех",
"update-success": "ROM успешно обновлён!"
"update-success": "ROM успешно обновлён!",
"save-data": "Сохранения",
"status-backlogged": "Отложено",
"status-now-playing": "Сейчас играю",
"status-incomplete": "Не завершено",
"status-finished": "Пройдено",
"status-completed-100": "Пройдено на 100%",
"status-retired": "Заброшено",
"status-never-playing": "Никогда не играть",
"status-hidden": "Скрыто",
"updated": "Обновлено"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "未匹配的 ROM",
"unmatch-success": "ROM 取消匹配成功",
"unselect-all": "取消选择所有",
"update-success": "ROM 更新成功!"
"update-success": "ROM 更新成功!",
"save-data": "存档数据",
"status-backlogged": "待办",
"status-now-playing": "正在游玩",
"status-incomplete": "未完成",
"status-finished": "已通关",
"status-completed-100": "100%完成",
"status-retired": "已搁置",
"status-never-playing": "不玩",
"status-hidden": "隐藏",
"updated": "更新时间"
}

View File

@@ -91,5 +91,15 @@
"unmatch": "清除匹配資料",
"unmatch-success": "ROM 取消匹配成功",
"unselect-all": "取消選擇所有",
"update-success": "ROM 更新成功!"
"update-success": "ROM 更新成功!",
"save-data": "存檔資料",
"status-backlogged": "待遊玩",
"status-now-playing": "正在遊玩",
"status-incomplete": "未完成",
"status-finished": "已破關",
"status-completed-100": "100%完成",
"status-retired": "已擱置",
"status-never-playing": "不玩",
"status-hidden": "隱藏",
"updated": "更新時間"
}

View File

@@ -156,13 +156,16 @@ export function formatBytes(bytes: number, decimals = 2) {
* Format a timestamp to a human-readable string.
*
* @param timestamp The timestamp to format.
* @param locale The locale to use for formatting (e.g., "fr_FR" or "fr-FR"). Defaults to "en-US".
* @returns The formatted timestamp.
*/
export function formatTimestamp(timestamp: string | null) {
export function formatTimestamp(timestamp: string | null, locale: string = "en-US") {
if (!timestamp) return "-";
const date = new Date(timestamp);
return date.toLocaleString("en-US");
// Convert locale format from fr_FR to fr-FR for browser compatibility
const browserLocale = locale.replace("_", "-");
return date.toLocaleString(browserLocale);
}
/**
@@ -606,20 +609,20 @@ export function isRuffleEmulationSupported(
type PlayingStatus = RomUserStatus | "backlogged" | "now_playing" | "hidden";
/**
* Map of ROM statuses to their corresponding emoji and text.
* Map of ROM statuses to their corresponding emoji, text, and i18n key.
*/
export const romStatusMap: Record<
PlayingStatus,
{ emoji: string; text: string }
{ emoji: string; text: string; i18nKey: string }
> = {
backlogged: { emoji: "🔜", text: "Backlogged" },
now_playing: { emoji: "🕹️", text: "Now Playing" },
incomplete: { emoji: "🚧", text: "Incomplete" },
finished: { emoji: "🏁", text: "Finished" },
completed_100: { emoji: "💯", text: "Completed 100%" },
retired: { emoji: "🏴", text: "Retired" },
never_playing: { emoji: "🚫", text: "Never Playing" },
hidden: { emoji: "👻", text: "Hidden" },
backlogged: { emoji: "🔜", text: "Backlogged", i18nKey: "rom.status-backlogged" },
now_playing: { emoji: "🕹️", text: "Now Playing", i18nKey: "rom.status-now-playing" },
incomplete: { emoji: "🚧", text: "Incomplete", i18nKey: "rom.status-incomplete" },
finished: { emoji: "🏁", text: "Finished", i18nKey: "rom.status-finished" },
completed_100: { emoji: "💯", text: "Completed 100%", i18nKey: "rom.status-completed-100" },
retired: { emoji: "🏴", text: "Retired", i18nKey: "rom.status-retired" },
never_playing: { emoji: "🚫", text: "Never Playing", i18nKey: "rom.status-never-playing" },
hidden: { emoji: "👻", text: "Hidden", i18nKey: "rom.status-hidden" },
};
/**
@@ -657,6 +660,20 @@ export function getTextForStatus(status: PlayingStatus) {
}
}
/**
* Get the i18n key for a given ROM status.
*
* @param status The ROM status.
* @returns The corresponding i18n key (e.g., "rom.status-backlogged").
*/
export function getI18nKeyForStatus(status: PlayingStatus) {
if (status) {
return romStatusMap[status].i18nKey;
} else {
return null;
}
}
/**
* Get the status key for a given text.
*

View File

@@ -204,7 +204,7 @@ watch(
<v-tab v-if="currentRom.has_manual" value="manual">
{{ t("rom.manual") }}
</v-tab>
<v-tab value="gamedata"> Game data </v-tab>
<v-tab value="gamedata">{{ t("rom.save-data") }}</v-tab>
<v-tab value="personal">
{{ t("rom.personal") }}
</v-tab>

View File

@@ -23,7 +23,7 @@ import Player from "@/views/Player/EmulatorJS/Player.vue";
const EMULATORJS_VERSION = "4.2.3";
const { t } = useI18n();
const { t, locale } = useI18n();
const { smAndDown } = useDisplay();
const route = useRoute();
const auth = storeAuth();
@@ -330,8 +330,8 @@ onBeforeUnmount(async () => {
<v-row no-gutters>
<v-col cols="12">
<v-list-item rounded class="px-1 text-caption">
Updated:
{{ formatTimestamp(selectedState.updated_at) }}
{{ t("rom.updated") }}:
{{ formatTimestamp(selectedState.updated_at, locale) }}
<span class="text-grey text-caption"
>({{
formatRelativeDate(
@@ -417,8 +417,8 @@ onBeforeUnmount(async () => {
<v-row no-gutters>
<v-col cols="12">
<v-list-item rounded class="px-1 text-caption">
Updated:
{{ formatTimestamp(selectedSave.updated_at) }}
{{ t("rom.updated") }}:
{{ formatTimestamp(selectedSave.updated_at, locale) }}
<span class="text-grey text-caption"
>({{
formatRelativeDate(selectedSave.updated_at)
@@ -503,7 +503,7 @@ onBeforeUnmount(async () => {
<v-row class="ga-1" no-gutters>
<v-col cols="12">
<v-list-item rounded class="pa-1 text-caption">
Updated: {{ formatTimestamp(state.updated_at) }}
{{ t("rom.updated") }}: {{ formatTimestamp(state.updated_at, locale) }}
<span class="ml-1 text-grey text-caption"
>({{
formatRelativeDate(state.updated_at)
@@ -574,7 +574,7 @@ onBeforeUnmount(async () => {
<v-row class="ga-1" no-gutters>
<v-col cols="12">
<v-list-item rounded class="pa-1 text-caption">
Updated: {{ formatTimestamp(save.updated_at) }}
{{ t("rom.updated") }}: {{ formatTimestamp(save.updated_at, locale) }}
<span class="ml-1 text-grey text-caption"
>({{ formatRelativeDate(save.updated_at) }})</span
>