mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-21 14:47:41 +01:00
Merge pull request #523 from movie-web/contributing-update
Update contributing docs
This commit is contained in:
commit
152ea391f7
7 changed files with 47 additions and 85 deletions
30
.github/CONTRIBUTING.md
vendored
30
.github/CONTRIBUTING.md
vendored
|
@ -85,28 +85,10 @@ Here are some tips to make sure that your pull requests are :pinched_fingers: fi
|
||||||
### Language Contributions
|
### Language Contributions
|
||||||
Language contributions help movie-web massively, allowing people worldwide to use our app!
|
Language contributions help movie-web massively, allowing people worldwide to use our app!
|
||||||
|
|
||||||
Like most apps, our translations are stored in `.json` files. Each language string has a unique key (For example, `notFound.genericTitle`) that references a language string in the appropriate language file.
|
We use weblate for crowdsourcing our translations. [Click here to go to our translation tool.](https://weblate.movie-web.app/projects/movie-web/website/)
|
||||||
|
|
||||||
Each language file is called `translation.json` and is stored in the `src/setup/languages/<language code>/` folder. For example, the English language file is located at `src/setup/languages/en/translation.json`.
|
1. First make sure you make an account. (click the link above)
|
||||||
|
2. Click the language you want to help translate, if it's not listed you can click the plus top left to add a new language.
|
||||||
> **Warning**
|
3. In the top right of the screen, click "translate"
|
||||||
>
|
4. Here you will be prompted a key to translate, fill in a translation and proceed to the next item by pressing "save and continue".
|
||||||
> Before you start a translation, please:
|
5. Thats all there is to it, every translation will eventually come through and be pushed with an update. This usually doesn't take longer than a week.
|
||||||
> - Check there isn't an existing GitHub [issue](https://github.com/movie-web/movie-web/issues) or [pull request](https://github.com/movie-web/movie-web/pulls) open for the language.
|
|
||||||
> - Make sure we aren't in the middle of a new feature update. When releasing major versions, we only accept changes to translations once the new version is complete. Otherwise, the language files would need to be updated.
|
|
||||||
>
|
|
||||||
> Please speak to us before starting a language PR. We want to use your time effectively.
|
|
||||||
|
|
||||||
To make a translation:
|
|
||||||
- Copy the `en` folder inside the `src/setup/languages` folder
|
|
||||||
- Rename the copied folder to the 2-letter code for the country/language which is being translated.
|
|
||||||
- [Click this link to see a list of codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes). Use the codes in the `639-1` column!
|
|
||||||
- For example, Arabic is `ar`
|
|
||||||
- Edit the language strings inside the `translation.json` file
|
|
||||||
- **Do not** edit the keys. Only edit the values.
|
|
||||||
- e.g. in `"stopEditing": "Stop editing",` - only change the `Stop editing` part, not the `stopEditing` part.
|
|
||||||
- In the `src/setup/i18n.ts` file:
|
|
||||||
- Import your new translation file, e.g. `import ar from "./locales/ar/translation.json";`
|
|
||||||
- Add your translation to the `locales` object (Look at other languages for an example)
|
|
||||||
|
|
||||||
Once you have completed your translation, please open a pull request. We do not accept partial translations, so please ensure every language string is translated to the intended language.
|
|
||||||
|
|
52
.github/workflows/docs.yml
vendored
52
.github/workflows/docs.yml
vendored
|
@ -1,52 +0,0 @@
|
||||||
name: Publish docs
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
|
|
||||||
- name: Install Node.js
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
|
|
||||||
- name: Install packages
|
|
||||||
working-directory: ./.docs
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: Build project
|
|
||||||
working-directory: ./.docs
|
|
||||||
run: npm run generate
|
|
||||||
|
|
||||||
- name: Upload production-ready build files
|
|
||||||
uses: actions/upload-pages-artifact@v1
|
|
||||||
with:
|
|
||||||
path: ./.docs/.output/public
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
name: Deploy
|
|
||||||
needs: build
|
|
||||||
permissions:
|
|
||||||
pages: write
|
|
||||||
id-token: write
|
|
||||||
environment:
|
|
||||||
name: docs
|
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Deploy to GitHub Pages
|
|
||||||
id: deployment
|
|
||||||
uses: actions/deploy-pages@v2
|
|
|
@ -43,6 +43,8 @@ pnpm install
|
||||||
pnpm run dev
|
pnpm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You have to also make an `.env` file to configure your environment. Inspire it from the content of `example.env`.
|
||||||
|
|
||||||
To build production files, run:
|
To build production files, run:
|
||||||
```bash
|
```bash
|
||||||
pnpm build
|
pnpm build
|
||||||
|
@ -55,7 +57,7 @@ pnpm build
|
||||||
|
|
||||||
A simple guide has been written to assist in hosting your own instance of movie-web. Check it out below
|
A simple guide has been written to assist in hosting your own instance of movie-web. Check it out below
|
||||||
|
|
||||||
|[Selfhosting guide](https://docs.movie-web.app/self-hosting/self-hosting)|
|
|[Selfhosting guide](https://docs.movie-web.app)|
|
||||||
|---|
|
|---|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -260,7 +260,8 @@
|
||||||
"loadingUserError": {
|
"loadingUserError": {
|
||||||
"text": "Failed to load your profile",
|
"text": "Failed to load your profile",
|
||||||
"textWithReset": "Failed to load your profile from your custom server, want to reset back to the default server?",
|
"textWithReset": "Failed to load your profile from your custom server, want to reset back to the default server?",
|
||||||
"reset": "Reset custom server"
|
"reset": "Reset custom server",
|
||||||
|
"logout": "Logout"
|
||||||
},
|
},
|
||||||
"migration": {
|
"migration": {
|
||||||
"failed": "Failed to migrate your data.",
|
"failed": "Failed to migrate your data.",
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { useAsync } from "react-use";
|
||||||
import { Button } from "@/components/buttons/Button";
|
import { Button } from "@/components/buttons/Button";
|
||||||
import { Icon, Icons } from "@/components/Icon";
|
import { Icon, Icons } from "@/components/Icon";
|
||||||
import { Loading } from "@/components/layout/Loading";
|
import { Loading } from "@/components/layout/Loading";
|
||||||
|
import { useAuth } from "@/hooks/auth/useAuth";
|
||||||
import { useAuthRestore } from "@/hooks/auth/useAuthRestore";
|
import { useAuthRestore } from "@/hooks/auth/useAuthRestore";
|
||||||
import { useBackendUrl } from "@/hooks/auth/useBackendUrl";
|
import { useBackendUrl } from "@/hooks/auth/useBackendUrl";
|
||||||
import { ErrorBoundary } from "@/pages/errors/ErrorBoundary";
|
import { ErrorBoundary } from "@/pages/errors/ErrorBoundary";
|
||||||
|
@ -57,14 +58,22 @@ function LoadingScreen(props: { type: "user" | "lazy" }) {
|
||||||
function ErrorScreen(props: {
|
function ErrorScreen(props: {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
showResetButton?: boolean;
|
showResetButton?: boolean;
|
||||||
|
showLogoutButton?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { logout } = useAuth();
|
||||||
const setBackendUrl = useAuthStore((s) => s.setBackendUrl);
|
const setBackendUrl = useAuthStore((s) => s.setBackendUrl);
|
||||||
const resetBackend = useCallback(() => {
|
const resetBackend = useCallback(() => {
|
||||||
setBackendUrl(null);
|
setBackendUrl(null);
|
||||||
// eslint-disable-next-line no-restricted-globals
|
// eslint-disable-next-line no-restricted-globals
|
||||||
location.reload();
|
location.reload();
|
||||||
}, [setBackendUrl]);
|
}, [setBackendUrl]);
|
||||||
|
const logoutFromBackend = useCallback(() => {
|
||||||
|
logout().then(() => {
|
||||||
|
// eslint-disable-next-line no-restricted-globals
|
||||||
|
location.reload();
|
||||||
|
});
|
||||||
|
}, [logout]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LargeTextPart
|
<LargeTextPart
|
||||||
|
@ -80,6 +89,13 @@ function ErrorScreen(props: {
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
{props.showLogoutButton ? (
|
||||||
|
<div className="mt-6">
|
||||||
|
<Button theme="secondary" onClick={logoutFromBackend}>
|
||||||
|
{t("screens.loadingUserError.logout")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</LargeTextPart>
|
</LargeTextPart>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -90,12 +106,17 @@ function AuthWrapper() {
|
||||||
const userBackendUrl = useBackendUrl();
|
const userBackendUrl = useBackendUrl();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const isCustomUrl = backendUrl !== userBackendUrl;
|
||||||
|
|
||||||
if (status.loading) return <LoadingScreen type="user" />;
|
if (status.loading) return <LoadingScreen type="user" />;
|
||||||
if (status.error)
|
if (status.error)
|
||||||
return (
|
return (
|
||||||
<ErrorScreen showResetButton={backendUrl !== userBackendUrl}>
|
<ErrorScreen
|
||||||
|
showResetButton={isCustomUrl}
|
||||||
|
showLogoutButton={!isCustomUrl}
|
||||||
|
>
|
||||||
{t(
|
{t(
|
||||||
backendUrl !== userBackendUrl
|
isCustomUrl
|
||||||
? "screens.loadingUserError.textWithReset"
|
? "screens.loadingUserError.textWithReset"
|
||||||
: "screens.loadingUserError.text"
|
: "screens.loadingUserError.text"
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -16,6 +16,14 @@ export interface HeroPartProps {
|
||||||
searchParams: ReturnType<typeof useSearchQuery>;
|
searchParams: ReturnType<typeof useSearchQuery>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTimeOfDay(date: Date): "night" | "morning" | "day" {
|
||||||
|
const hour = date.getHours();
|
||||||
|
if (hour < 5) return "night";
|
||||||
|
if (hour < 12) return "morning";
|
||||||
|
if (hour < 19) return "day";
|
||||||
|
return "night";
|
||||||
|
}
|
||||||
|
|
||||||
export function HeroPart({ setIsSticky, searchParams }: HeroPartProps) {
|
export function HeroPart({ setIsSticky, searchParams }: HeroPartProps) {
|
||||||
const { t: randomT } = useRandomTranslation();
|
const { t: randomT } = useRandomTranslation();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
@ -44,11 +52,7 @@ export function HeroPart({ setIsSticky, searchParams }: HeroPartProps) {
|
||||||
}
|
}
|
||||||
}, [windowWidth]);
|
}, [windowWidth]);
|
||||||
|
|
||||||
let time = "night";
|
const time = getTimeOfDay(new Date());
|
||||||
const hour = new Date().getHours();
|
|
||||||
if (hour < 12) time = "morning";
|
|
||||||
else if (hour < 19) time = "day";
|
|
||||||
|
|
||||||
const title = randomT(`home.titles.${time}`);
|
const title = randomT(`home.titles.${time}`);
|
||||||
|
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
|
@ -102,6 +102,10 @@ export default defineConfig(({ mode }) => {
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
|
||||||
|
build: {
|
||||||
|
sourcemap: true,
|
||||||
|
},
|
||||||
|
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"@": path.resolve(__dirname, "./src"),
|
"@": path.resolve(__dirname, "./src"),
|
||||||
|
|
Loading…
Reference in a new issue