Update Japanese translation and add localization support in notification (#1706)

This commit is contained in:
Yuki
2026-03-27 13:31:12 +09:00
committed by GitHub
parent 1e5cc91fc2
commit 3dc7b07dd4
9 changed files with 990 additions and 276 deletions

View File

@@ -1,7 +1,7 @@
<template> <template>
<Dialog v-model:open="isOpen"> <Dialog v-model:open="isOpen">
<DialogContent <DialogContent
class="border border-border bg-background/85 shadow-lg backdrop-blur-xl backdrop-saturate-[1.4] sm:max-w-xl" class="border border-border bg-background/85 shadow-lg backdrop-blur-xl backdrop-saturate-[1.4] sm:max-w-3xl"
:show-close-button="false" :show-close-button="false"
@escape-key-down="handleDismiss" @escape-key-down="handleDismiss"
@pointer-down-outside="handleDismiss" @pointer-down-outside="handleDismiss"

View File

@@ -1,7 +1,7 @@
<template> <template>
<Dialog v-model:open="whatsNewDialog.visible"> <Dialog v-model:open="whatsNewDialog.visible">
<DialogContent <DialogContent
class="border border-border bg-background/88 p-5 shadow-lg backdrop-blur-xl backdrop-saturate-[1.4] sm:max-w-xl" class="border border-border bg-background/88 p-5 shadow-lg backdrop-blur-xl backdrop-saturate-[1.4] sm:max-w-3xl"
:show-close-button="false" :show-close-button="false"
@escape-key-down="handleDismiss" @escape-key-down="handleDismiss"
@pointer-down-outside="handleDismiss" @pointer-down-outside="handleDismiss"

View File

@@ -490,9 +490,10 @@ export function selectAvatarWithConfirmation(id) {
*/ */
export async function selectAvatarWithoutConfirmation(id) { export async function selectAvatarWithoutConfirmation(id) {
const userStore = useUserStore(); const userStore = useUserStore();
const t = i18n.global.t;
if (userStore.currentUser.currentAvatar === id) { if (userStore.currentUser.currentAvatar === id) {
toast.info('Avatar already selected'); toast.info(t('message.avatar.already_selected'));
return; return;
} }
return avatarRequest return avatarRequest
@@ -500,7 +501,7 @@ export async function selectAvatarWithoutConfirmation(id) {
avatarId: id avatarId: id
}) })
.then(() => { .then(() => {
toast.success('Avatar changed'); toast.success(t('message.avatar.selected'));
}); });
} }

View File

