Add i18next framework to enable further contributions (#96)
* prototype * Update with comments and type safetypull/97/head
parent
b44ee95610
commit
73c9625df1
|
@ -10,6 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material/material-color-utilities": "^0.2.7",
|
"@material/material-color-utilities": "^0.2.7",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
|
"i18next": "^23.11.1",
|
||||||
"json-stable-stringify": "^1.1.0",
|
"json-stable-stringify": "^1.1.0",
|
||||||
"phaser": "^3.70.0",
|
"phaser": "^3.70.0",
|
||||||
"phaser3-rex-plugins": "^1.1.84"
|
"phaser3-rex-plugins": "^1.1.84"
|
||||||
|
@ -2750,9 +2751,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/i18next": {
|
"node_modules/i18next": {
|
||||||
"version": "22.5.1",
|
"version": "23.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.1.tgz",
|
||||||
"integrity": "sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==",
|
"integrity": "sha512-mXw4A24BiPZKRsbb9ewgSvjYd6fxFCNwJyfK6nYfSTIAX2GkCWcb598m3DFkDZmqADatvuASrKo6qwORz3VwTQ==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
|
@ -2768,7 +2769,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.6"
|
"@babel/runtime": "^7.23.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/i18next-http-backend": {
|
"node_modules/i18next-http-backend": {
|
||||||
|
@ -3819,6 +3820,28 @@
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
|
||||||
"integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="
|
"integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="
|
||||||
},
|
},
|
||||||
|
"node_modules/phaser3-rex-plugins/node_modules/i18next": {
|
||||||
|
"version": "22.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.1.tgz",
|
||||||
|
"integrity": "sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://locize.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://locize.com/i18next.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.20.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/phaser3spectorjs": {
|
"node_modules/phaser3spectorjs": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/phaser3spectorjs/-/phaser3spectorjs-0.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/phaser3spectorjs/-/phaser3spectorjs-0.0.8.tgz",
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material/material-color-utilities": "^0.2.7",
|
"@material/material-color-utilities": "^0.2.7",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
|
"i18next": "^23.11.1",
|
||||||
"json-stable-stringify": "^1.1.0",
|
"json-stable-stringify": "^1.1.0",
|
||||||
"phaser": "^3.70.0",
|
"phaser": "^3.70.0",
|
||||||
"phaser3-rex-plugins": "^1.1.84"
|
"phaser3-rex-plugins": "^1.1.84"
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
/**
|
||||||
|
* The menu namespace holds most miscellaneous text that isn't directly part of the game's
|
||||||
|
* contents or directly related to Pokemon. This includes menu navigation, settings,
|
||||||
|
* account interactions, etc.
|
||||||
|
*/
|
||||||
|
export const menu = {
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"continue": "Continue",
|
||||||
|
"dailyRun": "Daily Run (Beta)",
|
||||||
|
"loadGame": "Load Game",
|
||||||
|
"newGame": "New Game",
|
||||||
|
"selectGameMode": "Select a game mode."
|
||||||
|
} as const;
|
|
@ -0,0 +1,8 @@
|
||||||
|
export const menu = {
|
||||||
|
"cancel": "Annulla",
|
||||||
|
"continue": "Continua",
|
||||||
|
"newGame": "Nuova Partita",
|
||||||
|
"loadGame": "Carica Partita",
|
||||||
|
"dailyRun": "Corsa Giornaliera (Beta)",
|
||||||
|
"selectGameMode": "Seleziona una modalità di gioco."
|
||||||
|
} as const;
|
|
@ -57,6 +57,7 @@ import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler";
|
||||||
import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run";
|
import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run";
|
||||||
import { GameModes, gameModes } from "./game-mode";
|
import { GameModes, gameModes } from "./game-mode";
|
||||||
import { getPokemonSpecies, speciesStarters } from "./data/pokemon-species";
|
import { getPokemonSpecies, speciesStarters } from "./data/pokemon-species";
|
||||||
|
import i18next from './plugins/i18n';
|
||||||
|
|
||||||
export class LoginPhase extends Phase {
|
export class LoginPhase extends Phase {
|
||||||
private showText: boolean;
|
private showText: boolean;
|
||||||
|
@ -173,12 +174,12 @@ export class TitlePhase extends Phase {
|
||||||
const options: OptionSelectItem[] = [];
|
const options: OptionSelectItem[] = [];
|
||||||
if (loggedInUser.lastSessionSlot > -1) {
|
if (loggedInUser.lastSessionSlot > -1) {
|
||||||
options.push({
|
options.push({
|
||||||
label: 'Continue',
|
label: i18next.t('menu:continue'),
|
||||||
handler: () => this.loadSaveSlot(this.lastSessionData ? -1 : loggedInUser.lastSessionSlot)
|
handler: () => this.loadSaveSlot(this.lastSessionData ? -1 : loggedInUser.lastSessionSlot)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
options.push({
|
options.push({
|
||||||
label: 'New Game',
|
label: i18next.t('menu:newGame'),
|
||||||
handler: () => {
|
handler: () => {
|
||||||
const setModeAndEnd = (gameMode: GameModes) => {
|
const setModeAndEnd = (gameMode: GameModes) => {
|
||||||
this.gameMode = gameMode;
|
this.gameMode = gameMode;
|
||||||
|
@ -204,14 +205,14 @@ export class TitlePhase extends Phase {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
options.push({
|
options.push({
|
||||||
label: 'Cancel',
|
label: i18next.t('menu:cancel'),
|
||||||
handler: () => {
|
handler: () => {
|
||||||
this.scene.clearPhaseQueue();
|
this.scene.clearPhaseQueue();
|
||||||
this.scene.pushPhase(new TitlePhase(this.scene));
|
this.scene.pushPhase(new TitlePhase(this.scene));
|
||||||
super.end();
|
super.end();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.scene.ui.showText('Select a game mode.', null, () => this.scene.ui.setOverlayMode(Mode.OPTION_SELECT, { options: options }));
|
this.scene.ui.showText(i18next.t("menu:selectGameMode"), null, () => this.scene.ui.setOverlayMode(Mode.OPTION_SELECT, { options: options }));
|
||||||
} else {
|
} else {
|
||||||
this.gameMode = GameModes.CLASSIC;
|
this.gameMode = GameModes.CLASSIC;
|
||||||
this.scene.ui.setMode(Mode.MESSAGE);
|
this.scene.ui.setMode(Mode.MESSAGE);
|
||||||
|
@ -221,7 +222,7 @@ export class TitlePhase extends Phase {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Load Game',
|
label: i18next.t('menu:loadGame'),
|
||||||
handler: () => this.scene.ui.setOverlayMode(Mode.SAVE_SLOT, SaveSlotUiMode.LOAD,
|
handler: () => this.scene.ui.setOverlayMode(Mode.SAVE_SLOT, SaveSlotUiMode.LOAD,
|
||||||
(slotId: integer) => {
|
(slotId: integer) => {
|
||||||
if (slotId === -1)
|
if (slotId === -1)
|
||||||
|
@ -231,7 +232,7 @@ export class TitlePhase extends Phase {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Daily Run (Beta)',
|
label: i18next.t('menu:dailyRun'),
|
||||||
handler: () => this.initDailyRun(),
|
handler: () => this.initDailyRun(),
|
||||||
keepOpen: true
|
keepOpen: true
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import i18next from 'i18next';
|
||||||
|
import { menu as enMenu } from '../locales/en/menu';
|
||||||
|
import { menu as itMenu } from '../locales/it/menu';
|
||||||
|
|
||||||
|
const DEFAULT_LANGUAGE_OVERRIDE = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i18next is a localization library for maintaining and using translation resources.
|
||||||
|
*
|
||||||
|
* Q: How do I add a new language?
|
||||||
|
* A: To add a new language, create a new folder in the locales directory with the language code.
|
||||||
|
* Each language folder should contain a file for each namespace (ex. menu.ts) with the translations.
|
||||||
|
*
|
||||||
|
* Q: How do I add a new namespace?
|
||||||
|
* A: To add a new namespace, create a new file in each language folder with the translations.
|
||||||
|
* Then update the `resources` field in the init() call and the CustomTypeOptions interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
i18next.init({
|
||||||
|
lng: DEFAULT_LANGUAGE_OVERRIDE ? DEFAULT_LANGUAGE_OVERRIDE : 'en',
|
||||||
|
fallbackLng: 'en',
|
||||||
|
debug: true,
|
||||||
|
resources: {
|
||||||
|
en: {
|
||||||
|
menu: enMenu,
|
||||||
|
},
|
||||||
|
it: {
|
||||||
|
menu: itMenu,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Module declared to make referencing keys in the localization files type-safe.
|
||||||
|
declare module 'i18next' {
|
||||||
|
interface CustomTypeOptions {
|
||||||
|
resources: {
|
||||||
|
menu: typeof enMenu;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default i18next;
|
Loading…
Reference in New Issue