forked from akanyan/STARTLINER
fix: localization fixes
This commit is contained in:
@ -7,12 +7,20 @@ use crate::pkg_store::PackageStore;
|
||||
use crate::util;
|
||||
use crate::profiles::types::ProfilePaths;
|
||||
|
||||
pub async fn prepare_packages<'a>(p: &'a impl ProfilePaths, pkgs: &BTreeSet<PkgKey>, redo_bepinex: bool) -> Result<()> {
|
||||
pub async fn prepare_packages<'a>(p: &'a impl ProfilePaths, pkgs: &BTreeSet<PkgKey>, mut redo_bepinex: bool) -> Result<()> {
|
||||
log::debug!("begin prepare packages");
|
||||
|
||||
let pfx_dir = p.data_dir();
|
||||
let opt_dir = pfx_dir.join("option");
|
||||
|
||||
for m in pkgs {
|
||||
let (namespace, _) = m.split()?;
|
||||
if namespace == "local" {
|
||||
log::info!("package with the 'local' namespace enabled -- force refreshing");
|
||||
redo_bepinex = true;
|
||||
}
|
||||
}
|
||||
|
||||
if redo_bepinex {
|
||||
if pfx_dir.join("BepInEx").exists() {
|
||||
util::remove_dir_all(pfx_dir.join("BepInEx")).await?;
|
||||
|
@ -27,6 +27,9 @@ import {
|
||||
usePrfStore,
|
||||
} from '../stores';
|
||||
import { messageSplit, shouldPreferDark } from '../util';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
document.documentElement.classList.toggle('use-dark-mode', shouldPreferDark());
|
||||
|
||||
@ -257,7 +260,7 @@ listen<DownloadingStatus>('download-progress', (event) => {
|
||||
style="min-width: 0; width: 25dvw"
|
||||
class="self-center"
|
||||
size="small"
|
||||
placeholder="Search"
|
||||
:placeholder="t('search')"
|
||||
v-model="general.cfgSearchTerm"
|
||||
/>
|
||||
<InputText
|
||||
@ -265,7 +268,7 @@ listen<DownloadingStatus>('download-progress', (event) => {
|
||||
style="min-width: 0; width: 25dvw"
|
||||
class="self-center"
|
||||
size="small"
|
||||
placeholder="Search"
|
||||
:placeholder="t('search')"
|
||||
v-model="pkgSearchTerm"
|
||||
/>
|
||||
</div>
|
||||
|
@ -101,7 +101,7 @@ const installRecommended = () => {
|
||||
<MultiSelect
|
||||
size="small"
|
||||
:showToggleAll="false"
|
||||
placeholder="Include categories"
|
||||
:placeholder="t('store.includeCategories')"
|
||||
v-model="pkgs.includeCategories"
|
||||
:options="[...pkgs.availableCategories]"
|
||||
class="w-full"
|
||||
@ -109,7 +109,7 @@ const installRecommended = () => {
|
||||
<MultiSelect
|
||||
size="small"
|
||||
:showToggleAll="false"
|
||||
placeholder="Exclude categories"
|
||||
:placeholder="t('store.excludeCategories')"
|
||||
v-model="pkgs.excludeCategories"
|
||||
:options="[...pkgs.availableCategories]"
|
||||
class="w-full"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ComputedRef, computed, onMounted, ref } from 'vue';
|
||||
import { ComputedRef, computed, ref } from 'vue';
|
||||
import Button from 'primevue/button';
|
||||
import Carousel from 'primevue/carousel';
|
||||
import Dialog from 'primevue/dialog';
|
||||
@ -27,7 +27,7 @@ interface Datum {
|
||||
|
||||
const game = computed(() => prf.current?.meta.game);
|
||||
|
||||
const processText = (s: string) => {
|
||||
const processText = computed(() => (s: string) => {
|
||||
// Why do I have to do this
|
||||
s = s
|
||||
.split('\n')
|
||||
@ -39,14 +39,14 @@ const processText = (s: string) => {
|
||||
if (readable !== null) {
|
||||
return s.replace(
|
||||
'%TESTMENU%',
|
||||
`${readable} or a button on the back of the controller`
|
||||
`${readable} ${t('onboarding.or')} ${t('onboarding.backButton')}`
|
||||
);
|
||||
}
|
||||
}
|
||||
return s.replace('%TESTMENU%', 'a button on the back of the controller');
|
||||
};
|
||||
return s.replace('%TESTMENU%', t('onboarding.backButton'));
|
||||
});
|
||||
|
||||
const loadPage = (title: string, messages?: object) => {
|
||||
const loadPage = computed(() => (title: string, messages?: object) => {
|
||||
return {
|
||||
text: t(`onboarding.${title}`, {
|
||||
endlink: '</a>',
|
||||
@ -56,19 +56,44 @@ const loadPage = (title: string, messages?: object) => {
|
||||
}),
|
||||
image: `help-${title}.png`,
|
||||
};
|
||||
};
|
||||
|
||||
let systemProcessing: Datum;
|
||||
let standardOngeki: Datum;
|
||||
let standardChunithm: Datum;
|
||||
let lever: Datum;
|
||||
let server: Datum;
|
||||
let finaleOngeki: Datum;
|
||||
let finaleChunithm: Datum;
|
||||
});
|
||||
|
||||
const data: ComputedRef<Datum[]> = computed(() => {
|
||||
const res = [];
|
||||
|
||||
const [standard, systemProcessing, lever, server, finale] = [
|
||||
loadPage.value('standard', {
|
||||
bigblack: '<div class="p-2 mt-1 mb-1 bg-black text-white">',
|
||||
endbig: '</div>',
|
||||
}),
|
||||
loadPage.value('ongeki-system-processing'),
|
||||
loadPage.value('ongeki-lever'),
|
||||
loadPage.value('chunithm-server', {
|
||||
link: '<a href="https://gitea.tendokyu.moe/Dniel97/SEGAguide/wiki/FAQ#game-is-stuck-at-checking-distribution-server" target="_blank">',
|
||||
}),
|
||||
loadPage.value('finale', {
|
||||
segaguide:
|
||||
'<a href="https://gitea.tendokyu.moe/Dniel97/SEGAguide/wiki/FAQ" target="_blank">',
|
||||
twotorial: '<a href="https://two-torial.xyz/" target="_blank">',
|
||||
}),
|
||||
];
|
||||
const standardOngeki = {
|
||||
...standard,
|
||||
image: '/help-standard-ongeki.png',
|
||||
};
|
||||
const standardChunithm = {
|
||||
...standard,
|
||||
image: '/help-standard-chunithm.png',
|
||||
};
|
||||
const finaleOngeki = {
|
||||
...finale,
|
||||
image: '/help-finale-ongeki.png',
|
||||
};
|
||||
const finaleChunithm = {
|
||||
...finale,
|
||||
image: '/help-finale-chunithm.png',
|
||||
};
|
||||
|
||||
switch (prf.current?.meta.game) {
|
||||
case 'ongeki':
|
||||
res.push(systemProcessing);
|
||||
@ -92,48 +117,14 @@ const context = ref({
|
||||
index: 0,
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
[standardOngeki, systemProcessing, lever, server, finaleOngeki] =
|
||||
await Promise.all([
|
||||
loadPage('standard', {
|
||||
bigblack: '<div class="p-2 mt-1 mb-1 bg-black text-white">',
|
||||
endbig: '</div>',
|
||||
}),
|
||||
loadPage('ongeki-system-processing'),
|
||||
loadPage('ongeki-lever'),
|
||||
loadPage('chunithm-server', {
|
||||
link: '<a href="https://gitea.tendokyu.moe/Dniel97/SEGAguide/wiki/FAQ#game-is-stuck-at-checking-distribution-server" target="_blank">',
|
||||
}),
|
||||
loadPage('finale', {
|
||||
segaguide:
|
||||
'<a href="https://gitea.tendokyu.moe/Dniel97/SEGAguide/wiki/FAQ" target="_blank">',
|
||||
twotorial: '<a href="https://two-torial.xyz/" target="_blank">',
|
||||
}),
|
||||
]);
|
||||
standardOngeki = {
|
||||
...standardOngeki,
|
||||
image: '/help-standard-ongeki.png',
|
||||
};
|
||||
standardChunithm = {
|
||||
...standardOngeki,
|
||||
image: '/help-standard-chunithm.png',
|
||||
};
|
||||
finaleOngeki = {
|
||||
...finaleOngeki,
|
||||
image: '/help-finale-ongeki.png',
|
||||
};
|
||||
finaleChunithm = {
|
||||
...finaleOngeki,
|
||||
image: '/help-finale-chunithm.png',
|
||||
};
|
||||
});
|
||||
|
||||
const exitLabel = computed(() => {
|
||||
return props.firstTime === true &&
|
||||
context.value.index < data.value.length - 1
|
||||
? 'Skip'
|
||||
: 'Close';
|
||||
? t('skip')
|
||||
: t('close');
|
||||
});
|
||||
|
||||
const page = ref(0);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -147,14 +138,15 @@ const exitLabel = computed(() => {
|
||||
: `${game ? prettyPrint(game) : '<game>'} help`
|
||||
"
|
||||
:style="{ width: '760px', scale: client.scaleValue }"
|
||||
v-on:show="() => (context.index = 0)"
|
||||
v-on:show="() => ((context.index = 0), (page = 0))"
|
||||
>
|
||||
<Carousel
|
||||
:value="data"
|
||||
:num-visible="1"
|
||||
:num-scroll="1"
|
||||
:context="context"
|
||||
v-on:update:page="(p) => (context.index = p)"
|
||||
:page="page"
|
||||
v-on:update:page="(p) => ((context.index = p), (page = p))"
|
||||
>
|
||||
<template #item="slotProps">
|
||||
<div class="md-container markdown">
|
||||
@ -178,8 +170,8 @@ const exitLabel = computed(() => {
|
||||
<Button
|
||||
v-if="context.index < data.length - 1"
|
||||
class="m-auto mr-4"
|
||||
label="Next"
|
||||
@click="() => (context.index += 1)"
|
||||
:label="t('next')"
|
||||
@click="() => (page += 1)"
|
||||
/>
|
||||
<Button
|
||||
class="m-auto"
|
||||
|
@ -57,7 +57,7 @@ invoke('list_patches', { target: prf.current!.data.sgt.target }).then(
|
||||
v-for="p in amdPatches"
|
||||
:patch="p"
|
||||
/>
|
||||
<div v-if="gamePatches === null">Loading...</div>
|
||||
<div v-if="gamePatches === null">{{ t('patch.loading') }}</div>
|
||||
<div v-if="amdPatches !== null && amdPatches.length === 0">
|
||||
{{ t('patch.noneFound') }}
|
||||
<!-- <br />
|
||||
|
@ -150,14 +150,14 @@ const importPick = async () => {
|
||||
</div>
|
||||
<div class="mt-4 flex flex-row flex-wrap align-middle gap-4">
|
||||
<Button
|
||||
label="Import template"
|
||||
:label="t('profile.import')"
|
||||
icon="pi pi-file-import"
|
||||
class="import-button profile-button"
|
||||
@click="() => importPick()"
|
||||
/>
|
||||
<Button
|
||||
:disabled="prf.current === null"
|
||||
label="Export template"
|
||||
:label="t('profile.export')"
|
||||
icon="pi pi-file-export"
|
||||
class="profile-button"
|
||||
@click="() => openExportDialog()"
|
||||
@ -179,6 +179,7 @@ const importPick = async () => {
|
||||
:options="[
|
||||
{ title: 'English', value: 'en' },
|
||||
// { title: '日本語', value: 'ja' },
|
||||
{ title: 'Polski', value: 'pl' },
|
||||
]"
|
||||
size="small"
|
||||
option-label="title"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { Ref, computed, ref } from 'vue';
|
||||
import { Ref, computed, onMounted, ref } from 'vue';
|
||||
import InputNumber from 'primevue/inputnumber';
|
||||
import Select from 'primevue/select';
|
||||
import SelectButton from 'primevue/selectbutton';
|
||||
@ -65,7 +65,9 @@ const loadDisplays = () => {
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
loadDisplays();
|
||||
onMounted(() => {
|
||||
loadDisplays();
|
||||
});
|
||||
|
||||
const game = computed(() => prf.current!.meta.game);
|
||||
const isVertical = computed(() => prf.current!.meta.game === 'ongeki');
|
||||
@ -76,7 +78,7 @@ const canSkipPrimarySwitch = computed(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<OptionCategory title="Display">
|
||||
<OptionCategory :title="t('cfg.display.title')">
|
||||
<OptionRow
|
||||
v-if="capabilities.includes('display')"
|
||||
:title="t('cfg.display.target')"
|
||||
@ -92,7 +94,7 @@ const canSkipPrimarySwitch = computed(
|
||||
</OptionRow>
|
||||
<OptionRow
|
||||
class="number-input"
|
||||
title="Game resolution"
|
||||
:title="t('cfg.display.resolution')"
|
||||
v-if="adjustableRez"
|
||||
>
|
||||
<InputNumber
|
||||
@ -117,9 +119,9 @@ const canSkipPrimarySwitch = computed(
|
||||
<SelectButton
|
||||
v-model="prf.current!.data.display.mode"
|
||||
:options="[
|
||||
{ title: 'Window', value: 'Window' },
|
||||
{ title: 'Borderless window', value: 'Borderless' },
|
||||
{ title: 'Fullscreen', value: 'Fullscreen' },
|
||||
{ title: t('cfg.display.window'), value: 'Window' },
|
||||
{ title: t('cfg.display.borderless'), value: 'Borderless' },
|
||||
{ title: t('cfg.display.fullscreen'), value: 'Fullscreen' },
|
||||
]"
|
||||
:allow-empty="false"
|
||||
option-label="title"
|
||||
|
@ -147,9 +147,9 @@ const checkSegatoolsIni = async (target: string) => {
|
||||
<Select
|
||||
v-model="prf.current!.data.sgt.io2"
|
||||
:options="[
|
||||
{ title: 'native io4', value: 'hardware' },
|
||||
{ title: t('cfg.segatools.io4'), value: 'hardware' },
|
||||
{
|
||||
title: 'segatools built-in (keyboard)',
|
||||
title: t('cfg.segatools.ioBuiltIn'),
|
||||
value: 'segatools_built_in',
|
||||
},
|
||||
...pkgs
|
||||
|
@ -1,8 +1,7 @@
|
||||
import en from './i18n/en';
|
||||
import ja from './i18n/ja';
|
||||
import { createI18n } from 'vue-i18n';
|
||||
|
||||
export type Locale = 'en' | 'ja';
|
||||
export type Locale = 'en' | 'ja' | 'pl';
|
||||
|
||||
const loadLocaleMessages = async (locale: Locale) => {
|
||||
return (await import(`./i18n/${locale}.ts`)).default;
|
||||
@ -14,7 +13,7 @@ const i18n = createI18n({
|
||||
fallbackLocale: 'en',
|
||||
warnHtmlInMessage: false,
|
||||
warnHtmlMessage: false,
|
||||
messages: { en, ja },
|
||||
messages: { en, ja: {}, pl: {} },
|
||||
});
|
||||
|
||||
const setLocale = async (locale: Locale) => {
|
||||
|
@ -4,6 +4,10 @@ export default {
|
||||
enable: 'Enable',
|
||||
disable: 'Disable',
|
||||
default: 'Default',
|
||||
search: 'Search',
|
||||
next: 'Next',
|
||||
skip: 'Skip',
|
||||
close: 'Close',
|
||||
start: {
|
||||
failed: 'Start check failed',
|
||||
accept: 'Run anyway',
|
||||
@ -38,6 +42,8 @@ export default {
|
||||
delete: 'Delete profile',
|
||||
reallyDelete: 'Are you sure you want to delete {profile}?',
|
||||
template: 'STARTLINER template',
|
||||
import: 'Import template',
|
||||
export: 'Export template',
|
||||
},
|
||||
store: {
|
||||
installRecommended: 'Install recommended packages',
|
||||
@ -46,6 +52,8 @@ export default {
|
||||
nsfw: 'Show NSFW',
|
||||
incompatible: 'This package is currently incompatible with STARTLINER.',
|
||||
missing: 'Missing',
|
||||
includeCategories: 'Include categories',
|
||||
excludeCategories: 'Exclude categories',
|
||||
},
|
||||
patch: {
|
||||
loading: 'Loading...',
|
||||
@ -70,9 +78,13 @@ export default {
|
||||
hooks: 'Hooks',
|
||||
ioModules: 'IO modules',
|
||||
ioModulesDesc: 'This should match your desired input method.',
|
||||
ioBuiltIn: 'segatools built-in (keyboard)',
|
||||
io4: 'Native IO4',
|
||||
installTooltip: '{thing} can be downloaded from the package store.',
|
||||
},
|
||||
display: {
|
||||
title: 'Display',
|
||||
resolution: 'Game resolution',
|
||||
primary: 'Primary',
|
||||
target: 'Target display',
|
||||
mode: 'Mode',
|
||||
@ -88,6 +100,9 @@ export default {
|
||||
portrait: 'Portrait',
|
||||
landscape: 'Landscape',
|
||||
flipped: 'flipped',
|
||||
window: 'Window',
|
||||
borderless: 'Borderless window',
|
||||
fullscreen: 'Fullscreen',
|
||||
},
|
||||
network: {
|
||||
title: 'Network',
|
||||
@ -160,6 +175,8 @@ export default {
|
||||
},
|
||||
},
|
||||
onboarding: {
|
||||
or: 'or',
|
||||
backButton: 'a button on the back of the controller',
|
||||
standard: `
|
||||
You might get stuck on the following screen:
|
||||
|
||||
|
Reference in New Issue
Block a user