diff --git a/commafeed-client/package.json b/commafeed-client/package.json index 2a36e23e..e26a5fc4 100644 --- a/commafeed-client/package.json +++ b/commafeed-client/package.json @@ -1,84 +1,81 @@ { - "name": "commafeed-client", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite --host", - "dev:typescript": "tsc --watch", - "build": "npm run i18n:compile && tsc && vite build", - "preview": "vite preview", - "test": "vitest", - "test:ci": "vitest run", - "eslint": "eslint --ext=.js,.jsx,.ts,.tsx src", - "i18n": "npm run i18n:extract && npm run i18n:compile", - "i18n:extract": "lingui extract --clean", - "i18n:compile": "lingui compile --typescript", - "postinstall": "npm run i18n:compile" - }, - "dependencies": { - "@emotion/react": "^11.11.0", - "@fontsource/open-sans": "^4.5.14", - "@lingui/core": "^4.0.0", - "@lingui/macro": "^4.0.0", - "@lingui/react": "^4.0.0", - "@mantine/core": "^6.0.10", - "@mantine/form": "^6.0.10", - "@mantine/hooks": "^6.0.10", - "@mantine/modals": "^6.0.10", - "@mantine/notifications": "^6.0.10", - "@mantine/spotlight": "^6.0.10", - "@mantine/styles": "^6.0.10", - "@reduxjs/toolkit": "^1.9.5", - "axios": "^1.4.0", - "dayjs": "^1.11.7", - "interweave": "^13.1.0", - "mousetrap": "^1.6.5", - "react": "^18.2.0", - "react-async-hook": "^4.0.0", - "react-contexify": "^6.0.0", - "react-dom": "^18.2.0", - "react-ga4": "^2.1.0", - "react-icons": "^4.8.0", - "react-infinite-scroller": "^1.2.6", - "react-redux": "^8.0.5", - "react-router-dom": "^6.11.1", - "react-swipeable": "^7.0.0", - "swagger-ui-react": "^4.18.3", - "throttle-debounce": "^5.0.0", - "tinycon": "^0.6.8", - "use-local-storage": "^3.0.0", - "websocket-heartbeat-js": "^1.1.2" - }, - "devDependencies": { - "@lingui/cli": "^4.0.0", - "@lingui/vite-plugin": "^4.0.0", - "@types/eslint": "^8.37.0", - "@types/mousetrap": "^1.6.11", - "@types/react": "^18.2.6", - "@types/react-dom": "^18.2.4", - "@types/react-infinite-scroller": "^1.2.3", - "@types/swagger-ui-react": "^4.18.0", - "@types/throttle-debounce": "^5.0.0", - "@types/tinycon": "^0.6.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.2", - "@vitejs/plugin-react": "^4.0.0", - "babel-plugin-macros": "^3.1.0", - "eslint": "^8.40.0", - "eslint-config-airbnb": "^19.0.4", - "eslint-config-airbnb-typescript": "^17.0.0", - "eslint-config-prettier": "^8.8.0", - "eslint-config-react-app": "^7.0.1", - "eslint-plugin-hooks": "^0.4.3", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", - "rollup-plugin-visualizer": "^5.9.0", - "typescript": "^5.0.4", - "vite": "^4.3.5", - "vite-plugin-eslint": "^1.8.1", - "vite-tsconfig-paths": "^4.2.0", - "vitest": "^0.31.0", - "vitest-mock-extended": "^1.1.3" - } + "name": "commafeed-client", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite --host", + "dev:typescript": "tsc --watch", + "build": "tsc && vite build", + "preview": "vite preview", + "test": "vitest", + "test:ci": "vitest run", + "eslint": "eslint --ext=.js,.jsx,.ts,.tsx src", + "i18n:extract": "lingui extract --clean" + }, + "dependencies": { + "@emotion/react": "^11.11.0", + "@fontsource/open-sans": "^4.5.14", + "@lingui/core": "^4.0.0", + "@lingui/macro": "^4.0.0", + "@lingui/react": "^4.0.0", + "@mantine/core": "^6.0.10", + "@mantine/form": "^6.0.10", + "@mantine/hooks": "^6.0.10", + "@mantine/modals": "^6.0.10", + "@mantine/notifications": "^6.0.10", + "@mantine/spotlight": "^6.0.10", + "@mantine/styles": "^6.0.10", + "@reduxjs/toolkit": "^1.9.5", + "axios": "^1.4.0", + "dayjs": "^1.11.7", + "interweave": "^13.1.0", + "mousetrap": "^1.6.5", + "react": "^18.2.0", + "react-async-hook": "^4.0.0", + "react-contexify": "^6.0.0", + "react-dom": "^18.2.0", + "react-ga4": "^2.1.0", + "react-icons": "^4.8.0", + "react-infinite-scroller": "^1.2.6", + "react-redux": "^8.0.5", + "react-router-dom": "^6.11.1", + "react-swipeable": "^7.0.0", + "swagger-ui-react": "^4.18.3", + "throttle-debounce": "^5.0.0", + "tinycon": "^0.6.8", + "use-local-storage": "^3.0.0", + "websocket-heartbeat-js": "^1.1.2" + }, + "devDependencies": { + "@lingui/cli": "^4.0.0", + "@lingui/vite-plugin": "^4.0.0", + "@types/eslint": "^8.37.0", + "@types/mousetrap": "^1.6.11", + "@types/react": "^18.2.6", + "@types/react-dom": "^18.2.4", + "@types/react-infinite-scroller": "^1.2.3", + "@types/swagger-ui-react": "^4.18.0", + "@types/throttle-debounce": "^5.0.0", + "@types/tinycon": "^0.6.3", + "@typescript-eslint/eslint-plugin": "^5.59.2", + "@typescript-eslint/parser": "^5.59.2", + "@vitejs/plugin-react": "^4.0.0", + "babel-plugin-macros": "^3.1.0", + "eslint": "^8.40.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-typescript": "^17.0.0", + "eslint-config-prettier": "^8.8.0", + "eslint-config-react-app": "^7.0.1", + "eslint-plugin-hooks": "^0.4.3", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "rollup-plugin-visualizer": "^5.9.0", + "typescript": "^5.0.4", + "vite": "^4.3.5", + "vite-plugin-eslint": "^1.8.1", + "vite-tsconfig-paths": "^4.2.0", + "vitest": "^0.31.0", + "vitest-mock-extended": "^1.1.3" + } } diff --git a/commafeed-client/src/i18n.ts b/commafeed-client/src/i18n.ts index 0893d8c4..5114769b 100644 --- a/commafeed-client/src/i18n.ts +++ b/commafeed-client/src/i18n.ts @@ -1,113 +1,59 @@ -import { i18n, Messages } from "@lingui/core" +import { i18n } from "@lingui/core" import { useAppSelector } from "app/store" import dayjs from "dayjs" -import "dayjs/locale/ar" -import "dayjs/locale/ca" -import "dayjs/locale/cs" -import "dayjs/locale/cy" -import "dayjs/locale/da" -import "dayjs/locale/de" -import "dayjs/locale/en" -import "dayjs/locale/es" -import "dayjs/locale/fa" -import "dayjs/locale/fi" -import "dayjs/locale/fr" -import "dayjs/locale/gl" -import "dayjs/locale/hu" -import "dayjs/locale/id" -import "dayjs/locale/it" -import "dayjs/locale/ja" -import "dayjs/locale/ko" -import "dayjs/locale/ms" -import "dayjs/locale/nb" -import "dayjs/locale/nl" -import "dayjs/locale/nn" -import "dayjs/locale/pl" -import "dayjs/locale/pt" -import "dayjs/locale/ru" -import "dayjs/locale/sk" -import "dayjs/locale/sv" -import "dayjs/locale/tr" -import "dayjs/locale/zh" - import { useEffect } from "react" -import { messages as arMessages } from "./locales/ar/messages" -import { messages as caMessages } from "./locales/ca/messages" -import { messages as csMessages } from "./locales/cs/messages" -import { messages as cyMessages } from "./locales/cy/messages" -import { messages as daMessages } from "./locales/da/messages" -import { messages as deMessages } from "./locales/de/messages" -import { messages as enMessages } from "./locales/en/messages" -import { messages as esMessages } from "./locales/es/messages" -import { messages as faMessages } from "./locales/fa/messages" -import { messages as fiMessages } from "./locales/fi/messages" -import { messages as frMessages } from "./locales/fr/messages" -import { messages as glMessages } from "./locales/gl/messages" -import { messages as huMessages } from "./locales/hu/messages" -import { messages as idMessages } from "./locales/id/messages" -import { messages as itMessages } from "./locales/it/messages" -import { messages as jaMessages } from "./locales/ja/messages" -import { messages as koMessages } from "./locales/ko/messages" -import { messages as msMessages } from "./locales/ms/messages" -import { messages as nbMessages } from "./locales/nb/messages" -import { messages as nlMessages } from "./locales/nl/messages" -import { messages as nnMessages } from "./locales/nn/messages" -import { messages as plMessages } from "./locales/pl/messages" -import { messages as ptMessages } from "./locales/pt/messages" -import { messages as ruMessages } from "./locales/ru/messages" -import { messages as skMessages } from "./locales/sk/messages" -import { messages as svMessages } from "./locales/sv/messages" -import { messages as trMessages } from "./locales/tr/messages" -import { messages as zhMessages } from "./locales/zh/messages" interface Locale { key: string label: string - messages: Messages + daysjsImportFn: () => Promise } // add an object to the array to add a new locale // don't forget to also add it to the 'locales' array in .linguirc export const locales: Locale[] = [ - { key: "ar", messages: arMessages, label: "العربية" }, - { key: "ca", messages: caMessages, label: "Català" }, - { key: "cs", messages: csMessages, label: "Čeština" }, - { key: "cy", messages: cyMessages, label: "Cymraeg" }, - { key: "da", messages: daMessages, label: "Danish" }, - { key: "de", messages: deMessages, label: "Deutsch" }, - { key: "en", messages: enMessages, label: "English" }, - { key: "es", messages: esMessages, label: "Español" }, - { key: "fa", messages: faMessages, label: "فارسی" }, - { key: "fi", messages: fiMessages, label: "Suomi" }, - { key: "fr", messages: frMessages, label: "Français" }, - { key: "gl", messages: glMessages, label: "Galician" }, - { key: "hu", messages: huMessages, label: "Magyar" }, - { key: "id", messages: idMessages, label: "Indonesian" }, - { key: "it", messages: itMessages, label: "Italiano" }, - { key: "ja", messages: jaMessages, label: "日本語" }, - { key: "ko", messages: koMessages, label: "한국어" }, - { key: "ms", messages: msMessages, label: "Bahasa Malaysian" }, - { key: "nb", messages: nbMessages, label: "Norsk (bokmål)" }, - { key: "nl", messages: nlMessages, label: "Nederlands" }, - { key: "nn", messages: nnMessages, label: "Norsk (nynorsk)" }, - { key: "pl", messages: plMessages, label: "Polski" }, - { key: "pt", messages: ptMessages, label: "Português" }, - { key: "ru", messages: ruMessages, label: "Русский" }, - { key: "sk", messages: skMessages, label: "Slovenčina" }, - { key: "sv", messages: svMessages, label: "Svenska" }, - { key: "tr", messages: trMessages, label: "Türkçe" }, - { key: "zh", messages: zhMessages, label: "简体中文" }, + { key: "ar", label: "العربية", daysjsImportFn: () => import("dayjs/locale/ar") }, + { key: "ca", label: "Català", daysjsImportFn: () => import("dayjs/locale/ca") }, + { key: "cs", label: "Čeština", daysjsImportFn: () => import("dayjs/locale/cs") }, + { key: "cy", label: "Cymraeg", daysjsImportFn: () => import("dayjs/locale/cy") }, + { key: "da", label: "Danish", daysjsImportFn: () => import("dayjs/locale/da") }, + { key: "de", label: "Deutsch", daysjsImportFn: () => import("dayjs/locale/de") }, + { key: "en", label: "English", daysjsImportFn: () => import("dayjs/locale/en") }, + { key: "es", label: "Español", daysjsImportFn: () => import("dayjs/locale/es") }, + { key: "fa", label: "فارسی", daysjsImportFn: () => import("dayjs/locale/fa") }, + { key: "fi", label: "Suomi", daysjsImportFn: () => import("dayjs/locale/fi") }, + { key: "fr", label: "Français", daysjsImportFn: () => import("dayjs/locale/fr") }, + { key: "gl", label: "Galician", daysjsImportFn: () => import("dayjs/locale/gl") }, + { key: "hu", label: "Magyar", daysjsImportFn: () => import("dayjs/locale/hu") }, + { key: "id", label: "Indonesian", daysjsImportFn: () => import("dayjs/locale/id") }, + { key: "it", label: "Italiano", daysjsImportFn: () => import("dayjs/locale/it") }, + { key: "ja", label: "日本語", daysjsImportFn: () => import("dayjs/locale/ja") }, + { key: "ko", label: "한국어", daysjsImportFn: () => import("dayjs/locale/ko") }, + { key: "ms", label: "Bahasa Malaysian", daysjsImportFn: () => import("dayjs/locale/ms") }, + { key: "nb", label: "Norsk (bokmål)", daysjsImportFn: () => import("dayjs/locale/nb") }, + { key: "nl", label: "Nederlands", daysjsImportFn: () => import("dayjs/locale/nl") }, + { key: "nn", label: "Norsk (nynorsk)", daysjsImportFn: () => import("dayjs/locale/nn") }, + { key: "pl", label: "Polski", daysjsImportFn: () => import("dayjs/locale/pl") }, + { key: "pt", label: "Português", daysjsImportFn: () => import("dayjs/locale/pt") }, + { key: "ru", label: "Русский", daysjsImportFn: () => import("dayjs/locale/ru") }, + { key: "sk", label: "Slovenčina", daysjsImportFn: () => import("dayjs/locale/sk") }, + { key: "sv", label: "Svenska", daysjsImportFn: () => import("dayjs/locale/sv") }, + { key: "tr", label: "Türkçe", daysjsImportFn: () => import("dayjs/locale/tr") }, + { key: "zh", label: "简体中文", daysjsImportFn: () => import("dayjs/locale/zh") }, ] -locales.forEach(l => { - i18n.load({ - [l.key]: l.messages, - }) -}) - function activateLocale(locale: string) { - i18n.activate(locale) - dayjs.locale(locale) + // lingui + import(`./locales/${locale}/messages.po`).then(data => { + i18n.load(locale, data.messages) + i18n.activate(locale) + }) + + // dayjs + locales + .find(l => l.key === locale) + ?.daysjsImportFn() + .then(() => dayjs.locale(locale)) } export const useI18n = () => { diff --git a/commafeed-client/vite.config.ts b/commafeed-client/vite.config.ts index fdc951e5..d3821dd2 100644 --- a/commafeed-client/vite.config.ts +++ b/commafeed-client/vite.config.ts @@ -1,3 +1,4 @@ +import { lingui } from "@lingui/vite-plugin" import react from "@vitejs/plugin-react" import { visualizer } from "rollup-plugin-visualizer" import { defineConfig } from "vite" @@ -13,6 +14,7 @@ export default defineConfig({ plugins: ["macros"], }, }), + lingui(), eslint(), tsconfigPaths(), visualizer(),