diff --git a/apps/website/index.html b/apps/website/index.html
index 798ca14f9..55cb4fa6a 100644
--- a/apps/website/index.html
+++ b/apps/website/index.html
@@ -1,5 +1,5 @@
-
+
diff --git a/apps/website/src/i18n.spec.ts b/apps/website/src/i18n.spec.ts
index eab06ba5a..fcc8d790a 100644
--- a/apps/website/src/i18n.spec.ts
+++ b/apps/website/src/i18n.spec.ts
@@ -19,6 +19,7 @@ describe("swapLocale", () => {
expect(swapLocaleInUrl("/ro/get-started", "ro")).toStrictEqual("/ro/get-started");
expect(swapLocaleInUrl("/en/get-started", "ro")).toStrictEqual("/ro/get-started");
expect(swapLocaleInUrl("/ro/", "en")).toStrictEqual("/en/");
+ expect(swapLocaleInUrl("/ro", "en")).toStrictEqual("/en");
});
});
diff --git a/apps/website/src/i18n.ts b/apps/website/src/i18n.ts
index 435245217..93931d936 100644
--- a/apps/website/src/i18n.ts
+++ b/apps/website/src/i18n.ts
@@ -1,9 +1,36 @@
+import i18next from "i18next";
+import { initReactI18next } from "react-i18next";
+
interface Locale {
id: string;
name: string;
rtl?: boolean;
}
+i18next.use(initReactI18next);
+const localeFiles = import.meta.glob("./translations/*/translation.json", { eager: true });
+const resources: Record>> = {};
+for (const [path, module] of Object.entries(localeFiles)) {
+ const id = path.split("/").at(-2);
+ if (!id) continue;
+
+ const translations = (module as any).default ?? module;
+ resources[id] = { translation: translations };
+}
+
+export function initTranslations(lng: string) {
+ i18next.init({
+ fallbackLng: "en",
+ lng,
+ returnEmptyString: false,
+ resources,
+ initAsync: false,
+ react: {
+ useSuspense: false
+ }
+ });
+}
+
export const LOCALES: Locale[] = [
{ id: "en", name: "English" },
{ id: "ro", name: "Română" },
@@ -35,7 +62,13 @@ export function mapLocale(locale: string) {
export function swapLocaleInUrl(url: string, newLocale: string) {
const components = url.split("/");
if (components.length === 2) {
- return `/${newLocale}${url}`;
+ const potentialLocale = components[1];
+ const correspondingLocale = LOCALES.find(l => l.id === potentialLocale);
+ if (correspondingLocale) {
+ return `/${newLocale}`;
+ } else {
+ return `/${newLocale}${url}`;
+ }
} else {
components[1] = newLocale;
return components.join("/");
diff --git a/apps/website/src/index.tsx b/apps/website/src/index.tsx
index 8cbea3d0e..5bef0fad2 100644
--- a/apps/website/src/index.tsx
+++ b/apps/website/src/index.tsx
@@ -8,11 +8,9 @@ import Footer from './components/Footer.js';
import GetStarted from './pages/GetStarted/get-started.js';
import SupportUs from './pages/SupportUs/SupportUs.js';
import { createContext } from 'preact';
-import { useLayoutEffect, useState } from 'preact/hooks';
-import { default as i18next, changeLanguage } from 'i18next';
-import { extractLocaleFromUrl, LOCALES, mapLocale } from './i18n';
-import HttpApi from 'i18next-http-backend';
-import { initReactI18next } from "react-i18next";
+import { useLayoutEffect, useRef } from 'preact/hooks';
+import { changeLanguage } from 'i18next';
+import { extractLocaleFromUrl, initTranslations, LOCALES, mapLocale } from './i18n';
export const LocaleContext = createContext('en');
@@ -42,34 +40,26 @@ export function App(props: {repoStargazersCount: number}) {
export function LocaleProvider({ children }) {
const { path } = useLocation();
- const localeId = mapLocale(extractLocaleFromUrl(path) || navigator.language);
- const [ loaded, setLoaded ] = useState(false);
+ const localeId = getLocaleId(path);
+ const loadedRef = useRef(false);
- useLayoutEffect(() => {
- i18next
- .use(HttpApi)
- .use(initReactI18next);
- i18next.init({
- lng: localeId,
- fallbackLng: "en",
- backend: {
- loadPath: "/translations/{{lng}}/{{ns}}.json",
- },
- returnEmptyString: false
- }).then(() => setLoaded(true))
-}, []);
-
- useLayoutEffect(() => {
- if (!loaded) return;
+ if (!loadedRef.current) {
+ initTranslations(localeId);
+ loadedRef.current = true;
+ } else {
changeLanguage(localeId);
+ }
+
+ // Update html lang and dir attributes
+ useLayoutEffect(() => {
const correspondingLocale = LOCALES.find(l => l.id === localeId);
document.documentElement.lang = localeId;
document.documentElement.dir = correspondingLocale?.rtl ? "rtl" : "ltr";
- }, [ loaded, localeId ]);
+ }, [localeId]);
return (
- {loaded && children}
+ {children}
);
}
@@ -78,12 +68,26 @@ if (typeof window !== 'undefined') {
hydrate(, document.getElementById('app')!);
}
+function getLocaleId(path: string) {
+ const extractedLocale = extractLocaleFromUrl(path);
+ if (extractedLocale) return mapLocale(extractedLocale);
+ if (typeof window === "undefined") return 'en';
+ return mapLocale(navigator.language);
+}
+
export async function prerender(data) {
// Fetch the stargazer count of the Trilium's GitHub repo on prerender to pass
// it to the App component for SSR.
// This ensures the GitHub API is not called on every page load in the client.
const stargazersCount = await getRepoStargazersCount();
- return await ssr();
+ const { html, links } = await ssr();
+ return {
+ html,
+ links,
+ head: {
+ lang: extractLocaleFromUrl(data.url) ?? "en"
+ }
+ }
}
diff --git a/apps/website/public/translations/ar/translation.json b/apps/website/src/translations/ar/translation.json
similarity index 100%
rename from apps/website/public/translations/ar/translation.json
rename to apps/website/src/translations/ar/translation.json
diff --git a/apps/website/public/translations/ca/translation.json b/apps/website/src/translations/ca/translation.json
similarity index 100%
rename from apps/website/public/translations/ca/translation.json
rename to apps/website/src/translations/ca/translation.json
diff --git a/apps/website/public/translations/cs/translation.json b/apps/website/src/translations/cs/translation.json
similarity index 100%
rename from apps/website/public/translations/cs/translation.json
rename to apps/website/src/translations/cs/translation.json
diff --git a/apps/website/public/translations/de/translation.json b/apps/website/src/translations/de/translation.json
similarity index 100%
rename from apps/website/public/translations/de/translation.json
rename to apps/website/src/translations/de/translation.json
diff --git a/apps/website/public/translations/el/translation.json b/apps/website/src/translations/el/translation.json
similarity index 100%
rename from apps/website/public/translations/el/translation.json
rename to apps/website/src/translations/el/translation.json
diff --git a/apps/website/public/translations/en/translation.json b/apps/website/src/translations/en/translation.json
similarity index 100%
rename from apps/website/public/translations/en/translation.json
rename to apps/website/src/translations/en/translation.json
diff --git a/apps/website/public/translations/es/translation.json b/apps/website/src/translations/es/translation.json
similarity index 100%
rename from apps/website/public/translations/es/translation.json
rename to apps/website/src/translations/es/translation.json
diff --git a/apps/website/public/translations/fa/translation.json b/apps/website/src/translations/fa/translation.json
similarity index 100%
rename from apps/website/public/translations/fa/translation.json
rename to apps/website/src/translations/fa/translation.json
diff --git a/apps/website/public/translations/fi/translation.json b/apps/website/src/translations/fi/translation.json
similarity index 100%
rename from apps/website/public/translations/fi/translation.json
rename to apps/website/src/translations/fi/translation.json
diff --git a/apps/website/public/translations/fr/translation.json b/apps/website/src/translations/fr/translation.json
similarity index 100%
rename from apps/website/public/translations/fr/translation.json
rename to apps/website/src/translations/fr/translation.json
diff --git a/apps/website/public/translations/hr/translation.json b/apps/website/src/translations/hr/translation.json
similarity index 100%
rename from apps/website/public/translations/hr/translation.json
rename to apps/website/src/translations/hr/translation.json
diff --git a/apps/website/public/translations/hu/translation.json b/apps/website/src/translations/hu/translation.json
similarity index 100%
rename from apps/website/public/translations/hu/translation.json
rename to apps/website/src/translations/hu/translation.json
diff --git a/apps/website/public/translations/id/translation.json b/apps/website/src/translations/id/translation.json
similarity index 100%
rename from apps/website/public/translations/id/translation.json
rename to apps/website/src/translations/id/translation.json
diff --git a/apps/website/public/translations/it/translation.json b/apps/website/src/translations/it/translation.json
similarity index 100%
rename from apps/website/public/translations/it/translation.json
rename to apps/website/src/translations/it/translation.json
diff --git a/apps/website/public/translations/ja/translation.json b/apps/website/src/translations/ja/translation.json
similarity index 100%
rename from apps/website/public/translations/ja/translation.json
rename to apps/website/src/translations/ja/translation.json
diff --git a/apps/website/public/translations/ko/translation.json b/apps/website/src/translations/ko/translation.json
similarity index 100%
rename from apps/website/public/translations/ko/translation.json
rename to apps/website/src/translations/ko/translation.json
diff --git a/apps/website/public/translations/md/translation.json b/apps/website/src/translations/md/translation.json
similarity index 100%
rename from apps/website/public/translations/md/translation.json
rename to apps/website/src/translations/md/translation.json
diff --git a/apps/website/public/translations/nb-NO/translation.json b/apps/website/src/translations/nb-NO/translation.json
similarity index 100%
rename from apps/website/public/translations/nb-NO/translation.json
rename to apps/website/src/translations/nb-NO/translation.json
diff --git a/apps/website/public/translations/nl/translation.json b/apps/website/src/translations/nl/translation.json
similarity index 100%
rename from apps/website/public/translations/nl/translation.json
rename to apps/website/src/translations/nl/translation.json
diff --git a/apps/website/public/translations/pl/translation.json b/apps/website/src/translations/pl/translation.json
similarity index 100%
rename from apps/website/public/translations/pl/translation.json
rename to apps/website/src/translations/pl/translation.json
diff --git a/apps/website/public/translations/pt-BR/translation.json b/apps/website/src/translations/pt-BR/translation.json
similarity index 100%
rename from apps/website/public/translations/pt-BR/translation.json
rename to apps/website/src/translations/pt-BR/translation.json
diff --git a/apps/website/public/translations/pt/translation.json b/apps/website/src/translations/pt/translation.json
similarity index 100%
rename from apps/website/public/translations/pt/translation.json
rename to apps/website/src/translations/pt/translation.json
diff --git a/apps/website/public/translations/ro/translation.json b/apps/website/src/translations/ro/translation.json
similarity index 100%
rename from apps/website/public/translations/ro/translation.json
rename to apps/website/src/translations/ro/translation.json
diff --git a/apps/website/public/translations/ru/translation.json b/apps/website/src/translations/ru/translation.json
similarity index 100%
rename from apps/website/public/translations/ru/translation.json
rename to apps/website/src/translations/ru/translation.json
diff --git a/apps/website/public/translations/sl/translation.json b/apps/website/src/translations/sl/translation.json
similarity index 100%
rename from apps/website/public/translations/sl/translation.json
rename to apps/website/src/translations/sl/translation.json
diff --git a/apps/website/public/translations/sr/translation.json b/apps/website/src/translations/sr/translation.json
similarity index 100%
rename from apps/website/public/translations/sr/translation.json
rename to apps/website/src/translations/sr/translation.json
diff --git a/apps/website/public/translations/sv/translation.json b/apps/website/src/translations/sv/translation.json
similarity index 100%
rename from apps/website/public/translations/sv/translation.json
rename to apps/website/src/translations/sv/translation.json
diff --git a/apps/website/public/translations/tr/translation.json b/apps/website/src/translations/tr/translation.json
similarity index 100%
rename from apps/website/public/translations/tr/translation.json
rename to apps/website/src/translations/tr/translation.json
diff --git a/apps/website/public/translations/uk/translation.json b/apps/website/src/translations/uk/translation.json
similarity index 100%
rename from apps/website/public/translations/uk/translation.json
rename to apps/website/src/translations/uk/translation.json
diff --git a/apps/website/public/translations/vi/translation.json b/apps/website/src/translations/vi/translation.json
similarity index 100%
rename from apps/website/public/translations/vi/translation.json
rename to apps/website/src/translations/vi/translation.json
diff --git a/apps/website/public/translations/zh-Hans/translation.json b/apps/website/src/translations/zh-Hans/translation.json
similarity index 100%
rename from apps/website/public/translations/zh-Hans/translation.json
rename to apps/website/src/translations/zh-Hans/translation.json
diff --git a/apps/website/public/translations/zh-Hant/translation.json b/apps/website/src/translations/zh-Hant/translation.json
similarity index 100%
rename from apps/website/public/translations/zh-Hant/translation.json
rename to apps/website/src/translations/zh-Hant/translation.json
diff --git a/apps/website/tsconfig.json b/apps/website/tsconfig.json
index 48581e18c..4d67635d7 100644
--- a/apps/website/tsconfig.json
+++ b/apps/website/tsconfig.json
@@ -9,6 +9,9 @@
"jsx": "react-jsx",
"jsxImportSource": "preact",
"skipLibCheck": true,
+ "types": [
+ "vite/client"
+ ],
"paths": {
"react": ["../../node_modules/preact/compat/"],
"react-dom": ["../../node_modules/preact/compat/"]