From 7b801857a591233b46be25615f7005b57328d671 Mon Sep 17 00:00:00 2001 From: Filip Czaplicki Date: Fri, 23 Feb 2024 23:55:24 +0100 Subject: [PATCH] Vite: MultiPageApp for languages --- .github/workflows/ci_test.yml | 1 - .github/workflows/deploy_development.yml | 16 +----- .github/workflows/deploy_production.yml | 5 +- .gitignore | 2 + README.md | 1 - index.html | 2 +- scripts/build_every_lang.sh | 13 ----- src/i18n.ts | 4 +- vite.config.js | 65 +++++++++++++++++------- 9 files changed, 56 insertions(+), 53 deletions(-) delete mode 100755 scripts/build_every_lang.sh diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index df71563..96864a4 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -32,5 +32,4 @@ jobs: - name: Build run: bun run build env: - VITE_DEFAULT_LANG: en VITE_BACKEND_API_URL: "https://dev.openaedmap.org" diff --git a/.github/workflows/deploy_development.yml b/.github/workflows/deploy_development.yml index 8524a57..7384780 100644 --- a/.github/workflows/deploy_development.yml +++ b/.github/workflows/deploy_development.yml @@ -34,7 +34,6 @@ jobs: - name: Build app (main) env: VITE_ENV: development - VITE_DEFAULT_LANG: en VITE_OSM_API_URL: "https://master.apis.dev.openstreetmap.org" VITE_OSM_OAUTH2_CLIENT_ID: ${{ secrets.REACT_APP_OSM_OAUTH2_CLIENT_ID }} VITE_BACKEND_API_URL: "https://dev.openaedmap.org" @@ -47,17 +46,6 @@ jobs: User-agent: * Disallow: / EOF - - name: Copy main build to server + - name: Copy result to server run: | - rsync -rp -e 'ssh -p ${{ secrets.SSH_HOST_NEW_PORT }}' build/* ${{ secrets.SSH_USER_NEW }}@${{ secrets.SSH_HOST_NEW_IP }}:~/dev-static/ - - name: Build app lang versions - env: - VITE_ENV: development - VITE_OSM_API_URL: "https://master.apis.dev.openstreetmap.org" - VITE_OSM_OAUTH2_CLIENT_ID: ${{ secrets.REACT_APP_OSM_OAUTH2_CLIENT_ID }} - VITE_BACKEND_API_URL: "https://dev.openaedmap.org" - VITE_SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: ./scripts/build_every_lang.sh - - name: Copy lang version builds to server - run: | - rsync -rp --delete -e 'ssh -p ${{ secrets.SSH_HOST_NEW_PORT }}' build/* ${{ secrets.SSH_USER_NEW }}@${{ secrets.SSH_HOST_NEW_IP }}:~/dev-static/ + rsync -rp --delete -e 'ssh -p ${{ secrets.SSH_HOST_NEW_PORT }}' build/* ${{ secrets.SSH_USER_NEW }}@${{ secrets.SSH_HOST_NEW_IP }}:~/dev-static/ \ No newline at end of file diff --git a/.github/workflows/deploy_production.yml b/.github/workflows/deploy_production.yml index 6e68ab0..4d008c7 100644 --- a/.github/workflows/deploy_production.yml +++ b/.github/workflows/deploy_production.yml @@ -34,13 +34,12 @@ jobs: - name: Build app env: VITE_ENV: production - VITE_DEFAULT_LANG: en VITE_OSM_AUTH_URL: "https://www.openstreetmap.org" VITE_OSM_API_URL: "https://api.openstreetmap.org" VITE_OSM_OAUTH2_CLIENT_ID: ${{ secrets.REACT_APP_OSM_OAUTH2_CLIENT_ID }} VITE_BACKEND_API_URL: "https://openaedmap.org" VITE_SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: bun run build && ./scripts/build_every_lang.sh - - name: Run deploy script on host + run: bun run build + - name: Copy result to server run: | rsync -rp --delete -e 'ssh -p ${{ secrets.SSH_HOST_NEW_PORT }}' build/* ${{ secrets.SSH_USER_NEW }}@${{ secrets.SSH_HOST_NEW_IP }}:~/main-static/ diff --git a/.gitignore b/.gitignore index 4a68f04..0943da1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +langs + # Logs logs *.log diff --git a/README.md b/README.md index e417a62..24f2a7c 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,6 @@ Second way is if you are using VS Code and have Docker installed you can use dev Create .env file and put these variables there: ``` -VITE_DEFAULT_LANG=en VITE_OSM_API_URL=https://master.apis.dev.openstreetmap.org VITE_BACKEND_API_URL=https://dev.openaedmap.org VITE_OSM_OAUTH2_CLIENT_ID=xXaPFXSLizLHuZzoLI1eebHncPdDdVH7nA917S9uFUo diff --git a/index.html b/index.html index 81a2f92..be25819 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + OpenAEDMap - Map of Defibrillators diff --git a/scripts/build_every_lang.sh b/scripts/build_every_lang.sh deleted file mode 100755 index 135a214..0000000 --- a/scripts/build_every_lang.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -eu - -for lang in public/locales/*; do - lang=$(basename "$lang") - if [[ $lang = "debug" ]]; then - continue - fi - export VITE_DEFAULT_LANG=$lang - export VITE_BASE_URL="/$lang/" - echo "Generating $lang" - bun run build -- --outDir "build/$lang" --base "/$lang" -done diff --git a/src/i18n.ts b/src/i18n.ts index 62340e2..3a54f27 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -10,7 +10,6 @@ if (!isProduction) { languages.debug = { nativeName: "--debug--" }; } const languagesIsoCodes = Object.keys(languages); -const defaultLanguage = import.meta.env.VITE_DEFAULT_LANG ?? "en"; i18n // i18next-http-backend @@ -57,7 +56,8 @@ function useLanguage(): string { const { i18n: { resolvedLanguage }, } = useTranslation(); - return resolvedLanguage ?? defaultLanguage; + const htmlLanguage = document.getElementsByTagName("html")[0].lang; + return resolvedLanguage ?? htmlLanguage ?? "en"; } export default i18n; diff --git a/vite.config.js b/vite.config.js index 5987b30..61a67ed 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,4 +1,6 @@ +import * as fs from "fs"; import path from "path"; +import { resolve } from "path"; import { sentryVitePlugin } from "@sentry/vite-plugin"; import react from "@vitejs/plugin-react"; import { defineConfig, loadEnv } from "vite"; @@ -14,26 +16,28 @@ const getTranslatedStrings = async (languageCode) => { const htmlPlugin = async (env) => { const translationsEn = await getTranslatedStrings("en"); - const translationsTarget = await getTranslatedStrings( - env.VITE_DEFAULT_LANG ?? "en", - ).catch((e) => console.error(e)); - const { meta_title, meta_description, website_title } = { - ...translationsEn, - ...translationsTarget, - }; - const baseUrl = env.VITE_BASE_URL ?? ""; - const canonicalLinks = ``; - const alternateLinks = Object.keys(languages) - .map( - (lang) => - `\t`, - ) - .join("\n"); - const defaultAlternateLink = `\t`; - const seoLinks = `${canonicalLinks}\n${alternateLinks}\n${defaultAlternateLink}`; return { name: "html-transform", - transformIndexHtml(html) { + async transformIndexHtml(html) { + const currentLang = html.match(//)[1]; + const translationsTarget = await getTranslatedStrings(currentLang).catch( + (e) => console.error(e), + ); + const { meta_title, meta_description, website_title } = { + ...translationsEn, + ...translationsTarget, + }; + const baseUrl = currentLang === "en" ? "" : `/${currentLang}/`; + const canonicalLinks = ``; + const alternateLinks = Object.keys(languages) + .filter((lang) => lang !== currentLang) + .map( + (lang) => + `\t`, + ) + .join("\n"); + const defaultAlternateLink = `\t`; + const seoLinks = `${canonicalLinks}\n${alternateLinks}\n${defaultAlternateLink}`; return html .replace(/(.*?)<\/title>/, `<title>${website_title}`) .replace( @@ -49,6 +53,23 @@ const htmlPlugin = async (env) => { seoLinks, ); }, + buildStart(options) { + const content = fs.readFileSync("index.html", "utf-8"); + for (const lang of Object.keys(languages)) { + fs.mkdirSync(`langs/${lang}`, { recursive: true }); + const contentLang = content.replace( + //, + ``, + ); + fs.writeFileSync(`langs/${lang}/index.html`, contentLang); + } + }, + writeBundle() { + for (const lang of Object.keys(languages)) { + fs.mkdirSync(`build/${lang}`, { recursive: true }); + fs.renameSync(`build/langs/${lang}`, `build/${lang}`); + } + }, }; }; @@ -85,6 +106,11 @@ export default defineConfig(({ mode }) => { ); } + const rollupInputs = { main: resolve(__dirname, "index.html") }; + for (const lang of Object.keys(languages)) { + rollupInputs[lang] = resolve(__dirname, `langs/${lang}/index.html`); + } + return { // https://github.com/vitejs/vite/issues/1973#issuecomment-787571499 define: { @@ -100,6 +126,9 @@ export default defineConfig(({ mode }) => { outDir: "build", chunkSizeWarningLimit: 1900, sourcemap: true, + rollupOptions: { + input: rollupInputs, + }, }, plugins: plugins, server: {