From a2b689e69a24173f2d8bcb0a0557bd706757a68a Mon Sep 17 00:00:00 2001 From: Joost De Cock Date: Wed, 5 Jul 2023 20:58:30 +0200 Subject: [PATCH] feat(org): Added translation status page --- config/dependencies.yaml | 2 + sites/org/components/crowdin/status.mjs | 103 +++++++++++++++++++++ sites/org/hooks/use-navigation.mjs | 5 + sites/org/package.json | 2 + sites/org/pages/translation/index.mjs | 102 ++++++++++++++++++++ sites/org/site.config.mjs | 5 + sites/shared/components/wrappers/chart.mjs | 19 ++++ yarn.lock | 33 +++++++ 8 files changed, 271 insertions(+) create mode 100644 sites/org/components/crowdin/status.mjs create mode 100644 sites/org/pages/translation/index.mjs create mode 100644 sites/shared/components/wrappers/chart.mjs diff --git a/config/dependencies.yaml b/config/dependencies.yaml index 839ca819aa1..c5baaa57a70 100644 --- a/config/dependencies.yaml +++ b/config/dependencies.yaml @@ -319,6 +319,8 @@ org: 'algoliasearch': *algoliasearch 'react-copy-to-clipboard': 5.1.0 'daisyui': *daisyui + 'echarts': 5.4.2 + 'echarts-for-react': 3.0.2 'jotai': &jotai '2.2.1' 'jotai-location': &jotai-location '0.5.1' 'lodash.get': *_get diff --git a/sites/org/components/crowdin/status.mjs b/sites/org/components/crowdin/status.mjs new file mode 100644 index 00000000000..155fd2a8add --- /dev/null +++ b/sites/org/components/crowdin/status.mjs @@ -0,0 +1,103 @@ +import { useState, useEffect } from 'react' +import { siteConfig } from 'site/site.config.mjs' +import { Spinner } from 'shared/components/spinner.mjs' +import { ChartWrapper } from 'shared/components/wrappers/chart.mjs' +import orderBy from 'lodash.orderby' + +/* + * This method load the translation status from the Crowdin API + */ +const loadTranslationStatus = async (setter) => { + let response + try { + response = await fetch( + `https://api.crowdin.com/api/v2/projects/${siteConfig.crowdin.projectId}/languages/progress`, + { headers: { Authorization: `Bearer ${siteConfig.crowdin.token}` } } + ) + } catch (err) { + console.log(err) + setter(err) + } + if (response) { + const data = await response.json() + setter(data) + } +} + +const Status = ({ done, approved, language }) => { + const option = { + series: [ + { + name: 'Translation Status', + type: 'pie', + radius: ['40%', '70%'], + label: { + show: false, + }, + emphasis: { + disabled: true, + }, + data: [ + { + value: approved, + name: 'Translated & Approved', + itemStyle: { + color: 'currentColor', + opacity: 1, + }, + }, + { + value: done, + name: 'Translated & Approved', + itemStyle: { + color: 'currentColor', + opacity: 0.7, + }, + }, + { + value: 100 - (done + approved), + name: 'Untranslated', + itemStyle: { + color: 'currentColor', + opacity: 0.3, + }, + }, + ], + }, + ], + } + + return +} + +export const TranslationStatus = () => { + const [status, setStatus] = useState(false) + + useEffect(() => { + if (!status) loadTranslationStatus(setStatus) + }, [status]) + + return status ? ( + <> +
+ {status.data && + orderBy(status.data, ['data.approvalProgress'], ['desc']).map((entry) => ( +
+
+ {entry.data.languageId.indexOf('-') === -1 + ? entry.data.languageId.toUpperCase() + : entry.data.languageId.split('-')[0].toUpperCase()} + : {entry.data.approvalProgress}% +
+ +
+ ))} +
+ + ) : ( + + ) +} diff --git a/sites/org/hooks/use-navigation.mjs b/sites/org/hooks/use-navigation.mjs index ce13e82e9a5..98570460bd8 100644 --- a/sites/org/hooks/use-navigation.mjs +++ b/sites/org/hooks/use-navigation.mjs @@ -89,6 +89,11 @@ const sitePages = (t = false, control = 99) => { s: 'profile', h: 1, }, + translation: { + t: t('translation'), + s: 'translation', + h: 1, + }, sitemap: { t: t('sitemap'), s: 'sitemap', diff --git a/sites/org/package.json b/sites/org/package.json index 5be14a9f9ff..f6d912addca 100644 --- a/sites/org/package.json +++ b/sites/org/package.json @@ -39,6 +39,8 @@ "algoliasearch": "4.18.0", "react-copy-to-clipboard": "5.1.0", "daisyui": "3.1.7", + "echarts": "5.4.2", + "echarts-for-react": "3.0.2", "jotai": "2.2.1", "jotai-location": "0.5.1", "lodash.get": "4.4.2", diff --git a/sites/org/pages/translation/index.mjs b/sites/org/pages/translation/index.mjs new file mode 100644 index 00000000000..da4f0f6df8a --- /dev/null +++ b/sites/org/pages/translation/index.mjs @@ -0,0 +1,102 @@ +// Dependencies +import { serverSideTranslations } from 'next-i18next/serverSideTranslations' +// Components +import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' +import { BareLayout as Layout } from 'site/components/layouts/bare.mjs' +import { TranslationStatus } from 'site/components/crowdin/status.mjs' +import { Popout } from 'shared/components/popout.mjs' +import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs' +import { WebLink } from 'shared/components/web-link.mjs' + +// Translation namespaces used on this page +const namespaces = [...new Set(pageNs)] + +// FIXME: This page (ironically) lacks translation +// +const TranslationPage = ({ page }) => ( + +
+ +

Translation

+

+ Thanks to the translation volunteers in our community FreeSewing is proudly multilingual. +

+ +

Get involved

+

+ Translation is a team effort, and getting involved is not hard at all. Refer to{' '} + for + all details. +

+ +

Translation Status

+ + Legend +
    +
  • + + Translated & Approved +
  • +
  • + + Translated but not (yet) approved +
  • +
  • + + Not translated (yet) +
  • +
+ +

Supported Languages

+

We currently support the following five languages:

+
    +
  • + English{' '} + + (This is our source language and the working language of the FreeSewing project) + +
  • +
  • + Dutch +
  • +
  • + German +
  • +
  • + French +
  • +
  • + Spanish +
  • +
+

In addition, comminity members have started initiatives to add the following langauges:

+
    +
  • + Ukranian +
  • +
+ +
Looking to add a language?
+

+ We would love to make FreeSewing available in more langauges. +
+ If you are interested in starting a new translation effort, please reach out. +

+
+
+
+) + +export default TranslationPage + +export async function getStaticProps({ locale }) { + return { + props: { + ...(await serverSideTranslations(locale, namespaces)), + page: { + locale, + path: ['translation'], + }, + }, + } +} diff --git a/sites/org/site.config.mjs b/sites/org/site.config.mjs index c22d5ea9f58..64873abee86 100644 --- a/sites/org/site.config.mjs +++ b/sites/org/site.config.mjs @@ -7,11 +7,16 @@ export const siteConfig = { bugsnag: { key: '1b3a900d6ebbfd071975e39b534e1ff5', }, + crowdin: { + projectId: 356411, + token: '77cf8abfabef66e1275cd4ddfe0c857d45db5e51e8349877dc50a7a740d28fb573e8a4543eca616b', // Translation status (Read-only) + }, sanity: { project: process.env.SANITY_PROJECT || 'hl5bw8cj', dataset: 'site-content', apiVersion: '2023-06-17', }, languages: ['en', 'es', 'de', 'fr', 'nl'], + languagesWip: ['uk'], site: 'FreeSewing.org', } diff --git a/sites/shared/components/wrappers/chart.mjs b/sites/shared/components/wrappers/chart.mjs new file mode 100644 index 00000000000..e45c6b3618d --- /dev/null +++ b/sites/shared/components/wrappers/chart.mjs @@ -0,0 +1,19 @@ +import { useState } from 'react' +import * as echarts from 'echarts' +import ReactECharts from 'echarts-for-react' +import { Popout } from 'shared/components/popout.mjs' + +echarts.registerTheme('light', { + backgroundColor: 'transparent', +}) +echarts.registerTheme('dark', { + backgroundColor: 'transparent', +}) + +export const ChartWrapper = ({ option = false, theme = 'light', h = 400 }) => { + return option ? ( + + ) : ( + Loading chart... + ) +} diff --git a/yarn.lock b/yarn.lock index 7c5b31134eb..0f24c7eb4d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7894,6 +7894,22 @@ ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer "^5.0.1" +echarts-for-react@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/echarts-for-react/-/echarts-for-react-3.0.2.tgz#ac5859157048a1066d4553e34b328abb24f2b7c1" + integrity sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA== + dependencies: + fast-deep-equal "^3.1.3" + size-sensor "^1.0.1" + +echarts@^5.4.2: + version "5.4.2" + resolved "https://registry.yarnpkg.com/echarts/-/echarts-5.4.2.tgz#9f38781c9c6ae323e896956178f6956952c77a48" + integrity sha512-2W3vw3oI2tWJdyAz+b8DuWS0nfXtSDqlDmqgin/lfzbkB01cuMEN66KWBlmur3YMp5nEDEEt5s23pllnAzB4EA== + dependencies: + tslib "2.3.0" + zrender "5.4.3" + editorconfig@^0.15.3: version "0.15.3" resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" @@ -18126,6 +18142,11 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +size-sensor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/size-sensor/-/size-sensor-1.0.1.tgz#f84e46206d3e259faff1d548e4b3beca93219dbb" + integrity sha512-QTy7MnuugCFXIedXRpUSk9gUnyNiaxIdxGfUjr8xxXOqIB3QvBUYP9+b51oCg2C4dnhaeNk/h57TxjbvoJrJUA== + slash@3.0.0, slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -19392,6 +19413,11 @@ tsconfig-paths@^4.1.2: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -20723,6 +20749,13 @@ zod@3.21.4: resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw== +zrender@5.4.3: + version "5.4.3" + resolved "https://registry.yarnpkg.com/zrender/-/zrender-5.4.3.tgz#41ffaf835f3a3210224abd9d6964b48ff01e79f5" + integrity sha512-DRUM4ZLnoaT0PBVvGBDO9oWIDBKFdAVieNWxWwK0niYzJCMwGchRk21/hsE+RKkIveH3XHCyvXcJDkgLVvfizQ== + dependencies: + tslib "2.3.0" + zwitch@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"