mirror of
https://github.com/movie-web/movie-web.git
synced 2024-12-25 20:01:49 +01:00
RTL text
Co-authored-by: mrjvs <mistrjvs@gmail.com>
This commit is contained in:
parent
762c4b0be7
commit
4813d9dbfe
26
index.html
26
index.html
@ -1,13 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta
|
||||
name="description"
|
||||
content="The place for your favourite movies & shows"
|
||||
/>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1, viewport-fit=cover, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta name="description" content="The place for your favourite movies & shows" />
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
@ -18,10 +17,7 @@
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||||
|
||||
<script src="/config.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/gh/movie-web/6C6F6C7A@8b821f445b83d51ef1b8f42c99b7346f6b47dce5/out.js"></script>
|
||||
@ -55,10 +51,12 @@
|
||||
}
|
||||
</script>
|
||||
{{/if}}
|
||||
</head>
|
||||
<body>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
</body>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -98,6 +98,8 @@
|
||||
"handlebars": "^4.7.7",
|
||||
"jsdom": "^21.1.0",
|
||||
"postcss": "^8.4.20",
|
||||
"postcss-rtl": "^2.0.0",
|
||||
"postcss-rtlcss": "^4.0.9",
|
||||
"prettier": "^2.5.1",
|
||||
"prettier-plugin-tailwindcss": "^0.1.7",
|
||||
"tailwind-scrollbar": "^2.0.1",
|
||||
|
48
pnpm-lock.yaml
generated
48
pnpm-lock.yaml
generated
@ -223,6 +223,12 @@ devDependencies:
|
||||
postcss:
|
||||
specifier: '>=8.4.31'
|
||||
version: 8.4.31
|
||||
postcss-rtl:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0(postcss@8.4.31)
|
||||
postcss-rtlcss:
|
||||
specifier: ^4.0.9
|
||||
version: 4.0.9(postcss@8.4.31)
|
||||
prettier:
|
||||
specifier: ^2.5.1
|
||||
version: 2.8.8
|
||||
@ -5070,6 +5076,26 @@ packages:
|
||||
postcss-selector-parser: 6.0.13
|
||||
dev: true
|
||||
|
||||
/postcss-rtl@2.0.0(postcss@8.4.31):
|
||||
resolution: {integrity: sha512-vFu78CvaGY9BafWRHNgDm6OjUxzRCWWCrp+KtnyXdgwibLwb/j5ls8Z/ubvOsk9B/Q2NLwSPrXRARKMaa9RBmA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
postcss: '>=8.4.31'
|
||||
dependencies:
|
||||
postcss: 8.4.31
|
||||
rtlcss: 4.0.0
|
||||
dev: true
|
||||
|
||||
/postcss-rtlcss@4.0.9(postcss@8.4.31):
|
||||
resolution: {integrity: sha512-dCNKEf+FgTv+EA3XI8ysg2RnpS5s3/iZmU+9qpCNFxHU/BhK+4hz7jyCsCAfo0CLnDrMPtaQENhwb+EGm1wh7Q==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
peerDependencies:
|
||||
postcss: '>=8.4.31'
|
||||
dependencies:
|
||||
postcss: 8.4.31
|
||||
rtlcss: 4.1.1
|
||||
dev: true
|
||||
|
||||
/postcss-selector-parser@6.0.13:
|
||||
resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==}
|
||||
engines: {node: '>=4'}
|
||||
@ -5480,6 +5506,28 @@ packages:
|
||||
'@babel/runtime': 7.22.11
|
||||
dev: false
|
||||
|
||||
/rtlcss@4.0.0:
|
||||
resolution: {integrity: sha512-j6oypPP+mgFwDXL1JkLCtm6U/DQntMUqlv5SOhpgHhdIE+PmBcjrtAHIpXfbIup47kD5Sgja9JDsDF1NNOsBwQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
escalade: 3.1.1
|
||||
picocolors: 1.0.0
|
||||
postcss: 8.4.31
|
||||
strip-json-comments: 3.1.1
|
||||
dev: true
|
||||
|
||||
/rtlcss@4.1.1:
|
||||
resolution: {integrity: sha512-/oVHgBtnPNcggP2aVXQjSy6N1mMAfHg4GSag0QtZBlD5bdDgAHwr4pydqJGd+SUCu9260+Pjqbjwtvu7EMH1KQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
escalade: 3.1.1
|
||||
picocolors: 1.0.0
|
||||
postcss: 8.4.31
|
||||
strip-json-comments: 3.1.1
|
||||
dev: true
|
||||
|
||||
/run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
dependencies:
|
||||
|
@ -25,3 +25,6 @@ export const locales = {
|
||||
pirate,
|
||||
minion,
|
||||
};
|
||||
export type Locales = keyof typeof locales;
|
||||
|
||||
export const rtlLocales: Locales[] = ["nl"];
|
||||
|
@ -9,8 +9,8 @@ export function EpisodeTitle() {
|
||||
if (meta?.type !== "show") return null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<span className="text-white font-medium mr-3">
|
||||
<div className="flex gap-3">
|
||||
<span className="text-white font-medium">
|
||||
{t("media.episodeDisplay", {
|
||||
season: meta?.season?.number,
|
||||
episode: meta?.episode?.number,
|
||||
|
@ -23,7 +23,7 @@ import { RegisterPage } from "@/pages/Register";
|
||||
import { SettingsPage } from "@/pages/Settings";
|
||||
import { Layout } from "@/setup/Layout";
|
||||
import { useHistoryListener } from "@/stores/history";
|
||||
import { useLanguageListener } from "@/stores/language";
|
||||
import { LanguageProvider } from "@/stores/language";
|
||||
|
||||
function LegacyUrlView({ children }: { children: ReactElement }) {
|
||||
const location = useLocation();
|
||||
@ -61,10 +61,10 @@ function QuickSearch() {
|
||||
function App() {
|
||||
useHistoryListener();
|
||||
useOnlineListener();
|
||||
useLanguageListener();
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<LanguageProvider />
|
||||
<Switch>
|
||||
{/* functional routes */}
|
||||
<Route exact path="/s/:query">
|
||||
|
@ -4,6 +4,7 @@ import { persist } from "zustand/middleware";
|
||||
import { immer } from "zustand/middleware/immer";
|
||||
|
||||
import i18n from "@/setup/i18n";
|
||||
import { rtlLocales } from "@/assets/languages";
|
||||
|
||||
export interface LanguageStore {
|
||||
language: string;
|
||||
@ -24,10 +25,18 @@ export const useLanguageStore = create(
|
||||
)
|
||||
);
|
||||
|
||||
export function useLanguageListener() {
|
||||
export function LanguageProvider() {
|
||||
const language = useLanguageStore((s) => s.language);
|
||||
|
||||
useEffect(() => {
|
||||
i18n.changeLanguage(language);
|
||||
}, [language]);
|
||||
|
||||
const isRtl = rtlLocales.includes(language);
|
||||
|
||||
return (
|
||||
<Helmet>
|
||||
<html dir={isRtl ? "rtl" : "ltr"} />
|
||||
</Helmet>
|
||||
);
|
||||
}
|
||||
|
43
src/stores/language/index.tsx
Normal file
43
src/stores/language/index.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { useEffect } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { immer } from "zustand/middleware/immer";
|
||||
|
||||
import { rtlLocales } from "@/assets/languages";
|
||||
import i18n from "@/setup/i18n";
|
||||
|
||||
export interface LanguageStore {
|
||||
language: string;
|
||||
setLanguage(v: string): void;
|
||||
}
|
||||
|
||||
export const useLanguageStore = create(
|
||||
persist(
|
||||
immer<LanguageStore>((set) => ({
|
||||
language: "en",
|
||||
setLanguage(v) {
|
||||
set((s) => {
|
||||
s.language = v;
|
||||
});
|
||||
},
|
||||
})),
|
||||
{ name: "__MW::locale" }
|
||||
)
|
||||
);
|
||||
|
||||
export function LanguageProvider() {
|
||||
const language = useLanguageStore((s) => s.language);
|
||||
|
||||
useEffect(() => {
|
||||
i18n.changeLanguage(language);
|
||||
}, [language]);
|
||||
|
||||
const isRtl = rtlLocales.includes(language as any);
|
||||
|
||||
return (
|
||||
<Helmet>
|
||||
<html dir={isRtl ? "rtl" : "ltr"} />
|
||||
</Helmet>
|
||||
);
|
||||
}
|
@ -7,6 +7,9 @@ import path from "path";
|
||||
import { handlebars } from "./plugins/handlebars";
|
||||
import { loadEnv } from "vite";
|
||||
|
||||
import tailwind from "tailwindcss";
|
||||
import rtl from "postcss-rtlcss";
|
||||
|
||||
export default defineConfig(({ mode }) => {
|
||||
const env = loadEnv(mode, process.cwd());
|
||||
return {
|
||||
@ -18,8 +21,8 @@ export default defineConfig(({ mode }) => {
|
||||
env.VITE_APP_DOMAIN +
|
||||
(env.VITE_NORMAL_ROUTER !== "true" ? "/#" : ""),
|
||||
domain: env.VITE_APP_DOMAIN,
|
||||
env
|
||||
}
|
||||
env,
|
||||
},
|
||||
}),
|
||||
react({
|
||||
babel: {
|
||||
@ -31,24 +34,24 @@ export default defineConfig(({ mode }) => {
|
||||
modules: false,
|
||||
useBuiltIns: "entry",
|
||||
corejs: {
|
||||
version: "3.29"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
version: "3.29",
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
}),
|
||||
VitePWA({
|
||||
disable: env.VITE_PWA_ENABLED !== "true",
|
||||
registerType: "autoUpdate",
|
||||
workbox: {
|
||||
maximumFileSizeToCacheInBytes: 4000000, // 4mb
|
||||
globIgnores: ["**ping.txt**"]
|
||||
globIgnores: ["**ping.txt**"],
|
||||
},
|
||||
includeAssets: [
|
||||
"favicon.ico",
|
||||
"apple-touch-icon.png",
|
||||
"safari-pinned-tab.svg"
|
||||
"safari-pinned-tab.svg",
|
||||
],
|
||||
manifest: {
|
||||
name: "movie-web",
|
||||
@ -63,48 +66,53 @@ export default defineConfig(({ mode }) => {
|
||||
src: "android-chrome-192x192.png",
|
||||
sizes: "192x192",
|
||||
type: "image/png",
|
||||
purpose: "any"
|
||||
purpose: "any",
|
||||
},
|
||||
{
|
||||
src: "android-chrome-512x512.png",
|
||||
sizes: "512x512",
|
||||
type: "image/png",
|
||||
purpose: "any"
|
||||
purpose: "any",
|
||||
},
|
||||
{
|
||||
src: "android-chrome-192x192.png",
|
||||
sizes: "192x192",
|
||||
type: "image/png",
|
||||
purpose: "maskable"
|
||||
purpose: "maskable",
|
||||
},
|
||||
{
|
||||
src: "android-chrome-512x512.png",
|
||||
sizes: "512x512",
|
||||
type: "image/png",
|
||||
purpose: "maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
purpose: "maskable",
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
loadVersion(),
|
||||
checker({
|
||||
overlay: {
|
||||
position: "tr"
|
||||
position: "tr",
|
||||
},
|
||||
typescript: true, // check typescript build errors in dev server
|
||||
eslint: {
|
||||
// check lint errors in dev server
|
||||
lintCommand: "eslint --ext .tsx,.ts src",
|
||||
dev: {
|
||||
logLevel: ["error"]
|
||||
}
|
||||
}
|
||||
})
|
||||
logLevel: ["error"],
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
||||
build: {
|
||||
sourcemap: true,
|
||||
},
|
||||
css: {
|
||||
postcss: {
|
||||
plugins: [tailwind(), rtl()],
|
||||
},
|
||||
},
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
@ -112,12 +120,12 @@ export default defineConfig(({ mode }) => {
|
||||
"@sozialhelden/ietf-language-tags": path.resolve(
|
||||
__dirname,
|
||||
"./node_modules/@sozialhelden/ietf-language-tags/dist/cjs"
|
||||
)
|
||||
}
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
test: {
|
||||
environment: "jsdom"
|
||||
}
|
||||
environment: "jsdom",
|
||||
},
|
||||
};
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user