From 714487e6aa75eab328286de1a0c6a760c0a60f3a Mon Sep 17 00:00:00 2001 From: Cian Monnin Date: Thu, 25 Jul 2024 16:15:42 -0400 Subject: [PATCH] fix: working on lang --- package.json | 2 + pnpm-lock.yaml | 75 +++++++++++++++ public/data.csv | 132 ++++++++++++++++++--------- public/experimentSettings.csv | 4 +- src/fetchAndParse.ts | 26 +++--- src/main.tsx | 9 +- src/pictureNamingTask.ts | 12 ++- src/services/i18n.ts | 20 ++++ src/translations/en/translation.json | 11 +++ src/translations/fr/translation.json | 11 +++ 10 files changed, 236 insertions(+), 66 deletions(-) create mode 100644 src/services/i18n.ts create mode 100644 src/translations/en/translation.json create mode 100644 src/translations/fr/translation.json diff --git a/package.json b/package.json index 5f1b011..3af515b 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "@jspsych/plugin-survey-html-form": "^2.0.0", "@jspsych/plugin-survey-text": "^2.0.0", "@types/node": "^20.14.12", + "i18next": "^23.12.2", + "i18next-http-backend": "^2.5.2", "jspsych": "^8.0.1", "papaparse": "^5.4.1", "pure-rand": "^6.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4e044fe..27597b8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,12 @@ importers: '@types/node': specifier: ^20.14.12 version: 20.14.12 + i18next: + specifier: ^23.12.2 + version: 23.12.2 + i18next-http-backend: + specifier: ^2.5.2 + version: 2.5.2 jspsych: specifier: ^8.0.1 version: 8.0.1 @@ -179,6 +185,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/runtime@7.24.8': + resolution: {integrity: sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==} + engines: {node: '>=6.9.0'} + '@babel/template@7.24.7': resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} engines: {node: '>=6.9.0'} @@ -690,6 +700,9 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cross-fetch@4.0.0: + resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -863,6 +876,12 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + i18next-http-backend@2.5.2: + resolution: {integrity: sha512-+K8HbDfrvc1/2X8jpb7RLhI9ZxBDpx3xogYkQwGKlWAUXLSEGXzgdt3EcUjLlBCdMwdQY+K+EUF6oh8oB6rwHw==} + + i18next@23.12.2: + resolution: {integrity: sha512-XIeh5V+bi8SJSWGL3jqbTEBW5oD6rbP5L+E7dVQh1MNTxxYef0x15rhJVcRb7oiuq4jLtgy2SD8eFlf6P2cmqg==} + ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -977,6 +996,15 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} @@ -1059,6 +1087,9 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1138,6 +1169,9 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -1201,6 +1235,12 @@ packages: terser: optional: true + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -1345,6 +1385,10 @@ snapshots: '@babel/core': 7.24.9 '@babel/helper-plugin-utils': 7.24.8 + '@babel/runtime@7.24.8': + dependencies: + regenerator-runtime: 0.14.1 + '@babel/template@7.24.7': dependencies: '@babel/code-frame': 7.24.7 @@ -1799,6 +1843,12 @@ snapshots: convert-source-map@2.0.0: {} + cross-fetch@4.0.0: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 @@ -2015,6 +2065,16 @@ snapshots: has-flag@4.0.0: {} + i18next-http-backend@2.5.2: + dependencies: + cross-fetch: 4.0.0 + transitivePeerDependencies: + - encoding + + i18next@23.12.2: + dependencies: + '@babel/runtime': 7.24.8 + ignore@5.3.1: {} import-fresh@3.3.0: @@ -2110,6 +2170,10 @@ snapshots: natural-compare@1.4.0: {} + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + node-releases@2.0.18: {} once@1.4.0: @@ -2181,6 +2245,8 @@ snapshots: dependencies: loose-envify: 1.4.0 + regenerator-runtime@0.14.1: {} + resolve-from@4.0.0: {} reusify@1.0.4: {} @@ -2257,6 +2323,8 @@ snapshots: dependencies: is-number: 7.0.0 + tr46@0.0.3: {} + ts-api-utils@1.3.0(typescript@5.5.4): dependencies: typescript: 5.5.4 @@ -2292,6 +2360,13 @@ snapshots: '@types/node': 20.14.12 fsevents: 2.3.3 + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + which@2.0.2: dependencies: isexe: 2.0.0 diff --git a/public/data.csv b/public/data.csv index 658c344..73cd0f6 100644 --- a/public/data.csv +++ b/public/data.csv @@ -1,45 +1,89 @@ stimulus,difficultyLevel,correctResponse,language -level1/addressplate.jpg,1,addressplate,EN -level1/bandage.jpg,1,bandage,EN -level1/bowrake.jpg,1,bowrake,EN -level1/bracelet04.jpg,1,bracelet04,EN -level1/broccoli01a.jpg,1,broccoli01a,EN -level2/africanelephant.jpg,2,africanelephant,EN -level2/almond.jpg,2,almond,EN -level2/bandaid01.jpg,2,bandaid01,EN -level2/bathtub.jpg,2,bathtub,EN -level2/belt02a.jpg,2,belt02a,EN -level3/acousticguitar02.jpg,3,acousticguitar02,EN -level3/apple07.jpg,3,apple07,EN -level3/asparagus.jpg,3,asparagus,EN -level3/bagel01.jpg,3,bagel01,EN -level3/blackbear.jpg,3,blackbear,EN -level4/accordion01.jpg,4,accordion01,EN -level4/binder03b.jpg,4,binder03b,EN -level4/birdnest.jpg,4,birdnest,EN -level4/bridge.jpg,4,bridge,EN -level4/cactus.jpg,4,cactus,EN -level5/baguette01.jpg,5,baguette01,EN -level5/bed.jpg,5,bed,EN -level5/blackberry.jpg,5,blackberry,EN -level5/boatmotor.jpg,5,boatmotor,EN -level5/bowl02a.jpg,5,bowl02a,EN -level6/ant.jpg,6,ant,EN -level6/barn.jpg,6,barn,EN -level6/baseboardheater01.jpg,6,baseboardheater01,EN -level6/birdie.jpg,6,birdie,EN -level6/bleachers.jpg,6,bleachers,EN -level7/aircompressor.jpg,7,aircompressor,EN -level7/arm.jpg,7,arm,EN -level7/arugula.jpg,7,arugula,EN -level7/atm.jpg,7,atm,EN -level7/barrel01.jpg,7,barrel01,EN -level8/aquarium.jpg,8,aquarium,EN -level8/ashtray01.jpg,8,ashtray01,EN -level8/avcable.jpg,8,avcable,EN -level8/axe01.jpg,8,axe01,EN -level9/anchor.jpg,9,anchor,EN -level9/awning.jpg,9,awning,EN -level9/badmintonracket.jpg,9,badmintonracket,EN -level9/bagofpowder.jpg,9,bagofpowder,EN -level9/banana01.jpg,9,banana01,EN +level1/addressplate.jpg,1,addressplate,en +level1/bandage.jpg,1,bandage,en +level1/bowrake.jpg,1,bowrake,en +level1/bracelet04.jpg,1,bracelet04,en +level1/broccoli01a.jpg,1,broccoli01a,en +level2/africanelephant.jpg,2,africanelephant,en +level2/almond.jpg,2,almond,en +level2/bandaid01.jpg,2,bandaid01,en +level2/bathtub.jpg,2,bathtub,en +level2/belt02a.jpg,2,belt02a,en +level3/acousticguitar02.jpg,3,acousticguitar02,en +level3/apple07.jpg,3,apple07,en +level3/asparagus.jpg,3,asparagus,en +level3/bagel01.jpg,3,bagel01,en +level3/blackbear.jpg,3,blackbear,en +level4/accordion01.jpg,4,accordion01,en +level4/binder03b.jpg,4,binder03b,en +level4/birdnest.jpg,4,birdnest,en +level4/bridge.jpg,4,bridge,en +level4/cactus.jpg,4,cactus,en +level5/baguette01.jpg,5,baguette01,en +level5/bed.jpg,5,bed,en +level5/blackberry.jpg,5,blackberry,en +level5/boatmotor.jpg,5,boatmotor,en +level5/bowl02a.jpg,5,bowl02a,en +level6/ant.jpg,6,ant,en +level6/barn.jpg,6,barn,en +level6/baseboardheater01.jpg,6,baseboardheater01,en +level6/birdie.jpg,6,birdie,en +level6/bleachers.jpg,6,bleachers,en +level7/aircompressor.jpg,7,aircompressor,en +level7/arm.jpg,7,arm,en +level7/arugula.jpg,7,arugula,en +level7/atm.jpg,7,atm,en +level7/barrel01.jpg,7,barrel01,en +level8/aquarium.jpg,8,aquarium,en +level8/ashtray01.jpg,8,ashtray01,en +level8/avcable.jpg,8,avcable,en +level8/axe01.jpg,8,axe01,en +level9/anchor.jpg,9,anchor,en +level9/awning.jpg,9,awning,en +level9/badmintonracket.jpg,9,badmintonracket,en +level9/bagofpowder.jpg,9,bagofpowder,en +level9/banana01.jpg,9,banana01,en +level1/addressplate.jpg,1,addressplate,fr +level1/bandage.jpg,1,bandage,fr +level1/bowrake.jpg,1,bowrake,fr +level1/bracelet04.jpg,1,bracelet04,fr +level1/broccoli01a.jpg,1,broccoli01a,fr +level2/africanelephant.jpg,2,africanelephant,fr +level2/almond.jpg,2,almond,fr +level2/bandaid01.jpg,2,bandaid01,fr +level2/bathtub.jpg,2,bathtub,fr +level2/belt02a.jpg,2,belt02a,fr +level3/acousticguitar02.jpg,3,acousticguitar02,fr +level3/apple07.jpg,3,apple07,fr +level3/asparagus.jpg,3,asparagus,fr +level3/bagel01.jpg,3,bagel01,fr +level3/blackbear.jpg,3,blackbear,fr +level4/accordion01.jpg,4,accordion01,fr +level4/binder03b.jpg,4,binder03b,fr +level4/birdnest.jpg,4,birdnest,fr +level4/bridge.jpg,4,bridge,fr +level4/cactus.jpg,4,cactus,fr +level5/baguette01.jpg,5,baguette01,fr +level5/bed.jpg,5,bed,fr +level5/blackberry.jpg,5,blackberry,fr +level5/boatmotor.jpg,5,boatmotor,fr +level5/bowl02a.jpg,5,bowl02a,fr +level6/ant.jpg,6,ant,fr +level6/barn.jpg,6,barn,fr +level6/baseboardheater01.jpg,6,baseboardheater01,fr +level6/birdie.jpg,6,birdie,fr +level6/bleachers.jpg,6,bleachers,fr +level7/aircompressor.jpg,7,aircompressor,fr +level7/arm.jpg,7,arm,fr +level7/arugula.jpg,7,arugula,fr +level7/atm.jpg,7,atm,fr +level7/barrel01.jpg,7,barrel01,fr +level8/aquarium.jpg,8,aquarium,fr +level8/ashtray01.jpg,8,ashtray01,fr +level8/avcable.jpg,8,avcable,fr +level8/axe01.jpg,8,axe01,fr +level9/anchor.jpg,9,anchor,fr +level9/awning.jpg,9,awning,fr +level9/badmintonracket.jpg,9,badmintonracket,fr +level9/bagofpowder.jpg,9,bagofpowder,fr +level9/banana01.jpg,9,banana01,fr diff --git a/public/experimentSettings.csv b/public/experimentSettings.csv index a7a571d..66fa0f5 100644 --- a/public/experimentSettings.csv +++ b/public/experimentSettings.csv @@ -1,2 +1,2 @@ -totalNumberOfTrialsToRun,advancementSchedule,regressionSchedule,language, seed -5,2,0,EN, 42 +totalNumberOfTrialsToRun,advancementSchedule,regressionSchedule,language,seed,initalDifficulty +5,2,0,fr,42,1 diff --git a/src/fetchAndParse.ts b/src/fetchAndParse.ts index 464b144..c105e13 100644 --- a/src/fetchAndParse.ts +++ b/src/fetchAndParse.ts @@ -2,15 +2,15 @@ import Papa from "papaparse"; import "./style.css"; async function fetchAndParse(path: string) { - console.log('path') - console.log(path) + console.log("path"); + console.log(path); try { const response = await fetch(path, { headers: { Accept: "text/csv" }, method: "GET", }); if (!response.ok) { - console.log(response) + console.log(response); const container = document.createElement(`div`); const p = document.createElement("p"); const msg = document.createElement(`h1`); @@ -32,31 +32,32 @@ async function fetchAndParse(path: string) { const responseText = await response.text(); const data = Papa.parse(responseText, { header: true }); - console.log('fetch and parse got data') + console.log("fetch and parse got data"); console.log(data); return data; } catch (error) { - console.log('error:') + console.log("error:"); console.log(error); } } const baseUrl = import.meta.env.BASE_URL; -const dataPath = baseUrl + 'data.csv' -const experimentSettingsPath = baseUrl + 'experimentSettings.csv' +console.log(`BaseUrl: ${baseUrl}`); +const dataPath = baseUrl + "data.csv"; +const experimentSettingsPath = baseUrl + "experimentSettings.csv"; const parsedImageDB = await fetchAndParse(dataPath); if (!parsedImageDB) { throw new Error("Failed to fetch and parse the data.csv."); } else { - console.log('parsedImageDB') + console.log("parsedImageDB"); console.table(parsedImageDB); } -const parsedExperimentSettings = await fetchAndParse(experimentSettingsPath) +const parsedExperimentSettings = await fetchAndParse(experimentSettingsPath); if (!parsedExperimentSettings) { - throw new Error('Failes to fetch and parse the experimentSettings.csv.') + throw new Error("Failes to fetch and parse the experimentSettings.csv."); } else { - console.log('experimentSettings') - console.table(parsedExperimentSettings) + console.log("experimentSettings"); + console.table(parsedExperimentSettings); } interface ImageBank { stimulus: string; @@ -71,6 +72,7 @@ interface Settings { regressionSchedule: number | string; language: string; seed: number; + initialDifficulty: number | string; } const experimentSettings: Settings = parsedExperimentSettings diff --git a/src/main.tsx b/src/main.tsx index e3dfc89..3131f5c 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,9 +1,4 @@ -// write a fuction to fetch the .csv, -// -// aysnc funv with a try catch -// -// h -// import pictureNamingTask from "./pictureNamingTask"; +import { experimentSettings } from "./fetchAndParse"; -pictureNamingTask(1); +pictureNamingTask(Number(experimentSettings.initialDifficulty)); diff --git a/src/pictureNamingTask.ts b/src/pictureNamingTask.ts index d998ded..2ff9811 100644 --- a/src/pictureNamingTask.ts +++ b/src/pictureNamingTask.ts @@ -8,6 +8,16 @@ import { transformAndDownload } from "./dataMunger"; import { experimentSettings } from "./fetchAndParse"; import { imageDB } from "./fetchAndParse"; import prand from "pure-rand"; +import i18n from "./services/i18n.ts"; +/* + * Translations + * + * + */ + +const welcomeText = i18n.t("welcome"); +console.log("++++++++++++++"); +console.log(welcomeText); //**************************** //****EXPERIMENT_SETTINGS***** //**************************** @@ -114,7 +124,7 @@ export default function pictureNamingTask(difficultyLevelParam: number) { const welcome = { type: HtmlKeyboardResponsePlugin, - stimulus: "Welcome. Press any key to begin", + stimulus: `welcome`, }; const preload = { diff --git a/src/services/i18n.ts b/src/services/i18n.ts new file mode 100644 index 0000000..a608a34 --- /dev/null +++ b/src/services/i18n.ts @@ -0,0 +1,20 @@ +import i18n from "i18next"; +import Backend from "i18next-http-backend"; +import { experimentSettings } from "../fetchAndParse"; + +i18n.use(Backend).init({ + initImmediate: false, + lng: experimentSettings.language, + fallbackLng: "en", + preload: ["en", "fr"], + ns: ["translation"], + defaultNS: "translation", + backend: { + loadPath: "../translations/{{lng}}/{{ns}}.json", + }, +}); +// this will only work if initImmediate is set to false, because it's async +console.log("**** i18n init"); +console.log(i18n.t("welcome")); +console.log(i18n.t("welcome", { lng: "fr" })); +export default i18n; diff --git a/src/translations/en/translation.json b/src/translations/en/translation.json new file mode 100644 index 0000000..4d7135d --- /dev/null +++ b/src/translations/en/translation.json @@ -0,0 +1,11 @@ +{ + "welcome": "Welcome. Press any key to begin", + "correctResponse": "Correct response:", + "loadingStimulus": "Loading stimulus", + "logResponse": "Log the response", + "correct": "Correct", + "incorrect": "Incorrect", + "responseWas": "The response was:", + "logNotes": "Log any other notes here", + "logResponseToContinue": "Log response and press submit to continue" +} diff --git a/src/translations/fr/translation.json b/src/translations/fr/translation.json new file mode 100644 index 0000000..9cde8c2 --- /dev/null +++ b/src/translations/fr/translation.json @@ -0,0 +1,11 @@ +{ + "welcome": "Bienvenue. Appuyez sur n'importe quelle touche pour commencer", + "correctResponse": "La réponse correcte est:", + "loadingStimulus": "Stimulus de chargement", + "logResponse": "Enregistrer la réponse", + "correct": "Correct", + "incorrect": "Incorrect", + "responseWas": "La réponse a été donnée:", + "logNotes": "Inscrivez ici toute autre note", + "logResponseToContinue": "Enregistrez la réponse et appuyez sur 'soumettre' pour continuer" +}