@@ -972,6 +972,7 @@
"layout_table": "Notifications Tab", "layout_table": "Notifications Tab",
"notification_filter": "Notification Filters", "notification_filter": "Notification Filters",
"test_notification": "Send Test Notification", "test_notification": "Send Test Notification",
"test_message": "Test notification.",
"steamvr_notifications": { "steamvr_notifications": {
"header": "SteamVR Notifications", "header": "SteamVR Notifications",
"steamvr_overlay": "SteamVR Overlay", "steamvr_overlay": "SteamVR Overlay",
@@ -2657,6 +2658,8 @@
"create_failed": "Failed to create instance" "create_failed": "Failed to create instance"
}, },
"avatar": { "avatar": {
"selected": "Avatar changed",
"already_selected": "Avatar already selected",
"change_moderation_failed": "Failed to change avatar moderation", "change_moderation_failed": "Failed to change avatar moderation",
"fallback_changed": "Fallback avatar changed", "fallback_changed": "Fallback avatar changed",
"blocked": "Avatar blocked", "blocked": "Avatar blocked",
@@ -2710,7 +2713,9 @@
}, },
"gallery": { "gallery": {
"uploaded": "Gallery image uploaded", "uploaded": "Gallery image uploaded",
"failed": "Failed to upload gallery image" "failed": "Failed to upload gallery image",
"profile_pic_changed": "Profile picture changed",
"profile_icon_changed": "Profile icon changed"
}, },
"upload": { "upload": {
"loading": "Uploading", "loading": "Uploading",
@@ -2773,6 +2778,44 @@
"copy_failed": "Copy failed", "copy_failed": "Copy failed",
"error": "Error" "error": "Error"
}, },
"notifications": {
"has_joined": "has joined",
"has_left": "has left",
"is_joining": "is joining",
"gps": "is in {location}",
"online_location": "has logged in to {location}",
"online": "has logged in",
"offline": "has logged out",
"status_update": "status is now {status} {description}",
"invite": "has invited you to {location} {message}",
"request_invite": "has requested an invite {message}",
"invite_response": "has responded to your invite {message}",
"request_invite_response": "has responded to your invite request {message}",
"friend_request": "has sent you a friend request",
"friend": "is now your friend",
"unfriend": "is no longer your friend",
"trust_level": "Trust level is now {trustLevel}",
"display_name": "changed their name to {displayName}",
"group_announcement_title": "Group Announcement",
"group_informative_title": "Group Informative",
"group_invite_title": "Group Invite",
"group_join_request_title": "Group Join Request",
"group_transfer_request_title": "Group Transfer Request",
"group_queue_ready_title": "Instance Queue Ready",
"instance_closed_title": "Instance Closed",
"portal_spawn_name": "has spawned a portal to {location}",
"portal_spawn": "User has spawned a portal",
"avatar_change": "changed into avatar {avatar}",
"chat_message": "said: {message}",
"blocked_player_joined": "Blocked user has joined",
"blocked_player_left": "Blocked user has left",
"muted_player_joined": "Muted user has joined",
"muted_player_left": "Muted user has left",
"blocked": "has blocked you",
"unblocked": "has unblocked you",
"muted": "has muted you",
"unmuted": "has unmuted you"
},
"status": { "status": {
"title": "VRChat Status" "title": "VRChat Status"
}, },

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
const toolCategories = [ const toolCategories = [
{ key: 'image', labelKey: 'view.tools.pictures.header' }, { key: 'image', labelKey: 'view.tools.pictures.header' },
{ key: 'shortcuts', labelKey: 'view.tools.shortcuts.header' }, { key: 'shortcuts', labelKey: 'view.tools.shortcuts.header' },
{ key: 'system', labelKey: 'view.tools.system_tools.header' },
{ key: 'group', labelKey: 'view.tools.group.header' }, { key: 'group', labelKey: 'view.tools.group.header' },
{ key: 'system', labelKey: 'view.tools.system_tools.header' },
{ key: 'user', labelKey: 'view.tools.export.header' }, { key: 'user', labelKey: 'view.tools.export.header' },
{ key: 'other', labelKey: 'view.tools.other.header' } { key: 'other', labelKey: 'view.tools.other.header' }
]; ];

View File

