diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..78f0280 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "tabWidth": 4, + "useTabs": false, + "bracketSameLine": true +} diff --git a/package-lock.json b/package-lock.json index 1353389..03bb08f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,9 @@ "name": "watsonindustries", "version": "0.0.1", "dependencies": { - "daisyui": "^2.46.0" + "daisyui": "^2.46.0", + "marked": "^5.1.0", + "sveltekit-i18n": "^2.2.2" }, "devDependencies": { "@steeze-ui/heroicons": "^2.2.1", @@ -24,6 +26,8 @@ "eslint": "^8.28.0", "eslint-plugin-svelte3": "^4.0.0", "postcss": "^8.4.20", + "prettier": "^2.8.8", + "prettier-plugin-svelte": "^2.10.1", "svelte": "^3.54.0", "svelte-check": "^2.9.2", "svelte-meta-tags": "^2.6.4", @@ -607,6 +611,22 @@ "vite": "^4.0.0" } }, + "node_modules/@sveltekit-i18n/base": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@sveltekit-i18n/base/-/base-1.2.1.tgz", + "integrity": "sha512-F8gqG2+KAOeT0o2wYlUrW3TRCX7zaD7rBy/1CEVNw0irfw9TgFf/ODmhubkHHT3+6Zk+SMz8RNgeuffBfAMbJw==", + "optionalDependencies": { + "@sveltekit-i18n/parser-default": "^1.x" + }, + "peerDependencies": { + "svelte": "^3.x" + } + }, + "node_modules/@sveltekit-i18n/parser-default": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@sveltekit-i18n/parser-default/-/parser-default-1.0.3.tgz", + "integrity": "sha512-HheveklTjp3hxpYQhoHfyA6B4bQaUeSV5MQf2usIv/58UF2jY/YqhCAWj9bDBjufbuZc5pSz4BXvdX3WVT+viA==" + }, "node_modules/@tailwindcss/typography": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.8.tgz", @@ -2192,6 +2212,17 @@ "node": ">=12" } }, + "node_modules/marked": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.0.tgz", + "integrity": "sha512-z3/nBe7aTI8JDszlYLk7dDVNpngjw0o1ZJtrA9kIfkkHcIF+xH7mO23aISl4WxP83elU+MFROgahqdpd05lMEQ==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2603,6 +2634,31 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-svelte": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-2.10.1.tgz", + "integrity": "sha512-Wlq7Z5v2ueCubWo0TZzKc9XHcm7TDxqcuzRuGd0gcENfzfT4JZ9yDlCbEgxWgiPmLHkBjfOtpAWkcT28MCDpUQ==", + "dev": true, + "peerDependencies": { + "prettier": "^1.16.4 || ^2.0.0", + "svelte": "^3.2.0 || ^4.0.0-next.0" + } + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2980,7 +3036,6 @@ "version": "3.55.0", "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.55.0.tgz", "integrity": "sha512-uGu2FVMlOuey4JoKHKrpZFkoYyj0VLjJdz47zX5+gVK5odxHM40RVhar9/iK2YFRVxvfg9FkhfVlR0sjeIrOiA==", - "dev": true, "engines": { "node": ">= 8" } @@ -3106,6 +3161,18 @@ "sourcemap-codec": "^1.4.8" } }, + "node_modules/sveltekit-i18n": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/sveltekit-i18n/-/sveltekit-i18n-2.2.2.tgz", + "integrity": "sha512-6eygICleGCSL7elY7A3trF8XUhV+mlW56ZSoD0UUKXlw+Y6u0MTTHDq48u1LyY73SfnlbPHXgTarhTjZ0BvUKA==", + "dependencies": { + "@sveltekit-i18n/base": "1.2.1", + "@sveltekit-i18n/parser-default": "1.0.3" + }, + "peerDependencies": { + "svelte": "^3.x" + } + }, "node_modules/tailwindcss": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", diff --git a/package.json b/package.json index 7e14f69..b5d740f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "preview": "vite preview", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "eslint ." + "lint": "eslint .", + "format": "prettier --write --plugin-search-dir=. .", + "formatfile": "prettier --write --plugin-search-dir=." }, "devDependencies": { "@steeze-ui/heroicons": "^2.2.1", @@ -24,6 +26,8 @@ "eslint": "^8.28.0", "eslint-plugin-svelte3": "^4.0.0", "postcss": "^8.4.20", + "prettier": "^2.8.8", + "prettier-plugin-svelte": "^2.10.1", "svelte": "^3.54.0", "svelte-check": "^2.9.2", "svelte-meta-tags": "^2.6.4", @@ -34,6 +38,8 @@ }, "type": "module", "dependencies": { - "daisyui": "^2.46.0" + "daisyui": "^2.46.0", + "marked": "^5.1.0", + "sveltekit-i18n": "^2.2.2" } } diff --git a/src/lib/PageTitle.svelte b/src/lib/PageTitle.svelte new file mode 100644 index 0000000..d4ce780 --- /dev/null +++ b/src/lib/PageTitle.svelte @@ -0,0 +1,17 @@ + + + + {pageTitle} + diff --git a/src/lib/lang/en/about.json b/src/lib/lang/en/about.json new file mode 100644 index 0000000..6e94ee5 --- /dev/null +++ b/src/lib/lang/en/about.json @@ -0,0 +1,10 @@ +{ + "pagename": "About", + "header": "About", + "watsonindustrieslogo.alttext": "Watson Industries logo", + "description": "Watson Industries was founded on **Amelia's Birthday, January 6th**, and is the embodiment of the best parts of Ame, TeaMates, and Investigators:\n- creativity\n- talent\n- innovation\n- humor\n\nThe website is a living, non-profit open source project and is open to contributions.\n

