Add language selector on site (fixes #64) (#76)

* Add language selector on site (fixes #64)

* review fixes
This commit is contained in:
Nutomic 2022-02-17 17:53:10 +00:00 committed by GitHub
parent c5baa7f0bc
commit ba5015d2a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 842 additions and 1159 deletions

View file

@ -60,3 +60,8 @@ img {
border-color: #FFD700 !important;
color: #FFD700;
}
.language-selector {
margin-top: 7px;
background-color: #333;
}

View file

@ -1,10 +1,17 @@
import { hydrate } from "inferno-hydrate";
import { BrowserRouter } from "inferno-router";
import { App } from "../shared/components/app";
import { i18n } from "../shared/i18next";
import { getLanguageFromCookie, i18n } from "../shared/i18next";
// Setting the language for js browsers
// If query param is set, server updates cookie automatically,
// so no need to check the query here
const languageCookie = getLanguageFromCookie(document.cookie);
if (languageCookie != null) {
i18n.changeLanguage(languageCookie);
} else {
i18n.changeLanguage(navigator.language);
}
const wrapper = (
<BrowserRouter>

View file

@ -7,7 +7,7 @@ import { App } from "../shared/components/app";
// import { routes } from "../shared/routes";
import process from "process";
import { Helmet } from "inferno-helmet";
import { i18n } from "../shared/i18next";
import { getLanguageFromCookie, i18n } from "../shared/i18next";
const server = express();
const port = 1234;
@ -23,10 +23,21 @@ server.get("/*", async (req, res) => {
const context = {} as any;
// Setting the language for non-js browsers
let lang = req.headers["accept-language"]
const cookieLang = getLanguageFromCookie(req.headers.cookie);
var language: string;
if (req.query["lang"] != null) {
language = req.query["lang"].toString();
res.cookie("lang", language, {
expires: new Date(Date.now() + 60 * 60 * 24 * 7),
});
} else if (cookieLang != null) {
language = cookieLang;
} else {
language = req.headers["accept-language"]
? req.headers["accept-language"].split(",")[0]
: "en";
i18n.changeLanguage(lang);
}
i18n.changeLanguage(language);
const wrapper = (
<StaticRouter location={req.url} context={context}>

View file

@ -1,13 +1,22 @@
import { Component } from "inferno";
import { Component, ChangeEvent, linkEvent } from "inferno";
import { Link } from "inferno-router";
import { LinkLine } from "./link-line";
import { Icon } from "./icon";
import { getLanguageName, i18n } from "../i18next";
export class Navbar extends Component<any, any> {
constructor(props: any, context: any) {
super(props, context);
}
handleLanguageChange(_: any, event: ChangeEvent<HTMLSelectElement>) {
location.href = `/?lang=${event.target.value}`;
}
languageList() {
return Object.keys(i18n.services.resourceStore.data).sort();
}
render() {
return (
<>
@ -23,6 +32,22 @@ export class Navbar extends Component<any, any> {
<LinkLine />
</div>
<div class="nav-right">
<div>
<select
onChange={linkEvent(this, this.handleLanguageChange)}
class="text-light bd-dark language-selector"
>
{this.languageList().map((language, i) => (
<option
key={i}
value={language}
selected={i18n.language.startsWith(language)}
>
{getLanguageName(language)}
</option>
))}
</select>
</div>
<a href="https://github.com/LemmyNet">
<Icon icon="github" />
</a>

View file

@ -60,6 +60,36 @@ const resources = {
pt,
};
const languageNames = {
en: "English",
ru: "Русский",
zh: "中文",
es: "Español",
eu: "Euskara",
bg: "Български",
nl: "Nederlands",
fi: "Suomi",
fr: "Français",
el: "Ελληνικά",
ko: "한국어",
pl: "Polski",
ar: "العربية",
eo: "Esperanto",
de: "Deutsch",
gl: "Galego",
it: "Italiano",
ja: "日本語",
km: "ភាសាខ្មែរ",
nb_NO: "Norsk (Bokmål)",
zh_Hant: "文言",
fa: "فارسی",
id: "Bahasa Indonesia",
mnc: "ᠮᠠᠨᠵᡠ ᡤᡳᠰᡠᠨ",
sv: "Svenska",
vi: "Tiếng Việt",
pt: "Português",
};
function format(value: any, format: any): any {
return format === "uppercase" ? value.toUpperCase() : value;
}
@ -68,7 +98,6 @@ i18next.init({
debug: false,
// load: 'languageOnly',
// initImmediate: false,
lng: "en", // This is changed later
fallbackLng: "en",
resources,
interpolation: { format },
@ -77,3 +106,23 @@ i18next.init({
export const i18n = i18next as i18nTyped;
export { resources };
export function getLanguageName(key: string): string {
return languageNames[key];
}
// https://gist.github.com/hunan-rostomyan/28e8702c1cecff41f7fe64345b76f2ca
export function getLanguageFromCookie(cookies?: string): string | null {
if (cookies == null) {
return null;
}
const key = "lang=";
return (
cookies
.split(";")
.map(c => c.trim())
.filter(cookie => cookie.substring(0, key.length) === key)
.map(cookie => cookie.substring(key.length))[0] || null
);
}

1886
yarn.lock

File diff suppressed because it is too large Load diff