@@ -1,4 +1,5 @@
import { displayLocation } from './locationParser'; import { displayLocation } from './locationParser';
import { i18n } from '../../plugins/i18n';
/** /**
* Extracts the notification title and body from a notification object. * Extracts the notification title and body from a notification object.
@@ -13,128 +14,131 @@ import { displayLocation } from './locationParser';
export function getNotificationMessage(noty, message, displayNameOverride) { export function getNotificationMessage(noty, message, displayNameOverride) {
const name = displayNameOverride || noty.displayName; const name = displayNameOverride || noty.displayName;
const sender = displayNameOverride || noty.senderUsername; const sender = displayNameOverride || noty.senderUsername;
const t = i18n.global.t;
switch (noty.type) { switch (noty.type) {
case 'OnPlayerJoined': case 'OnPlayerJoined':
return { title: name, body: 'has joined' }; return { title: name, body: t('notifications.has_joined') };
case 'OnPlayerLeft': case 'OnPlayerLeft':
return { title: name, body: 'has left' }; return { title: name, body: t('notifications.has_left') };
case 'OnPlayerJoining': case 'OnPlayerJoining':
return { title: name, body: 'is joining' }; return { title: name, body: t('notifications.is_joining') };
case 'GPS': case 'GPS':
return { return {
title: name, title: name,
body: `is in ${displayLocation( body: t('notifications.gps', { location: displayLocation(
noty.location, noty.location,
noty.worldName, noty.worldName,
noty.groupName noty.groupName
)}` )})
}; };
case 'Online': { case 'Online': {
let locationName = ''; let locationName = '';
if (noty.worldName) { if (noty.worldName) {
locationName = ` to ${displayLocation( return {
noty.location, title: name,
noty.worldName, body: t('notifications.online_location', { location: displayLocation(
noty.groupName noty.location,
)}`; noty.worldName,
noty.groupName
) })
};
} }
return { return {
title: name, title: name, body: t('notifications.online')
body: `has logged in${locationName}`
}; };
} }
case 'Offline': case 'Offline':
return { title: name, body: 'has logged out' }; return { title: name, body: t('notifications.offline') };
case 'Status': case 'Status':
return { return {
title: name, title: name,
body: `status is now ${noty.status} ${noty.statusDescription}` body: t('notifications.status_update', { status: noty.status, description: noty.statusDescription })
}; };
case 'invite': case 'invite':
return { return {
title: sender, title: sender,
body: `has invited you to ${displayLocation( body: t('notifications.invite', { location: displayLocation(
noty.details.worldId, noty.details.worldId,
noty.details.worldName noty.details.worldName
)}${message}` ), message })
}; };
case 'requestInvite': case 'requestInvite':
return { return {
title: sender, title: sender,
body: `has requested an invite${message}` body: t('notifications.request_invite', { message })
}; };
case 'inviteResponse': case 'inviteResponse':
return { return {
title: sender, title: sender,
body: `has responded to your invite${message}` body: t('notifications.invite_response', { message })
}; };
case 'requestInviteResponse': case 'requestInviteResponse':
return { return {
title: sender, title: sender,
body: `has responded to your invite request${message}` body: t('notifications.request_invite_response', { message })
}; };
case 'friendRequest': case 'friendRequest':
return { return {
title: sender, title: sender,
body: 'has sent you a friend request' body: t('notifications.friend_request')
}; };
case 'Friend': case 'Friend':
return { title: name, body: 'is now your friend' }; return { title: name, body: t('notifications.friend') };
case 'Unfriend': case 'Unfriend':
return { return {
title: name, title: name,
body: 'is no longer your friend' body: t('notifications.unfriend')
}; };
case 'TrustLevel': case 'TrustLevel':
return { return {
title: name, title: name,
body: `trust level is now ${noty.trustLevel}` body: t('notifications.trust_level', { trustLevel: noty.trustLevel })
}; };
case 'DisplayName': case 'DisplayName':
return { return {
title: displayNameOverride || noty.previousDisplayName, title: displayNameOverride || noty.previousDisplayName,
body: `changed their name to ${noty.displayName}` body: t('notifications.display_name', { displayName: noty.displayName })
}; };
case 'boop': case 'boop':
return { title: sender, body: noty.message }; return { title: sender, body: noty.message };
case 'groupChange': case 'groupChange':
return { title: sender, body: noty.message }; return { title: sender, body: noty.message };
case 'group.announcement': case 'group.announcement':
return { title: 'Group Announcement', body: noty.message }; return { title: t('notifications.group_announcement_title'), body: noty.message };
case 'group.informative': case 'group.informative':
return { title: 'Group Informative', body: noty.message }; return { title: t('notifications.group_informative_title'), body: noty.message };
case 'group.invite': case 'group.invite':
return { title: 'Group Invite', body: noty.message }; return { title: t('notifications.group_invite_title'), body: noty.message };
case 'group.joinRequest': case 'group.joinRequest':
return { title: 'Group Join Request', body: noty.message }; return { title: t('notifications.group_join_request_title'), body: noty.message };
case 'group.transfer': case 'group.transfer':
return { title: 'Group Transfer Request', body: noty.message }; return { title: t('notifications.group_transfer_request_title'), body: noty.message };
case 'group.queueReady': case 'group.queueReady':
return { title: 'Instance Queue Ready', body: noty.message }; return { title: t('notifications.group_queue_ready_title'), body: noty.message };
case 'instance.closed': case 'instance.closed':
return { title: 'Instance Closed', body: noty.message }; return { title: t('notifications.instance_closed_title'), body: noty.message };
case 'PortalSpawn': case 'PortalSpawn':
if (name) { if (name) {
return { return {
title: name, title: name,
body: `has spawned a portal to ${displayLocation( body: t('notifications.portal_spawn_name', { location: displayLocation(
noty.instanceId, noty.instanceId,
noty.worldName, noty.worldName,
noty.groupName noty.groupName
)}` ) })
}; };
} }
return { title: '', body: 'User has spawned a portal' }; return { title: '', body: t('notifications.portal_spawn') };
case 'AvatarChange': case 'AvatarChange':
return { return {
title: name, title: name,
body: `changed into avatar ${noty.name}` body: t('notifications.avatar_change', { avatar: noty.name })
}; };
case 'ChatBoxMessage': case 'ChatBoxMessage':
return { return {
title: name, title: name,
body: `said ${noty.text}` body: t('notifications.chat_message', { message: noty.text })
}; };
case 'Event': case 'Event':
return { title: 'Event', body: noty.data }; return { title: 'Event', body: noty.data };
@@ -145,31 +149,31 @@ export function getNotificationMessage(noty, message, displayNameOverride) {
case 'BlockedOnPlayerJoined': case 'BlockedOnPlayerJoined':
return { return {
title: name, title: name,
body: 'Blocked user has joined' body: t('notifications.blocked_player_joined')
}; };
case 'BlockedOnPlayerLeft': case 'BlockedOnPlayerLeft':
return { return {
title: name, title: name,
body: 'Blocked user has left' body: t('notifications.blocked_player_left')
}; };
case 'MutedOnPlayerJoined': case 'MutedOnPlayerJoined':
return { return {
title: name, title: name,
body: 'Muted user has joined' body: t('notifications.muted_player_joined')
}; };
case 'MutedOnPlayerLeft': case 'MutedOnPlayerLeft':
return { return {
title: name, title: name,
body: 'Muted user has left' body: t('notifications.muted_player_left')
}; };
case 'Blocked': case 'Blocked':
return { title: name, body: 'has blocked you' }; return { title: name, body: t('notifications.blocked') };
case 'Unblocked': case 'Unblocked':
return { title: name, body: 'has unblocked you' }; return { title: name, body: t('notifications.unblocked') };
case 'Muted': case 'Muted':
return { title: name, body: 'has muted you' }; return { title: name, body: t('notifications.muted') };
case 'Unmuted': case 'Unmuted':
return { title: name, body: 'has unmuted you' }; return { title: name, body: t('notifications.unmuted') };
default: default:
return null; return null;
} }

View File

@@ -1198,7 +1198,7 @@ export const useNotificationStore = defineStore('Notification', () => {
playNoty({ playNoty({
type: 'Event', type: 'Event',
created_at: new Date().toJSON(), created_at: new Date().toJSON(),
data: 'Notification Test' data: t('view.settings.notifications.notifications.test_message')
}); });
} }

View File

@@ -896,7 +896,7 @@
profilePicOverride profilePicOverride
}) })
.then((args) => { .then((args) => {
toast.success('Profile picture changed'); toast.success(t('message.gallery.profile_pic_changed'));
return args; return args;
}); });
} }
@@ -963,7 +963,7 @@
userIcon userIcon
}) })
.then((args) => { .then((args) => {
toast.success('Icon changed'); toast.success(t('message.gallery.profile_icon_changed'));
return args; return args;
}); });
} }