Skip to content

Commit e6a97f2

Browse files
committed
GameSelectionScreen supports i18n for English and French
1 parent 138968a commit e6a97f2

File tree

7 files changed

+205
-42
lines changed

7 files changed

+205
-42
lines changed

src/App.vue

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import { NodeFsImplementation } from './providers/node/fs/NodeFsImplementation';
5252
import { useRouter } from 'vue-router';
5353
import { ProtocolProviderImplementation } from './providers/generic/protocol/ProtocolProviderImplementation';
5454
import { provideProtocolImplementation } from './providers/generic/protocol/ProtocolProvider';
55+
import { useI18n } from 'vue-i18n';
5556
5657
const store = baseStore;
5758
const router = useRouter();
@@ -143,6 +144,19 @@ onMounted(async () => {
143144
watchEffect(() => {
144145
document.documentElement.classList.toggle('html--dark', quasar.dark.isActive);
145146
})
147+
148+
const { locale } = useI18n();
149+
150+
document.addEventListener('keydown', (e: KeyboardEvent) => {
151+
if (e.altKey && e.key === 'l') {
152+
console.log("Switch lang");
153+
if (locale.value === 'en') {
154+
locale.value = 'fr';
155+
} else {
156+
locale.value = 'en';
157+
}
158+
}
159+
})
146160
</script>
147161

148162
<style lang="scss">
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
export type GameSelectionMessageFormat = {
2+
platformModal: {
3+
header: string;
4+
selectAction: string;
5+
},
6+
pageTitle: {
7+
title: {
8+
game: string;
9+
server: string;
10+
}
11+
subtitle: {
12+
game: string;
13+
server: string;
14+
}
15+
},
16+
migrationNotice: {
17+
requiresUpdate: string;
18+
actionsDisabled: string;
19+
},
20+
filter: {
21+
placeholder: {
22+
game: string;
23+
server: string;
24+
};
25+
},
26+
actions: {
27+
select: {
28+
game: string;
29+
server: string;
30+
},
31+
setAsDefault: string;
32+
},
33+
tabs: {
34+
game: string;
35+
server: string;
36+
}
37+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export type PlatformMessageFormat = {
2+
STEAM: string;
3+
STEAM_DIRECT: string;
4+
EPIC_GAMES_STORE: string;
5+
OCULUS_STORE: string;
6+
ORIGIN: string;
7+
XBOX_GAME_PASS: string;
8+
OTHER: string;
9+
}

src/i18n/en/index.ts

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// This is just an example,
22
// so you can safely delete all default props below
33

4-
import { Message } from '../index';
4+
import { MessageFormat } from '../index';
55

6-
export default {
6+
const message: MessageFormat = {
77
metadata: {
88
name: 'English',
99
locale: 'en'
@@ -12,9 +12,53 @@ export default {
1212
pages: {
1313
gameSelection: {
1414
platformModal: {
15-
header: "Which store manages your game?"
15+
header: "Which store manages your game?",
16+
selectAction: "Select platform",
17+
},
18+
pageTitle: {
19+
title: {
20+
game: 'Game selection',
21+
server: 'Server selection',
22+
},
23+
subtitle: {
24+
game: 'Which game are you managing your mods for?',
25+
server: 'Which dedicated server are you managing your mods for?',
26+
}
27+
},
28+
migrationNotice: {
29+
requiresUpdate: 'An update to the manager has occurred and needs to do background work.',
30+
actionsDisabled: 'The options to select a game are disabled until the work has completed.',
31+
},
32+
tabs: {
33+
game: 'Game',
34+
server: 'Server'
35+
},
36+
actions: {
37+
select: {
38+
game: 'Select game',
39+
server: 'Select server'
40+
},
41+
setAsDefault: 'Set as default'
42+
},
43+
filter: {
44+
placeholder: {
45+
game: 'Search for a game',
46+
server: 'Search for a server',
47+
}
1648
}
1749
}
50+
},
51+
platforms: {
52+
STEAM: "Steam",
53+
STEAM_DIRECT: "Steam",
54+
EPIC_GAMES_STORE: "Epic Games Store",
55+
OCULUS_STORE: "Oculus Store",
56+
ORIGIN: "Origin / EA App",
57+
XBOX_GAME_PASS: "Xbox Game Pass",
58+
OTHER: "Autre",
1859
}
1960
}
20-
} as Message;
61+
};
62+
63+
// Exported separately to enforce validation on exported type
64+
export default message;

src/i18n/fr/index.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// This is just an example,
2+
// so you can safely delete all default props below
3+
4+
import { MessageFormat } from '../index';
5+
6+
const message: MessageFormat = {
7+
metadata: {
8+
name: 'French',
9+
locale: 'fr'
10+
},
11+
translations: {
12+
pages: {
13+
gameSelection: {
14+
platformModal: {
15+
header: "Sélectionnez le magasin pour vos jeux",
16+
selectAction: "Sélectionnez le magasin",
17+
},
18+
pageTitle: {
19+
title: {
20+
game: 'Sélectionnez un jeu',
21+
server: 'Sélectionnez un serveur',
22+
},
23+
subtitle: {
24+
game: 'Sélectionnez un jeu pour gérer vos mods',
25+
server: 'Sélectionnez un serveur pour gérer vos mods',
26+
}
27+
},
28+
migrationNotice: {
29+
requiresUpdate: 'Une mise à jour du gestionnaire a eu lieu et un travail de fond est nécessaire.',
30+
actionsDisabled: 'Les actions de sélection de jeu sont désactivées jusqu\'à ce que le travail soit terminé.'
31+
},
32+
tabs: {
33+
game: 'Jeu',
34+
server: 'Serveur'
35+
},
36+
actions: {
37+
select: {
38+
game: 'Sélectionner',
39+
server: 'Sélectionner'
40+
},
41+
setAsDefault: 'Définir par défaut'
42+
},
43+
filter: {
44+
placeholder: {
45+
game: 'Rechercher un jeu',
46+
server: 'Rechercher un serveur'
47+
}
48+
}
49+
}
50+
},
51+
platforms: {
52+
STEAM: "Steam",
53+
STEAM_DIRECT: "Steam",
54+
EPIC_GAMES_STORE: "Epic Games Store",
55+
OCULUS_STORE: "Oculus / Meta Magasin",
56+
ORIGIN: "Origin / EA App",
57+
XBOX_GAME_PASS: "Xbox Game Pass",
58+
OTHER: "Autre",
59+
}
60+
}
61+
};
62+
63+
// Exported separately to enforce validation on exported type
64+
export default message;

src/i18n/index.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
import enUS from './en';
1+
import langEn from './en';
2+
import langFr from './fr';
3+
import { PlatformMessageFormat } from './base/platforms/PlatformMessageFormat';
4+
import { GameSelectionMessageFormat } from './base/pages/GameSelectionMessageFormat';
25

36
export default {
4-
'en': enUS,
7+
'en': langEn,
8+
'fr': langFr,
59
};
610

711
// TODO - Use for language selection screens
@@ -10,15 +14,12 @@ export type MessageMetadata = {
1014
locale: string;
1115
}
1216

13-
export type Message = {
17+
export type MessageFormat = {
1418
metadata: MessageMetadata;
1519
translations: {
1620
pages: {
17-
gameSelection: {
18-
platformModal: {
19-
header: string;
20-
}
21-
}
22-
}
21+
gameSelection: GameSelectionMessageFormat
22+
},
23+
platforms: PlatformMessageFormat;
2324
}
2425
}

src/pages/GameSelectionScreen.vue

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,31 @@
22
<div>
33
<ModalCard id="select-platform-modal" v-show="showPlatformModal" :is-active="showPlatformModal" @close-modal="() => {showPlatformModal = false;}" class="z-max z-top">
44
<template v-slot:header>
5-
<h2 class='modal-title'>{{ t("translations.pages.gameSelection.platformModal.header") }}</h2>
5+
<h2 class='modal-title'>{{ t('translations.pages.gameSelection.platformModal.header') }}</h2>
66
</template>
77
<template v-slot:body>
88
<div v-if="selectedGame !== null">
99
<div v-for="(platform, index) of selectedGame.storePlatformMetadata" :key="`${index}-${platform.storePlatform}`">
1010
<input type="radio" :id="`${index}-${platform.storePlatform}`" :value="platform.storePlatform" v-model="selectedPlatform"/>
11-
<label :for="`${index}-${platform.storePlatform}`"><span class="margin-right margin-right--half-width"/>{{ platformLabels[platform.storePlatform] }}</label>
11+
<label :for="`${index}-${platform.storePlatform}`"><span class="margin-right margin-right--half-width"/>{{ t(`translations.platforms.${getPlatformKey(platform.storePlatform)}`) }}</label>
1212
</div>
1313
</div>
1414
</template>
1515
<template v-slot:footer>
1616
<button class='button is-info' @click='selectPlatform'>
17-
Select platform
17+
{{ t('translations.pages.gameSelection.platformModal.selectAction') }}
1818
</button>
1919
</template>
2020
</ModalCard>
2121
<hero
22-
:title="`${capitalize(activeTab)} selection`"
23-
:subtitle="
24-
activeTab === GameInstanceType.GAME
25-
? 'Which game are you managing your mods for?'
26-
: 'Which dedicated server are you managing your mods for?'
27-
"
22+
:title="t(`translations.pages.gameSelection.pageTitle.title.${activeTab}`)"
23+
:subtitle="t(`translations.pages.gameSelection.pageTitle.subtitle.${activeTab}`)"
2824
:heroType="activeTab === GameInstanceType.GAME ? 'primary' : 'warning'"
2925
/>
3026
<div class="notification is-warning is-square" v-if="runningMigration">
3127
<div class="container">
32-
<p>An update to the manager has occurred and needs to do background work.</p>
33-
<p>The options to select a game are disabled until the work has completed.</p>
28+
<p>{{ t('translations.pages.gameSelection.migrationNotice.requiresUpdate') }}</p>
29+
<p>{{ t('translations.pages.gameSelection.migrationNotice.actionsDisabled') }}</p>
3430
</div>
3531
</div>
3632
<div class="columns">
@@ -46,19 +42,19 @@
4642
id="game-selection-list-search"
4743
class="input margin-right"
4844
type="text"
49-
placeholder="Search for a game"
45+
:placeholder="t(`translations.pages.gameSelection.filter.placeholder.${activeTab}`)"
5046
autocomplete="off"
5147
/>
5248
</div>
5349
</div>
5450
</div>
5551
<div class="margin-right">
5652
<button class="button is-info"
57-
:disabled="!isAnyGameSelected() && !runningMigration" @click="selectGame(selectedGame)">Select {{ activeTab.toLowerCase() }}</button>
53+
:disabled="!isAnyGameSelected() && !runningMigration" @click="selectGame(selectedGame)">{{ t(`translations.pages.gameSelection.actions.select.${activeTab}`) }}</button>
5854
</div>
5955
<div class="margin-right">
6056
<button class="button"
61-
:disabled="!isAnyGameSelected() && !runningMigration" @click="selectDefaultGame(selectedGame)">Set as default</button>
57+
:disabled="!isAnyGameSelected() && !runningMigration" @click="selectDefaultGame(selectedGame)">{{ t('translations.pages.gameSelection.actions.setAsDefault') }}</button>
6258
</div>
6359
<div>
6460
<i class="button fas fa-th-large" @click="toggleViewMode"></i>
@@ -73,7 +69,7 @@
7369
id="game-selection-cards-search"
7470
class="input margin-right"
7571
type="text"
76-
placeholder="Search for a game"
72+
:placeholder="t(`translations.pages.gameSelection.filter.placeholder.${activeTab}`)"
7773
autocomplete="off"
7874
/>
7975
</div>
@@ -89,7 +85,7 @@
8985
<ul class="text-center">
9086
<li v-for="(value) in GameInstanceType" :key="`tab-${value}`"
9187
:class="[{'is-active': activeTab === value}]">
92-
<a @click="changeTab(value)">{{capitalize(value)}}</a>
88+
<a @click="changeTab(value)">{{ t(`translations.pages.gameSelection.tabs.${value}`) }}</a>
9389
</li>
9490
</ul>
9591
</div>
@@ -141,10 +137,13 @@
141137
</p>
142138
</div>
143139
<div class="absolute-center text-center">
144-
<button class="button is-info" @click="selectGame(game)" :class="[{'is-disabled': selectedGame === null}]">Select
145-
{{ activeTab.toLowerCase() }}</button>
140+
<button class="button is-info" @click="selectGame(game)" :class="[{'is-disabled': selectedGame === null}]">
141+
{{ t(`translations.pages.gameSelection.actions.select.${activeTab}`) }}
142+
</button>
146143
<br/><br/>
147-
<button class="button" @click="selectDefaultGame(game)">Set as default</button>
144+
<button class="button" @click="selectDefaultGame(game)">
145+
{{ t('translations.pages.gameSelection.actions.setAsDefault') }}
146+
</button>
148147
</div>
149148
</div>
150149
</div>
@@ -190,6 +189,7 @@ import { State } from '../store';
190189
import { useRouter } from 'vue-router';
191190
import ProtocolProvider from '../providers/generic/protocol/ProtocolProvider';
192191
import { useI18n } from 'vue-i18n';
192+
import EnumResolver from '../model/enums/_EnumResolver';
193193
194194
const store = getStore<State>();
195195
const router = useRouter();
@@ -207,6 +207,10 @@ const viewMode = ref<GameSelectionViewMode>(GameSelectionViewMode.LIST);
207207
const activeTab = ref<GameInstanceType>(GameInstanceType.GAME);
208208
const gameImages = reactive({});
209209
210+
function getPlatformKey(platform: Platform) {
211+
return EnumResolver.from(Platform, platform);
212+
}
213+
210214
const filteredGameList = computed(() => {
211215
const displayNameInAdditionalSearch = (game: Game, filterText: string): boolean => {
212216
return game.additionalSearchStrings.find(value => value.toLowerCase().trim().indexOf(filterText.toLowerCase().trim()) >= 0) !== undefined;
@@ -280,16 +284,6 @@ function selectDefaultGame(game: Game) {
280284
}
281285
}
282286
283-
const platformLabels = {
284-
[Platform.STEAM]: "Steam",
285-
[Platform.STEAM_DIRECT]: "Steam",
286-
[Platform.EPIC_GAMES_STORE]: "Epic Games Store",
287-
[Platform.OCULUS_STORE]: "Oculus Store",
288-
[Platform.ORIGIN]: "Origin / EA Desktop",
289-
[Platform.XBOX_GAME_PASS]: "Xbox Game Pass",
290-
[Platform.OTHER]: "Other"
291-
}
292-
293287
function selectPlatform() {
294288
if (isSettingDefaultPlatform.value) {
295289
proceedDefault()

0 commit comments

Comments
 (0)