\nWatsonIndustries.live is a fan project dedicated to [Amelia Watson](https://hololive.hololivepro.com/en/talents/watson-amelia/) of HololiveEN and is not associated with Cover Corp or Hololive Productions in any way. The project falls under the [Fan Work Guidelines](https://en.hololive.tv/terms).", + "featured": { + "header": "Want your content featured here?", + "description": "A process will come soon, for now you can simply DM [@DaniruKun on Twitter](https://twitter.com/danirukun)." + } +} \ No newline at end of file diff --git a/src/lib/lang/en/common.json b/src/lib/lang/en/common.json new file mode 100644 index 0000000..7c0ca12 --- /dev/null +++ b/src/lib/lang/en/common.json @@ -0,0 +1,5 @@ +{ + "watsonindustries": "Watson Industries", + "learnmore": "Learn more", + "sitetitle": "{{sitename}} - {{pagename}}" +} \ No newline at end of file diff --git a/src/lib/lang/en/home.json b/src/lib/lang/en/home.json new file mode 100644 index 0000000..755187f --- /dev/null +++ b/src/lib/lang/en/home.json @@ -0,0 +1,25 @@ +{ + "pagename": "Home", + "watsonindustries": { + "description": "Innovation knows no bounds at Watson Industries, where we push the limits of what's possible in rail, ametaverse, NFATs, Artificial Intelligence, groundpounding, and even time travel. Join us on the cutting edge of progress.", + "joinbutton.label": "Join Us" + }, + "watsonrailways": { + "header": "Watson Railways", + "description": "Experience the future of transportation with Watson Railways, a subsidiary of Watson Industries. With cutting-edge technology and a dedication to safety and efficiency, we are revolutionizing the way we travel by rail.", + "logo.alttext": "Watson Railways logo" + }, + "partners": { + "header": "Our Partners", + "description": "We would be nothing without our amazing partners, who supply us with nutrition and energy to keep pounding those grounds.", + "takoeats.logo.alttext": "Tako Eats logo", + "ubersheep.logo.alttext": "Uber Sheep logo by totangtotan", + "kfp.logo.alttext": "KFP logo with black background" + }, + "opensource": { + "image.alttext": "Watson Industries loves open source", + "header": "Open Source", + "description": "At Watson Industries, we believe in the power of collaboration and sharing knowledge. That's why we make our projects open source, allowing others to contribute, learn, and innovate with us.", + "browsebutton.label": "Browse Projects" + } +} \ No newline at end of file diff --git a/src/lib/lang/en/layout.json b/src/lib/lang/en/layout.json new file mode 100644 index 0000000..b08e372 --- /dev/null +++ b/src/lib/lang/en/layout.json @@ -0,0 +1,27 @@ +{ + "header.menu": { + "home": "Homepage", + "watsonrailways": "Watson Railways", + "ametaverse": "Ametaverse", + "amedoko": "AmeDoko App", + "about": "About" + }, + "footer": { + "services": { + "header": "Services", + "watsonrailways": "Watson Railways", + "ametaverse": "Ametaverse", + "amedoko": "AmeDoko" + }, + "company": { + "header": "Company", + "about": "About", + "credits": "Credits", + "github": "GitHub" + }, + "legal": { + "header": "Legal", + "privacy": "Privacy & Cookie policy" + } + } +} diff --git a/src/lib/lang/en/privacy.json b/src/lib/lang/en/privacy.json new file mode 100644 index 0000000..1422b43 --- /dev/null +++ b/src/lib/lang/en/privacy.json @@ -0,0 +1,7 @@ +{ + "pagename": "Privacy", + "header": "Privacy Policy", + "tagline": "We don't want or need your cookies.", + "cookieimage.alttext": "Cookies from Irasutoya", + "description": "We only use [Plausible Analytics](https://plausible.io/) for statistics purposes and do not use any cookies or collect personal information.\n\nYou can read more about how Plausible collects analytics [on their official website](https://plausible.io/data-policy).\n\nHowever, pages that include iframes like YouTube embeds may use additional trackers. By visiting these pages you agree to [YouTube's privacy policy](https://support.google.com/youtube/answer/10364219)." +} \ No newline at end of file diff --git a/src/lib/lang/ja/common.json b/src/lib/lang/ja/common.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/src/lib/lang/ja/common.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/lib/lang/ja/home.json b/src/lib/lang/ja/home.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/src/lib/lang/ja/home.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/lib/lang/ko/common.json b/src/lib/lang/ko/common.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/src/lib/lang/ko/common.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/lib/lang/ko/home.json b/src/lib/lang/ko/home.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/src/lib/lang/ko/home.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/lib/lang/lang.json b/src/lib/lang/lang.json new file mode 100644 index 0000000..aca9e17 --- /dev/null +++ b/src/lib/lang/lang.json @@ -0,0 +1,9 @@ +{ + "en": "English", + "ja": "日本語", + "ko": "한국어", + "nl": "Nederlands", + "de": "Deutsch", + "id": "Bahasa Indonesia", + "ru": "Русский" +} \ No newline at end of file diff --git a/src/lib/lang/localizationIndex.json b/src/lib/lang/localizationIndex.json new file mode 100644 index 0000000..5264edc --- /dev/null +++ b/src/lib/lang/localizationIndex.json @@ -0,0 +1,20 @@ +[ + { + "key": "common" + }, + { + "key": "layout" + }, + { + "key": "home", + "routes": ["/"] + }, + { + "key": "about", + "routes": ["/about"] + }, + { + "key": "privacy", + "routes": ["/privacy"] + } +] diff --git a/src/lib/translations.ts b/src/lib/translations.ts new file mode 100644 index 0000000..7923d67 --- /dev/null +++ b/src/lib/translations.ts @@ -0,0 +1,48 @@ +import i18n from "sveltekit-i18n"; +import lang from "./lang/lang.json"; +import localizationIndex from "./lang/localizationIndex.json"; + +type Locale = keyof typeof lang; + +type SyncTranslationsObject = { + [langcode: string]: {lang: typeof lang}, +} + +type AsyncLocaleLoader = { + locale: Locale, + key: string, + routes?: string[], + loader: () => Promise +} + +type LocaleFileDetails = { + key: string, + routes?: string[] +} + +const syncTranslations: SyncTranslationsObject = {}; +const asyncTranslations: AsyncLocaleLoader[] = []; + +Object.keys(lang).forEach(langcode => { + syncTranslations[langcode] = { lang }; + localizationIndex.forEach((localeFileDetails: LocaleFileDetails) => { + const { key, routes } = localeFileDetails; + const loader: AsyncLocaleLoader = { + locale: langcode as Locale, + key: key, + routes: routes, + loader: async () => ( + await import(`./lang/${langcode}/${key}.json`) + ).default, + }; + asyncTranslations.push(loader) + }); +}); + +/** @type {import("sveltekit-i18n").Config} */ +const config = ({ + loaders: asyncTranslations, + translations: syncTranslations +}); + +export const { t, locale, locales, loading, loadTranslations } = new i18n(config); \ No newline at end of file diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 3671efa..d800a28 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -15,6 +15,8 @@ import Moustache from "$lib/Moustache.svelte"; export let data: LayoutData; + + import { t } from "$lib/translations"; @@ -108,22 +110,23 @@ diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 721751e..edd059f 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -1,9 +1,15 @@ import type { LayoutLoad } from './$types'; +import { loadTranslations, locale } from '$lib/translations'; import thumbnailImg from "$lib/logos/watson-industries-landscape-light.png"; export const load = (async ({ url }) => { const thumbnailImgURL = new URL(thumbnailImg, url.origin).toString(); + const { pathname } = url; + const defaultLocale = "en"; // get from cookie, user session, ... + const initLocale = locale.get() || defaultLocale; // set default if no locale already set + await loadTranslations(initLocale, pathname); // keep this just before the `return` + return { thumbnailImgURL }; -}) satisfies LayoutLoad; \ No newline at end of file +}) satisfies LayoutLoad; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index f72a3c8..3c428ce 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,4 +1,4 @@ - - - Watson Industries - Home - +
-
-

Watson Industries

-

Innovation knows no bounds at Watson Industries, where we push the limits of what's possible in rail, ametaverse, NFATs, Artificial Intelligence, groundpounding, and even time travel. Join us on the cutting edge of progress.

+

{$t("common.watsonindustries")}

+

{$t("home.watsonindustries.description")}

- Join Us + {$t("home.watsonindustries.joinbutton.label")}
@@ -31,11 +31,11 @@
- Watson Railways logo + {$t("home.watsonrailways.logo.alttext")}
-

Watson Railways

-

Experience the future of transportation with Watson Railways, a subsidiary of Watson Industries. With cutting-edge technology and a dedication to safety and efficiency, we are revolutionizing the way we travel by rail.

- Learn more +

{$t("home.watsonrailways.header")}

+

{$t("home.watsonrailways.description")}

+ {$t("common.learnmore")}
@@ -45,14 +45,14 @@
-

Our Partners

-

We would be nothing without our amazing partners, who supply us with nutrition and energy to keep pounding those grounds.

+

{$t("home.partners.header")}

+

{$t("home.partners.description")}

- - - + + +
@@ -61,11 +61,11 @@
- Watson Industries loves open source + {$t("home.opensource.image.alttext")}
-

Open Source

-

At Watson Industries, we believe in the power of collaboration and sharing knowledge. That's why we make our projects open source, allowing others to contribute, learn, and innovate with us.

- Browse Projects +

{$t("home.opensource.header")}

+

{$t("home.opensource.description")}

+ {$t("home.opensource.browsebutton.label")}
\ No newline at end of file diff --git a/src/routes/about/+page.svelte b/src/routes/about/+page.svelte index a6450b1..7f5b09c 100644 --- a/src/routes/about/+page.svelte +++ b/src/routes/about/+page.svelte @@ -4,57 +4,32 @@ import watsonIndustriesLogo from "$lib/logos/watson-industries-dark.png"; export let data: PageData; + + import { t } from "$lib/translations"; + import PageTitle from "$lib/PageTitle.svelte"; + import { parse } from "marked"; - - Watson Industries - About - +
-

About

+

{$t("about.header")}

HoloEN Minecraft Hyperloop
-
-

-
- Watson Industries was founded on - Amelia's Birthday, January 6th, and is the - embodiment of the best parts of Ame and TeaMates and Investigators: -

-
    -
  • creativity
  • -
  • talent
  • -
  • innovation
  • -
  • humor
  • -
-

- The website is a living, non-profit open source project and is open - to contributions. -

-
- WatsonIndustries.live is a fan project dedicated to - Amelia Watson - of HololiveEN and is not associated with Cover Corp or Hololive Productions - in any way. The project falls under the - Fan Work Guidelines. +
+ {@html parse($t("about.description"))}

- Want your content featured here? + {$t("about.featured.header")}

-

- A process will come soon, for now you can simply DM @DaniruKun on - Twitter. +

+ {@html parse($t("about.featured.description"))}

diff --git a/src/routes/privacy/+page.svelte b/src/routes/privacy/+page.svelte index 7cce251..97300d6 100644 --- a/src/routes/privacy/+page.svelte +++ b/src/routes/privacy/+page.svelte @@ -1,24 +1,22 @@ - - Watson Industries - Privacy - +
-

Privacy Policy

-

- We don't want or need your cookies. - Cookies from Irasutoya - We only use Plausible Analytics for statistics purposes and do not use any cookies or collect personal information. -
- You can read more about how Plausible collect analytics on their official website. -
- However, certain pages that include iframes like Youtube embeds might use additional trackers. By visiting these pages you agree to Youtube's privacy policies. +

{$t("privacy.header")}

+

+ {$t("privacy.tagline")} + {$t("privacy.cookieimage.alttext")} + {@html parse($t("privacy.description"))}