aboutsummaryrefslogtreecommitdiff
path: root/src-vue/src/components
diff options
context:
space:
mode:
authorRémy Raes <contact@remyraes.com>2023-03-29 00:45:16 +0200
committerGitHub <noreply@github.com>2023-03-28 22:45:16 +0000
commit428c300e9f42f8b9232f780d387292c1a94fcd23 (patch)
tree8e3026de0ad6a69a08396026bdc7fd084d073739 /src-vue/src/components
parent784330797d947ec2ff4eb97a7325ac77f3a79e4d (diff)
downloadFlightCore-428c300e9f42f8b9232f780d387292c1a94fcd23.tar.gz
FlightCore-428c300e9f42f8b9232f780d387292c1a94fcd23.zip
feat: i18n (#182)
* build: add vue-i18n dependency * feat: add i18n plugin to vue project * feat: use translations in play button * feat: translate play view * feat: translate menu items * feat: translate local mods view * feat: translate online mods view * feat: translate mods menu * feat: translate thunderstore mod card component * fix: remove useless "this" keyword * feat: translate settings view * fix: remove leftover test invocation * feat: add language selector component * feat: using language selector updates interface's language * feat: save language in persistent store on selector change * feat: initialize lang on app launch * refactor: move i18n code into App.mounted callback * feat: update interface language on app launch * feat: adjust language selection on language selector load * fix: this.$root can't be null * feat: translate store notifications * fix: add missing parameter to english translation * feat: translate "by" author keyword * feat: translate repair window * feat: translate repair window title * docs: add some documentation regarding localization * docs: explain how to add a new language * feat: translate Northstar release canal selector elements * docs: describe how to inject variable into translations * feat: translate "info" word * feat: translate popconfirm buttons * fix: remove "this" keyword * fix: save store when updating interface language
Diffstat (limited to 'src-vue/src/components')
-rw-r--r--src-vue/src/components/LanguageSelector.vue47
-rw-r--r--src-vue/src/components/ModsMenu.vue14
-rw-r--r--src-vue/src/components/PlayButton.vue16
-rw-r--r--src-vue/src/components/ThunderstoreModCard.vue34
4 files changed, 79 insertions, 32 deletions
diff --git a/src-vue/src/components/LanguageSelector.vue b/src-vue/src/components/LanguageSelector.vue
new file mode 100644
index 00000000..c09f6c05
--- /dev/null
+++ b/src-vue/src/components/LanguageSelector.vue
@@ -0,0 +1,47 @@
+<template>
+ <el-select v-model="value" class="m-2"
+ :placeholder="$t('settings.language_select')" size="large"
+ @change="onChange"
+ >
+ <el-option
+ v-for="item in options"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+import { Store } from 'tauri-plugin-store-api';
+const persistentStore = new Store('flight-core-settings.json');
+
+export default defineComponent({
+ name: 'LanguageSelector',
+ data: () => ({
+ value: '',
+ options: [
+ {
+ value: 'en',
+ label: 'English'
+ },
+ {
+ value: 'fr',
+ label: 'Français'
+ }
+ ]
+ }),
+ mounted: async function() {
+ const lang: string = await persistentStore.get('lang') as string;
+ this.value = lang;
+ },
+ methods: {
+ async onChange(value: string) {
+ this.$root!.$i18n.locale = value;
+ persistentStore.set('lang', value);
+ await persistentStore.save();
+ }
+ }
+})
+</script>
diff --git a/src-vue/src/components/ModsMenu.vue b/src-vue/src/components/ModsMenu.vue
index 9b62fcfa..656c05a6 100644
--- a/src-vue/src/components/ModsMenu.vue
+++ b/src-vue/src/components/ModsMenu.vue
@@ -7,20 +7,20 @@
<h5>Mods</h5>
<el-menu-item index="1" @click="$emit('showLocalMods', true)">
<el-icon><Folder /></el-icon>
- <span>Local</span>
+ <span>{{ $t('mods.menu.local') }}</span>
</el-menu-item>
<el-menu-item index="2" @click="$emit('showLocalMods', false)">
<el-icon><Connection /></el-icon>
- <span>Online</span>
+ <span>{{ $t('mods.menu.online') }}</span>
</el-menu-item>
<!-- Search inputs -->
- <h5>Filter</h5>
- <el-input v-model="$store.state.search.searchValue" placeholder="Search" clearable />
+ <h5>{{ $t('mods.menu.filter') }}</h5>
+ <el-input v-model="$store.state.search.searchValue" :placeholder="$t('mods.menu.search')" clearable />
<el-select
v-if="!showingLocalMods"
v-model="$store.state.search.sortValue"
- placeholder="Sort mods"
+ :placeholder="$t('mods.menu.sort_mods')"
>
<el-option
v-for="item of sortValues"
@@ -33,7 +33,7 @@
v-if="!showingLocalMods"
v-model="$store.state.search.selectedCategories"
multiple
- placeholder="Select categories"
+ :placeholder="$t('mods.menu.select_categories')"
>
<el-option
v-for="item in $store.state.thunderstoreModsCategories"
@@ -66,7 +66,7 @@ export default defineComponent({
sortValues(): {label: string, value: string}[] {
return Object.keys(SortOptions).map((key: string) => ({
value: key,
- label: Object.values(SortOptions)[Object.keys(SortOptions).indexOf(key)]
+ label: this.$t('mods.menu.sort.' + Object.values(SortOptions)[Object.keys(SortOptions).indexOf(key)])
}));
}
}
diff --git a/src-vue/src/components/PlayButton.vue b/src-vue/src/components/PlayButton.vue
index 687f12a4..3efcc9f5 100644
--- a/src-vue/src/components/PlayButton.vue
+++ b/src-vue/src/components/PlayButton.vue
@@ -18,22 +18,22 @@ export default defineComponent({
},
playButtonLabel(): string {
if (this.$store.state.northstar_is_running) {
- return "Game is running";
+ return this.$t("play.button.northstar_is_running");
}
switch(this.$store.state.northstar_state) {
case NorthstarState.GAME_NOT_FOUND:
- return "Select Titanfall2 game folder";
+ return this.$t("play.button.select_game_dir");
case NorthstarState.INSTALL:
- return "Install";
+ return this.$t("play.button.install");
case NorthstarState.INSTALLING:
- return "Installing..."
+ return this.$t("play.button.installing");
case NorthstarState.MUST_UPDATE:
- return "Update";
+ return this.$t("play.button.update");
case NorthstarState.UPDATING:
- return "Updating...";
+ return this.$t("play.button.updating");
case NorthstarState.READY_TO_PLAY:
- return "Launch game";
+ return this.$t("play.button.ready_to_play");
default:
return "";
@@ -57,7 +57,7 @@ export default defineComponent({
options: [
{
value: ReleaseCanal.RELEASE_CANDIDATE,
- label: 'Northstar release candidate',
+ label: this.$t('channels.names.NorthstarReleaseCandidate'),
},
]
},
diff --git a/src-vue/src/components/ThunderstoreModCard.vue b/src-vue/src/components/ThunderstoreModCard.vue
index c9f6768c..b81ed03c 100644
--- a/src-vue/src/components/ThunderstoreModCard.vue
+++ b/src-vue/src/components/ThunderstoreModCard.vue
@@ -21,7 +21,7 @@
<br/>
<div class="name hide-text-overflow">{{ mod.name }}</div>
- <div class="author hide-text-overflow">by {{ mod.owner }}</div>
+ <div class="author hide-text-overflow">{{ $t('mods.card.by') }} {{ mod.owner }}</div>
<div class="desc">
{{ latestVersion.description }}
</div>
@@ -33,7 +33,7 @@
:loading="isBeingInstalled || isBeingUpdated"
@click.stop="installMod(mod)"
>
- {{ modButtonText }}
+ {{ $t(modButtonText) }}
</el-button>
<!-- Information dropdown menu -->
@@ -51,10 +51,10 @@
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="openURL(mod.package_url)">
- More info
+ {{ $t('mods.card.more_info') }}
</el-dropdown-item>
<el-dropdown-item @click="deleteMod(mod)">
- Remove mod
+ {{ $t('mods.card.remove') }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
@@ -129,15 +129,15 @@ export default defineComponent({
modButtonText(): string {
switch (this.modStatus) {
case ThunderstoreModStatus.BEING_INSTALLED:
- return "Installing...";
+ return "mods.card.button.being_installed";
case ThunderstoreModStatus.BEING_UPDATED:
- return "Updating...";
+ return "mods.card.button.being_updated";
case ThunderstoreModStatus.INSTALLED:
- return "Installed";
+ return "mods.card.button.installed";
case ThunderstoreModStatus.NOT_INSTALLED:
- return "Install";
+ return "mods.card.button.install";
case ThunderstoreModStatus.OUTDATED:
- return "Update";
+ return "mods.card.button.outdated";
}
},
@@ -200,11 +200,11 @@ export default defineComponent({
// Show pop-up to confirm delete
ElMessageBox.confirm(
- 'Delete Thunderstore mod?',
- 'Warning',
+ this.$t('mods.card.remove_dialog_text'),
+ this.$t('mods.card.remove_dialog_title'),
{
- confirmButtonText: 'OK',
- cancelButtonText: 'Cancel',
+ confirmButtonText: this.$t('generic.yes'),
+ cancelButtonText: this.$t('generic.cancel'),
type: 'warning',
}
)
@@ -217,7 +217,7 @@ export default defineComponent({
await invoke("delete_thunderstore_mod", { gameInstall: game_install, thunderstoreModString: this.latestVersion.full_name })
.then((message) => {
ElNotification({
- title: `Removed ${mod.name}`,
+ title: this.$t('mods.card.remove_success', {modName: mod.name}),
message: message as string,
type: 'success',
position: 'bottom-right'
@@ -225,7 +225,7 @@ export default defineComponent({
})
.catch((error) => {
ElNotification({
- title: 'Error',
+ title: this.$t('generic.error'),
message: error,
type: 'error',
position: 'bottom-right'
@@ -255,7 +255,7 @@ export default defineComponent({
await invoke("install_mod_caller", { gameInstall: game_install, thunderstoreModString: this.latestVersion.full_name }).then((message) => {
ElNotification({
- title: `Installed ${mod.name}`,
+ title: this.$t('mods.card.install_success', {modName: mod.name}),
message: message as string,
type: 'success',
position: 'bottom-right'
@@ -263,7 +263,7 @@ export default defineComponent({
})
.catch((error) => {
ElNotification({
- title: 'Error',
+ title: this.$t('generic.error'),
message: error,
type: 'error',
position: 'bottom-right'