diff --git a/README.md b/README.md
index 6606dd7..379c7c1 100644
--- a/README.md
+++ b/README.md
@@ -36,10 +36,15 @@
Language files are named with
[IETF language tags](https://en.wikipedia.org/wiki/IETF_language_tag). Short
-tags (e.g. `en` instead of `en-GB`) are preferred. The library will
-automatically detect the language from your browser to use, but for the sake of
-testing, you can override it by running the following command in the developer
-console (Ctrl+Shift+I):
+tags (e.g. `en` instead of `en-GB`) are preferred.
+
+**IMPORTANT:** If you are adding a new language, you **must** add it to
+[`src/utils/i18n.ts`](src/utils/i18n.ts) in `supportedLngs`. Be sure to add
+yourself to [`translators.json`](translators.json) too!
+
+The library will automatically detect the language from your browser to use, but
+for the sake of testing, you can override it by running the following command in
+the developer console (Ctrl+Shift+I):
```js
localStorage.i18nextLng = "en";
diff --git a/package.json b/package.json
index 320dc11..0bfa697 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"defaultSyncNode": "https://krist.ceriat.net",
"supportURL": "https://donate.lemmmy.pw",
"supportersURL": "https://donate.lemmmy.pw/supporters.json",
+ "translateURL": "https://github.com/tmpim/KristWeb2/blob/master/README.md#contributing-translations",
"private": true,
"dependencies": {
"@craco/craco": "^5.6.4",
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index bdeccd1..f98fd40 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -85,6 +85,9 @@
"madeBy": "Made by <1>{{authorName}}1>",
"supportersTitle": "Supporters",
"supportersDescription": "This project was made possible by the following amazing supporters:",
- "supportButton": "Support KristWeb"
+ "supportButton": "Support KristWeb",
+ "translatorsTitle": "Translators",
+ "translatorsDescription": "This project was translated by the following amazing contributors:",
+ "translateButton": "Translate KristWeb"
}
}
diff --git a/src/layouts/credits/Supporters.tsx b/src/layouts/credits/Supporters.tsx
new file mode 100644
index 0000000..9033253
--- /dev/null
+++ b/src/layouts/credits/Supporters.tsx
@@ -0,0 +1,88 @@
+import React, { Component, ReactNode } from "react";
+
+import { withTranslation, WithTranslation } from "react-i18next";
+
+import Row from "react-bootstrap/Row";
+import Col from "react-bootstrap/Col";
+import Button from "react-bootstrap/Button";
+
+import packageJson from "@/package.json";
+
+interface Supporter {
+ name: string;
+ url?: string;
+};
+
+interface State {
+ isLoaded: boolean;
+ supporters: Supporter[] | null;
+};
+
+class SupportersComponent extends Component {
+ constructor(props: WithTranslation) {
+ super(props);
+
+ this.state = {
+ isLoaded: false,
+ supporters: null
+ };
+ }
+
+ componentDidMount(): void {
+ const { supportersURL } = packageJson;
+ if (!supportersURL) return;
+
+ fetch(supportersURL)
+ .then(res => res.json())
+ .then(result => this.setState({
+ isLoaded: true,
+ supporters: result.supporters
+ }))
+ .catch(() => this.setState({ isLoaded: true }));
+ }
+
+ render(): ReactNode {
+ const supportURL = packageJson.supportURL;
+ if (!supportURL) return null;
+
+ const { t } = this.props;
+ const { isLoaded, supporters } = this.state;
+
+ return <>
+
+