improve i18n

This commit is contained in:
pa
2026-01-19 11:49:41 +09:00
parent 7303cd0b33
commit 1e25255ac5
34 changed files with 179 additions and 65 deletions

View File

@@ -311,7 +311,7 @@
shortName: props.shortname
})
.then((args) => {
toast.success('Self invite sent');
toast.success(t('message.invite.self_sent'));
return args;
});
};

View File

@@ -91,8 +91,9 @@
})
.then((args) => {
if (args.json[slot].message === I.messageSlot.message) {
toast.error("VRChat API didn't update message, try again");
throw new Error("VRChat API didn't update message, try again");
const errorMessage = t('message.invite.message_update_failed');
toast.error(errorMessage);
throw new Error(errorMessage);
} else {
toast('Invite message updated');
}
@@ -141,7 +142,7 @@
} else {
J.loading = false;
J.visible = false;
toast.success('Invite sent');
toast.success(t('message.invite.sent'));
}
};
inviteLoop();

View File

@@ -244,7 +244,7 @@
function sendInvite() {
modalStore
.confirm({
description: 'Continue? Invite',
description: t('confirm.invite'),
title: 'Confirm'
})
.then(({ ok }) => {
@@ -281,7 +281,7 @@
} else {
D.loading = false;
D.visible = false;
toast.success('Invite sent');
toast.success(t('message.invite.sent'));
}
};
inviteLoop();

View File

@@ -273,7 +273,7 @@
function sendGroupInvite() {
modalStore
.confirm({
description: 'Continue? Invite User(s) To Group',
description: t('confirm.invite_group'),
title: 'Confirm'
})
.then(({ ok }) => {

View File

@@ -309,7 +309,7 @@
shortName
})
.then((args) => {
toast.success('Self invite sent');
toast.success(t('message.invite.self_sent'));
return args;
});
}

View File

@@ -916,7 +916,7 @@
worldId: L.worldId
})
.then((args) => {
toast.success('Self invite sent');
toast.success(t('message.invite.self_sent'));
return args;
});
}

View File

@@ -1854,7 +1854,7 @@
D.id
)
.then((_args) => {
toast('Invite sent');
toast(t('message.invite.sent'));
return _args;
});
});

View File

