From 7fac0d70c85c3115bd7cf6cecbbc03dfe1e76de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Korbinian=20P=C3=B6ppel?= <37810656+kpoeppel@users.noreply.github.com> Date: Sun, 5 Feb 2023 07:10:53 +0100 Subject: [PATCH] Live language feedback (#1071) * Add live language detection using 'lande' in TrackedTextarea. * Remove 'Disable Language Detection'. * Re-run linter. --- website/package-lock.json | 27 +++ website/package.json | 1 + .../src/components/Survey/TrackedTextarea.tsx | 70 ++++++- website/src/lib/iso6393.ts | 187 ++++++++++++++++++ 4 files changed, 282 insertions(+), 3 deletions(-) create mode 100644 website/src/lib/iso6393.ts diff --git a/website/package-lock.json b/website/package-lock.json index fe03e145..3b8220e5 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -32,6 +32,7 @@ "eslint-plugin-simple-import-sort": "^8.0.0", "focus-visible": "^5.2.0", "framer-motion": "^6.5.1", + "lande": "^1.0.10", "lucide-react": "^0.105.0", "next": "13.0.6", "next-auth": "^4.18.6", @@ -26611,6 +26612,14 @@ "node": ">= 8" } }, + "node_modules/lande": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/lande/-/lande-1.0.10.tgz", + "integrity": "sha512-yT52DQh+UV2pEp08jOYrA4drDv0DbjpiRyZYgl25ak9G2cVR2AimzrqkYQWrD9a7Ud+qkAcaiDDoNH9DXfHPmw==", + "dependencies": { + "toygrad": "^2.6.0" + } + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -36420,6 +36429,11 @@ "node": ">=0.8" } }, + "node_modules/toygrad": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/toygrad/-/toygrad-2.6.0.tgz", + "integrity": "sha512-g4zBmlSbvzOE5FOILxYkAybTSxijKLkj1WoNqVGnbMcWDyj4wWQ+eYSr3ik7XOpIgMq/7eBcPRTJX3DM2E0YMg==" + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -58708,6 +58722,14 @@ "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", "dev": true }, + "lande": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/lande/-/lande-1.0.10.tgz", + "integrity": "sha512-yT52DQh+UV2pEp08jOYrA4drDv0DbjpiRyZYgl25ak9G2cVR2AimzrqkYQWrD9a7Ud+qkAcaiDDoNH9DXfHPmw==", + "requires": { + "toygrad": "^2.6.0" + } + }, "language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -65936,6 +65958,11 @@ "punycode": "^2.1.1" } }, + "toygrad": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/toygrad/-/toygrad-2.6.0.tgz", + "integrity": "sha512-g4zBmlSbvzOE5FOILxYkAybTSxijKLkj1WoNqVGnbMcWDyj4wWQ+eYSr3ik7XOpIgMq/7eBcPRTJX3DM2E0YMg==" + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", diff --git a/website/package.json b/website/package.json index c68b1537..7ab3f3d8 100644 --- a/website/package.json +++ b/website/package.json @@ -50,6 +50,7 @@ "eslint-plugin-simple-import-sort": "^8.0.0", "focus-visible": "^5.2.0", "framer-motion": "^6.5.1", + "lande": "^1.0.10", "lucide-react": "^0.105.0", "next": "13.0.6", "next-auth": "^4.18.6", diff --git a/website/src/components/Survey/TrackedTextarea.tsx b/website/src/components/Survey/TrackedTextarea.tsx index f408e168..196d2f1a 100644 --- a/website/src/components/Survey/TrackedTextarea.tsx +++ b/website/src/components/Survey/TrackedTextarea.tsx @@ -1,4 +1,23 @@ -import { Progress, Stack, Textarea, TextareaProps, useColorModeValue } from "@chakra-ui/react"; +import {} from "@chakra-ui/react"; +import lande from "lande"; +import { LanguageAbbreviations } from "src/lib/iso6393"; +import { useCookies } from "react-cookie"; +import React from "react"; +import { + Progress, + Stack, + Textarea, + TextareaProps, + useColorModeValue, + Button, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalHeader, + ModalOverlay, + useDisclosure, +} from "@chakra-ui/react"; interface TrackedTextboxProps { text: string; @@ -11,10 +30,55 @@ interface TrackedTextboxProps { onTextChange: (event: React.ChangeEvent) => void; } -export const TrackedTextarea = (props: TrackedTextboxProps) => { - const backgroundColor = useColorModeValue("gray.100", "gray.900"); +const killEvent = (e) => e.stopPropagation(); +export const TrackedTextarea = (props: TrackedTextboxProps) => { + const [wordLimitForLangDetection, setWordLimitForLangDetection] = React.useState(10); + const backgroundColor = useColorModeValue("gray.100", "gray.900"); + const [cookies] = useCookies(["NEXT_LOCALE"]); const wordCount = (props.text.match(/\w+/g) || []).length; + const { isOpen, onOpen, onClose } = useDisclosure(); + const currentLanguage = cookies["NEXT_LOCALE"]; + + const closeTemporaryIgnoreLanguageDetection = () => { + setWordLimitForLangDetection(2 * wordCount); + onClose(); + }; + + console.log("", wordCount, wordLimitForLangDetection); + if (wordCount > wordLimitForLangDetection) { + let mostProbableLanguage; + try { + mostProbableLanguage = LanguageAbbreviations[lande(props.text)[0][0]]; + } catch (error) { + mostProbableLanguage = ""; + } + + /*const mostProbableLanguage = lande(props.text);*/ + if (mostProbableLanguage !== currentLanguage) { + setTimeout(() => { + onOpen(); + }, 200); + + return ( + <> + + {/* we kill the event here to disable drag and drop, since it is in the same container */} + + + Switch Language? + + + Do you want to switch language? The detected language is {mostProbableLanguage}, whereas your + chosen language is {currentLanguage}. The language can be changed on the top right. + + + + + + ); + } + } let progressColor: string; switch (true) { diff --git a/website/src/lib/iso6393.ts b/website/src/lib/iso6393.ts new file mode 100644 index 00000000..3720150a --- /dev/null +++ b/website/src/lib/iso6393.ts @@ -0,0 +1,187 @@ +export const LanguageAbbreviations = { + aar: "aa", + abk: "ab", + afr: "af", + aka: "ak", + alb: "sq", + amh: "am", + ara: "ar", + arg: "an", + hye: "hy", + asm: "as", + ava: "av", + ave: "ae", + aym: "ay", + aze: "az", + bak: "ba", + bam: "bm", + eus: "eu", + bel: "be", + ben: "bn", + bih: "bh", + bis: "bi", + tib: "bo", + bos: "bs", + bre: "br", + bul: "bg", + mya: "my", + cat: "ca", + cze: "cs", + cha: "ch", + che: "ce", + zho: "zh", + chu: "cu", + chv: "cv", + cor: "kw", + cos: "co", + cre: "cr", + wel: "cy", + dan: "da", + ger: "de", + deu: "de", + div: "dv", + dut: "nl", + dzo: "dz", + gre: "el", + eng: "en", + epo: "eo", + est: "et", + ewe: "ee", + fao: "fo", + per: "fa", + fij: "fj", + fin: "fi", + fra: "fr", + fry: "fy", + ful: "ff", + geo: "ka", + gla: "gd", + gle: "ga", + glg: "gl", + glv: "gv", + grn: "gn", + guj: "gu", + hat: "ht", + hau: "ha", + heb: "he", + her: "hz", + hin: "hi", + hmo: "ho", + hrv: "hr", + hun: "hu", + ibo: "ig", + ice: "is", + ido: "io", + iii: "ii", + iku: "iu", + ile: "ie", + ina: "ia", + ind: "id", + ipk: "ik", + ita: "it", + jav: "jv", + jpn: "ja", + kal: "kl", + kan: "kn", + kas: "ks", + kau: "kr", + kaz: "kk", + khm: "km", + kik: "ki", + kin: "rw", + kir: "ky", + kom: "kv", + kon: "kg", + kor: "ko", + kua: "kj", + kur: "ku", + lao: "lo", + lat: "la", + lav: "lv", + lim: "li", + lin: "ln", + lit: "lt", + ltz: "lb", + lub: "lu", + lug: "lg", + mkd: "mk", + mah: "mh", + mal: "ml", + mri: "mi", + mar: "mr", + may: "ms", + mlg: "mg", + mlt: "mt", + mon: "mn", + nau: "na", + nav: "nv", + nbl: "nr", + nde: "nd", + ndo: "ng", + nep: "ne", + nno: "nn", + nob: "nb", + nor: "no", + nya: "ny", + oci: "oc", + oji: "oj", + ori: "or", + orm: "om", + oss: "os", + pan: "pa", + pli: "pi", + pol: "pl", + por: "pt", + pus: "ps", + que: "qu", + roh: "rm", + ron: "ro", + run: "rn", + rus: "ru", + sag: "sg", + san: "sa", + sin: "si", + slk: "sk", + slv: "sl", + sme: "se", + smo: "sm", + sna: "sn", + snd: "sd", + som: "so", + sot: "st", + spa: "es", + srd: "sc", + srp: "sr", + ssw: "ss", + sun: "su", + swa: "sw", + swe: "sv", + tah: "ty", + tam: "ta", + tat: "tt", + tel: "te", + tgk: "tg", + tgl: "tl", + tha: "th", + tir: "ti", + ton: "to", + tsn: "tn", + tso: "ts", + tuk: "tk", + tur: "tr", + twi: "tw", + uig: "ug", + ukr: "uk", + urd: "ur", + uzb: "uz", + ven: "ve", + vie: "vi", + vol: "vo", + wln: "wa", + wol: "wo", + xho: "xh", + yid: "yi", + yor: "yo", + zha: "za", + zul: "zu", +};