@@ -975,7 +975,9 @@
case 'Trash2':
modalStore
.confirm({
description: `Continue? ${command}`,
description: t('confirm.command_question', {
command
}),
title: 'Confirm'
})
.then(({ ok }) => {

View File

@@ -3,6 +3,7 @@
import { PaginationEllipsis } from 'reka-ui';
import { cn } from '@/lib/utils';
import { reactiveOmit } from '@vueuse/core';
import { useI18n } from 'vue-i18n';
const props = defineProps({
asChild: { type: Boolean, required: false },
@@ -10,6 +11,8 @@
class: { type: null, required: false }
});
const { t } = useI18n();
const delegatedProps = reactiveOmit(props, 'class');
</script>
@@ -20,7 +23,9 @@
:class="cn('flex size-9 items-center justify-center text-[13px]', props.class)">
<slot>
<MoreHorizontal class="size-4" />
<span class="sr-only">More pages</span>
<span class="sr-only">
{{ t('table.pagination.more_pages') }}
</span>
</slot>
</PaginationEllipsis>
</template>

View File

@@ -4,6 +4,7 @@
import { buttonVariants } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { reactiveOmit } from '@vueuse/core';
import { useI18n } from 'vue-i18n';
const props = defineProps({
asChild: { type: Boolean, required: false },
@@ -12,6 +13,8 @@
class: { type: null, required: false }
});
const { t } = useI18n();
const delegatedProps = reactiveOmit(props, 'class', 'size');
const forwarded = useForwardProps(delegatedProps);
</script>
@@ -23,7 +26,9 @@
v-bind="forwarded">
<slot>
<ChevronLeftIcon />
<span class="hidden sm:block">First</span>
<span class="hidden sm:block">
{{ t('table.pagination.first') }}
</span>
</slot>
</PaginationFirst>
</template>

View File

@@ -4,6 +4,7 @@
import { buttonVariants } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { reactiveOmit } from '@vueuse/core';
import { useI18n } from 'vue-i18n';
const props = defineProps({
asChild: { type: Boolean, required: false },
@@ -12,6 +13,8 @@
class: { type: null, required: false }
});
const { t } = useI18n();
const delegatedProps = reactiveOmit(props, 'class', 'size');
const forwarded = useForwardProps(delegatedProps);
</script>
@@ -22,7 +25,9 @@
:class="cn(buttonVariants({ variant: 'ghost', size }), 'text-[13px] gap-1 px-2.5 sm:pr-2.5', props.class)"
v-bind="forwarded">
<slot>
<span class="hidden sm:block">Last</span>
<span class="hidden sm:block">
{{ t('table.pagination.last') }}
</span>
<ChevronRightIcon />
</slot>
</PaginationLast>

View File

@@ -4,6 +4,7 @@
import { buttonVariants } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { reactiveOmit } from '@vueuse/core';
import { useI18n } from 'vue-i18n';
const props = defineProps({
asChild: { type: Boolean, required: false },
@@ -12,6 +13,8 @@
class: { type: null, required: false }
});
const { t } = useI18n();
const delegatedProps = reactiveOmit(props, 'class', 'size');
const forwarded = useForwardProps(delegatedProps);
</script>
@@ -22,7 +25,9 @@
:class="cn(buttonVariants({ variant: 'ghost', size }), 'text-[13px] gap-1 px-2.5 sm:pr-2.5', props.class)"
v-bind="forwarded">
<slot>
<span class="hidden sm:block">Next</span>
<span class="hidden sm:block">
{{ t('table.pagination.next') }}
</span>
<ChevronRightIcon />
</slot>
</PaginationNext>

View File

@@ -4,6 +4,7 @@
import { buttonVariants } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { reactiveOmit } from '@vueuse/core';
import { useI18n } from 'vue-i18n';
const props = defineProps({
asChild: { type: Boolean, required: false },
@@ -12,6 +13,8 @@
class: { type: null, required: false }
});
const { t } = useI18n();
const delegatedProps = reactiveOmit(props, 'class', 'size');
const forwarded = useForwardProps(delegatedProps);
</script>
@@ -23,7 +26,9 @@
v-bind="forwarded">
<slot>
<ChevronLeftIcon />
<span class="hidden sm:block">Previous</span>
<span class="hidden sm:block">
{{ t('table.pagination.previous') }}
</span>
</slot>
</PaginationPrev>
</template>

View File

@@ -250,6 +250,13 @@
"filter_placeholder": "Filter",
"search_placeholder": "Search",
"refresh_tooltip": "Refresh",
"actions": {
"accept": "Accept",
"invite": "Invite",
"decline": "Decline",
"delete_log": "Delete log",
"decline_with_message": "Decline with message"
},
"filters": {
"requestInvite": "Request Invite",
"invite": "Invite",
@@ -1954,7 +1961,22 @@
"title": "Confirm",
"confirm_button": "Confirm",
"cancel_button": "Cancel",
"message": "Continue {command}?"
"message": "Continue {command}?",
"logout": "Continue? Logout",
"unfriend": "Continue? Unfriend",
"clear_avatar_history": "Continue? Clear Avatar History",
"select_avatar": "Continue? Select Avatar",
"invite": "Continue? Invite",
"invite_group": "Continue? Invite User(s) To Group",
"delete_log": "Continue? Delete Log",
"accept_friend_request": "Continue? Accept Friend Request",
"send_invite": "Continue? Send Invite",
"decline_type": "Continue? Decline {type}",
"delete_type": "Continue? Trash2 {type}",
"command_question": "Continue? {command}",
"restart_required_title": "Restart Required",
"restart_now": "Restart Now",
"restart_later": "Later"
},
"status": {
"title": "VRChat Status"
@@ -1974,19 +1996,35 @@
"instance": {
"closed": "Instance closed",
"removed_form_queue": "Removed instance {worldName} from queue",
"not_allowed": "You're not allowed to access this instance"
"not_allowed": "You're not allowed to access this instance",
"create_failed": "Failed to create instance"
},
"avatar": {
"change_moderation_failed": "Failed to change avatar moderation",
"image_changed": "Avatar image changed",
"image_invalid": "Current avatar image invalid"
},
"database": {
"upgrade_complete": "Database upgrade complete"
},
"emoji": {
"uploaded": "Emoji uploaded"
},
"file": {
"not_image": "File isn't an image",
"too_large": "File size too large"
"too_large": "File size too large",
"folder_missing": "Folder dosn't exist"
},
"group": {
"load_failed": "Failed to load group"
},
"invite": {
"self_sent": "Self invite sent",
"sent": "Invite sent",
"message_update_failed": "VRChat API didn't update message, try again"
},
"launch": {
"invalid_path": "Invalid path, you must enter VRChat folder or launch.exe"
},
"print": {
"uploaded": "Print uploaded"
@@ -2014,17 +2052,22 @@
},
"world": {
"image_changed": "World image changed",
"image_invalid": "Current world image invalid"
"image_invalid": "Current world image invalid",
"load_failed": "Failed to load world"
},
"icon": {
"uploaded": "Icon uploaded"
},
"user": {
"moderated": "User moderated"
"moderated": "User moderated",
"load_failed": "Failed to load user"
},
"friend": {
"load_failed": "Failed to load friends list, logging out"
},
"vrcplus": {
"required": "VRCPlus required"
},
"screenshot_metadata": {
"deleted": "Screenshot metadata deleted",
"delete_failed": "Failed to delete screenshot metadata"
@@ -2272,7 +2315,12 @@
},
"table": {
"pagination": {
"rows_per_page": "Rows per page"
"rows_per_page": "Rows per page",
"first": "First",
"previous": "Previous",
"next": "Next",
"last": "Last",
"more_pages": "More pages"
},
"feed": {
"date": "Date",

View File

@@ -418,7 +418,7 @@ export const useAuthStore = defineStore('Auth', () => {
function logout() {
modalStore
.confirm({
description: 'Continue? Logout',
description: t('confirm.logout'),
title: 'Confirm'
})
.then(({ ok }) => {

View File

@@ -1,6 +1,7 @@
import { nextTick, ref, watch } from 'vue';
import { defineStore } from 'pinia';
import { toast } from 'vue-sonner';
import { useI18n } from 'vue-i18n';
import {
checkVRChatCache,
@@ -31,6 +32,7 @@ export const useAvatarStore = defineStore('Avatar', () => {
const advancedSettingsStore = useAdvancedSettingsStore();
const userStore = useUserStore();
const modalStore = useModalStore();
const { t } = useI18n();
let cachedAvatarModerations = new Map();
let cachedAvatars = new Map();
@@ -392,7 +394,7 @@ export const useAvatarStore = defineStore('Avatar', () => {
function promptClearAvatarHistory() {
modalStore
.confirm({
description: 'Continue? Clear Avatar History',
description: t('confirm.clear_avatar_history'),
title: 'Confirm'
})
.then(({ ok }) => {
@@ -556,7 +558,7 @@ export const useAvatarStore = defineStore('Avatar', () => {
function selectAvatarWithConfirmation(id) {
modalStore
.confirm({
description: 'Continue? Select Avatar',
description: t('confirm.select_avatar'),
title: 'Confirm'
})
.then(({ ok }) => {

View File

@@ -1581,7 +1581,7 @@ export const useFriendStore = defineStore('Friend', () => {
function confirmDeleteFriend(id) {
modalStore
.confirm({
description: 'Continue? Unfriend',
description: t('confirm.unfriend'),
title: 'Confirm'
})
.then(async ({ ok }) => {

View File

@@ -1,6 +1,7 @@
import { nextTick, reactive, ref, watch } from 'vue';
import { defineStore } from 'pinia';
import { toast } from 'vue-sonner';
import { useI18n } from 'vue-i18n';
import {
groupRequest,
@@ -32,6 +33,7 @@ export const useGroupStore = defineStore('Group', () => {
const userStore = useUserStore();
const notificationStore = useNotificationStore();
const modalStore = useModalStore();
const { t } = useI18n();
let cachedGroups = new Map();
@@ -152,7 +154,7 @@ export const useGroupStore = defineStore('Group', () => {
.catch((err) => {
D.loading = false;
D.visible = false;
toast.error('Failed to load group');
toast.error(t('message.group.load_failed'));
throw err;
})
.then((args) => {

View File

@@ -1,6 +1,7 @@
import { computed, ref, watch } from 'vue';
import { defineStore } from 'pinia';
import { toast } from 'vue-sonner';
import { useI18n } from 'vue-i18n';
import { instanceRequest, inviteMessagesRequest } from '../api';
import { parseLocation } from '../shared/utils';
@@ -15,6 +16,7 @@ export const useInviteStore = defineStore('Invite', () => {
const gameStore = useGameStore();
const launchStore = useLaunchStore();
const advancedSettingsStore = useAdvancedSettingsStore();
const { t } = useI18n();
const inviteMessageTable = ref({
data: [],
@@ -95,7 +97,7 @@ export const useInviteStore = defineStore('Invite', () => {
instanceStore.createNewInstance(worldId).then((args) => {
const location = args?.json?.location;
if (!location) {
toast.error('Failed to create instance');
toast.error(t('message.instance.create_failed'));
return;
}
// self invite
@@ -115,7 +117,7 @@ export const useInviteStore = defineStore('Invite', () => {
worldId: L.worldId
})
.then((args) => {
toast.success('Self invite sent');
toast.success(t('message.invite.self_sent'));
return args;
});
});

View File

@@ -1,6 +1,7 @@
import { nextTick, ref, watch } from 'vue';
import { defineStore } from 'pinia';
import { toast } from 'vue-sonner';
import { useI18n } from 'vue-i18n';
import { instanceRequest } from '../api';
import { parseLocation } from '../shared/utils';
@@ -11,6 +12,7 @@ import configRepository from '../service/config';
export const useLaunchStore = defineStore('Launch', () => {
const isLaunchOptionsDialogVisible = ref(false);
const isOpeningInstance = ref(false);
const { t } = useI18n();
const launchDialogData = ref({
visible: false,
loading: false,
@@ -114,7 +116,7 @@ export const useLaunchStore = defineStore('Launch', () => {
worldId: L.worldId,
shortName
});
toast.success('Self invite sent');
toast.success(t('message.invite.self_sent'));
} catch (e) {
console.error(e);
}

View File

@@ -485,9 +485,9 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
.confirm({
description:
'Error reporting setting has been enabled. Would you like to restart VRCX now for the change to take effect?',
title: 'Restart Required',
confirmText: 'Restart Now',
cancelText: 'Later'
title: t('confirm.restart_required_title'),
confirmText: t('confirm.restart_now'),
cancelText: t('confirm.restart_later')
})
.then(async ({ ok }) => {
if (!ok) return;
@@ -507,9 +507,9 @@ export const useAdvancedSettingsStore = defineStore('AdvancedSettings', () => {
.confirm({
description:
'Error reporting setting has been disabled. Would you like to restart VRCX now for the change to take effect?',
title: 'Restart Required',
confirmText: 'Restart Now',
cancelText: 'Later'
title: t('confirm.restart_required_title'),
confirmText: t('confirm.restart_now'),
cancelText: t('confirm.restart_later')
})
.then(async ({ ok }) => {
if (!ok) return;

View File

@@ -1,6 +1,7 @@
import { computed, reactive, ref, shallowReactive, watch } from 'vue';
import { defineStore } from 'pinia';
import { toast } from 'vue-sonner';
import { useI18n } from 'vue-i18n';
import Noty from 'noty';
@@ -70,6 +71,7 @@ export const useUserStore = defineStore('User', () => {
const moderationStore = useModerationStore();
const photonStore = usePhotonStore();
const sharedFeedStore = useSharedFeedStore();
const { t } = useI18n();
const currentUser = ref({
acceptedPrivacyVersion: 0,
@@ -837,7 +839,7 @@ export const useUserStore = defineStore('User', () => {
.catch((err) => {
D.loading = false;
D.visible = false;
toast.error('Failed to load user');
toast.error(t('message.user.load_failed'));
throw err;
})
.then((args) => {

View File

@@ -195,7 +195,7 @@ export const useVrcxStore = defineStore('Vrcx', () => {
toast.dismiss(msgBox);
if (state.databaseVersion) {
// only display when database exists
toast.success('Database upgrade complete');
toast.success(t('message.database.upgrade_complete'));
}
state.databaseVersion = databaseVersion;
} catch (err) {

View File

@@ -1,6 +1,7 @@
import { reactive, shallowReactive, watch } from 'vue';
import { defineStore } from 'pinia';
import { toast } from 'vue-sonner';
import { useI18n } from 'vue-i18n';
import {
checkVRChatCache,
@@ -24,6 +25,7 @@ export const useWorldStore = defineStore('World', () => {
const favoriteStore = useFavoriteStore();
const instanceStore = useInstanceStore();
const userStore = useUserStore();
const { t } = useI18n();
const worldDialog = reactive({
visible: false,
@@ -132,7 +134,7 @@ export const useWorldStore = defineStore('World', () => {
.catch((err) => {
D.loading = false;
D.visible = false;
toast.error('Failed to load world');
toast.error(t('message.world.load_failed'));
throw err;
})
.then((args) => {

View File

@@ -151,7 +151,7 @@
function deleteFriendLogPrompt(row) {
modalStore
.confirm({
description: 'Continue? Delete Log',
description: t('confirm.delete_log'),
title: 'Confirm'
})
.then(({ ok }) => ok && deleteFriendLog(row))

View File

@@ -138,7 +138,7 @@
function deleteGameLogEntryPrompt(row) {
modalStore
.confirm({
description: 'Continue? Delete Log',
description: t('confirm.delete_log'),
title: 'Confirm'
})
.then(({ ok }) => ok && deleteGameLogEntry(row))

View File

@@ -324,7 +324,7 @@
// FIXME: 메시지 수정
modalStore
.confirm({
description: 'Continue? Accept Friend Request',
description: t('confirm.accept_friend_request'),
title: 'Confirm'
})
.then(({ ok }) => {
@@ -349,7 +349,7 @@
function acceptRequestInvite(row) {
modalStore
.confirm({
description: 'Continue? Send Invite',
description: t('confirm.send_invite'),
title: 'Confirm'
})
.then(({ ok }) => {
@@ -381,7 +381,7 @@
row.senderUserId
)
.then((_args) => {
toast('Invite sent');
toast(t('message.invite.sent'));
notificationRequest.hideNotification({
notificationId: row.id
});
@@ -459,7 +459,7 @@
function hideNotificationPrompt(row) {
modalStore
.confirm({
description: `Continue? Decline ${row.type}`,
description: t('confirm.decline_type', { type: row.type }),
title: 'Confirm'
})
.then(({ ok }) => {
@@ -483,7 +483,7 @@
function deleteNotificationLogPrompt(row) {
modalStore
.confirm({
description: `Continue? Trash2 ${row.type}`,
description: t('confirm.delete_type', { type: row.type }),
title: 'Confirm'
})
.then(({ ok }) => {

View File

@@ -543,7 +543,11 @@ export const createColumns = ({
</button>
</TooltipTrigger>
<TooltipContent side="top">
<span>Accept</span>
<span>
{t(
'view.notification.actions.accept'
)}
</span>
</TooltipContent>
</Tooltip>
</TooltipProvider>
@@ -567,7 +571,9 @@ export const createColumns = ({
</TooltipTrigger>
<TooltipContent side="top">
<span>
Decline with message
{t(
'view.notification.actions.decline_with_message'
)}
</span>
</TooltipContent>
</Tooltip>
@@ -593,7 +599,11 @@ export const createColumns = ({
</button>
</TooltipTrigger>
<TooltipContent side="top">
<span>Invite</span>
<span>
{t(
'view.notification.actions.invite'
)}
</span>
</TooltipContent>
</Tooltip>
</TooltipProvider>
@@ -615,7 +625,9 @@ export const createColumns = ({
</TooltipTrigger>
<TooltipContent side="top">
<span>
Decline with message
{t(
'view.notification.actions.decline_with_message'
)}
</span>
</TooltipContent>
</Tooltip>
@@ -705,7 +717,11 @@ export const createColumns = ({
</button>
</TooltipTrigger>
<TooltipContent side="top">
<span>Decline</span>
<span>
{t(
'view.notification.actions.decline'
)}
</span>
</TooltipContent>
</Tooltip>
</TooltipProvider>
@@ -736,7 +752,11 @@ export const createColumns = ({
</button>
</TooltipTrigger>
<TooltipContent side="top">
<span>Delete log</span>
<span>
{t(
'view.notification.actions.delete_log'
)}
</span>
</TooltipContent>
</Tooltip>
</TooltipProvider>
@@ -767,7 +787,11 @@ export const createColumns = ({
</button>
</TooltipTrigger>
<TooltipContent side="top">
<span>Delete log</span>
<span>
{t(
'view.notification.actions.delete_log'
)}
</span>
</TooltipContent>
</Tooltip>
</TooltipProvider>

View File

@@ -79,8 +79,9 @@
})
.then((args) => {
if (args.json[slot].message === I.messageSlot.message) {
toast.error("VRChat API didn't update message, try again");
throw new Error("VRChat API didn't update message, try again");
const errorMessage = t('message.invite.message_update_failed');
toast.error(errorMessage);
throw new Error(errorMessage);
} else {
toast('Invite message updated');
}

View File

@@ -507,7 +507,7 @@
if (result) {
toast.success('Folder opened');
} else {
toast.error("Folder dosn't exist");
toast.error(t('message.file.folder_missing'));
}
});
}
@@ -517,7 +517,7 @@
if (result) {
toast.success('Folder opened');
} else {
toast.error("Folder dosn't exist");
toast.error(t('message.file.folder_missing'));
}
});
}
@@ -527,7 +527,7 @@
if (result) {
toast.success('Folder opened');
} else {
toast.error("Folder dosn't exist");
toast.error(t('message.file.folder_missing'));
}
});
}

View File

@@ -111,7 +111,7 @@
D.vrcLaunchPathOverride.endsWith('.exe') &&
!D.vrcLaunchPathOverride.endsWith('launch.exe')
) {
toast.error('Invalid path, you must enter VRChat folder or launch.exe');
toast.error(t('message.launch.invalid_path'));
return;
}
configRepository.setString('vrcLaunchPathOverride', D.vrcLaunchPathOverride);

View File

@@ -737,7 +737,7 @@
function setProfilePicOverride(fileId) {
if (!isLocalUserVrcPlusSupporter.value) {
toast.error('VRCPlus required');
toast.error(t('message.vrcplus.required'));
return;
}
let profilePicOverride = '';
@@ -834,7 +834,7 @@
function setVRCPlusIcon(fileId) {
if (!isLocalUserVrcPlusSupporter.value) {
toast.error('VRCPlus required');
toast.error(t('message.vrcplus.required'));
return;
}
let userIcon = '';

View File

@@ -286,7 +286,7 @@
if (result) {
toast.success('Folder opened');
} else {
toast.error("Folder dosn't exist");
toast.error(t('message.file.folder_missing'));
}
});
}
@@ -296,7 +296,7 @@
if (result) {
toast.success('Folder opened');
} else {
toast.error("Folder dosn't exist");
toast.error(t('message.file.folder_missing'));
}
});
}

View File

@@ -70,8 +70,9 @@
})
.then((args) => {
if (args.json[slot].message === props.inviteMessage.message) {
toast.error("VRChat API didn't update message, try again");
throw new Error("VRChat API didn't update message, try again");
const errorMessage = t('message.invite.message_update_failed');
toast.error(errorMessage);
throw new Error(errorMessage);
} else {
toast.success('Invite message updated');
emit('updateInviteMessages', messageType);