Skip to content

Commit

Permalink
feat: browser language detection (#301)
Browse files Browse the repository at this point in the history
* feat: browser language detection

works for chromium, did not work for firefox.

closes #270

* only set if not null

* do it properly with tests

* prettier

* refactor: rename i18nCached to i18nConfigured

---------

Co-authored-by: michael1011 <[email protected]>
  • Loading branch information
dni and michael1011 authored Nov 14, 2023
1 parent b8c9911 commit 8308f8c
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 9 deletions.
4 changes: 2 additions & 2 deletions src/Nav.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "./style/nav.scss";
import locales from "./i18n/i18n.js";
import logo from "./assets/boltz.svg";
import Warnings from "./components/Warnings";
import { setI18n, hamburger, setHamburger } from "./signals";
import { setI18nConfigured, hamburger, setHamburger } from "./signals";

const Nav = ({ network }) => {
let timeout;
Expand Down Expand Up @@ -41,7 +41,7 @@ const Nav = ({ network }) => {
{(lang) => (
<span
class="lang"
onClick={() => setI18n(lang)}>
onClick={() => setI18nConfigured(lang)}>
{locales[lang].language}
</span>
)}
Expand Down
30 changes: 30 additions & 0 deletions src/i18n/detect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import log from "loglevel";
import locales from "./i18n";
import { defaultLanguage } from "../config";
import { i18nConfigured, setI18n } from "../signals";

export const getNavigatorLanguage = (language) => {
if (language === undefined) {
log.info(
`browser language undefined; using default: ${defaultLanguage}`,
);
return defaultLanguage;
}

const lang = language.split("-")[0];
if (!Object.keys(locales).includes(lang)) {
log.info(
`browser language "${lang}" not found; using default: ${defaultLanguage}`,
);
return defaultLanguage;
}

log.info(`detected browser language ${lang}`);
return lang;
};

export const detectLanguage = () => {
if (i18nConfigured() === null) {
setI18n(getNavigatorLanguage(navigator.language));
}
};
7 changes: 5 additions & 2 deletions src/i18n/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { createMemo } from "solid-js";
import { translator, flatten, resolveTemplate } from "@solid-primitives/i18n";
import dict from "./i18n";
import { i18n } from "../signals";
import { defaultLanguage } from "../config";
import { i18n, i18nConfigured, setI18n } from "../signals";

const dictLocale = createMemo(() => flatten(dict[i18n()]));
createMemo(() => setI18n(i18nConfigured()));

const dictLocale = createMemo(() => flatten(dict[i18n() || defaultLanguage]));

export default translator(dictLocale, resolveTemplate);
2 changes: 2 additions & 0 deletions src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import NotFound from "./NotFound";
import Notification from "./Notification";
import { checkReferralId } from "./helper";
import { loglevel, network } from "./config";
import { detectLanguage } from "./i18n/detect";
import { swapChecker } from "./utils/swapChecker";
import { detectWebLNProvider } from "./utils/webln";
import { setWebln, setWasmSupported } from "./signals";
Expand All @@ -26,6 +27,7 @@ log.setLevel(loglevel);
detectWebLNProvider().then((state) => setWebln(state));
setWasmSupported(checkWasmSupported());
checkReferralId();
detectLanguage();

swapChecker();

Expand Down
15 changes: 10 additions & 5 deletions src/signals.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createEffect, createSignal } from "solid-js";
import { makePersisted } from "@solid-primitives/storage";
import { isMobile } from "./helper";
import { LN, sideSend } from "./consts";
import { defaultLanguage, pairs } from "./config";
import { pairs } from "./config";

const defaultSelection = Object.keys(pairs)[0].split("/")[0];

Expand Down Expand Up @@ -48,6 +48,8 @@ export const [timeoutBlockHeight, setTimeoutBlockheight] = createSignal(0);
export const [refundTx, setRefundTx] = createSignal("");
export const [transactionToRefund, setTransactionToRefund] = createSignal(null);

export const [i18n, setI18n] = createSignal(null);

// local storage

// To support the values created by the deprecated "createStorageSignal"
Expand All @@ -63,10 +65,13 @@ export const [ref, setRef] = makePersisted(
...stringSerializer,
},
);
export const [i18n, setI18n] = makePersisted(createSignal(defaultLanguage), {
name: "i18n",
...stringSerializer,
});
export const [i18nConfigured, setI18nConfigured] = makePersisted(
createSignal(null),
{
name: "i18n",
...stringSerializer,
},
);
export const [denomination, setDenomination] = makePersisted(
createSignal("sat"),
{ name: "denomination", ...stringSerializer },
Expand Down
25 changes: 25 additions & 0 deletions tests/i18n/detect.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { describe, expect } from "vitest";
import { defaultLanguage } from "../../src/config";
import { getNavigatorLanguage } from "../../src/i18n/detect";

describe("detect", () => {
test.each`
navigatorLanguage | expected
${"en-US"} | ${"en"}
${"en-UK"} | ${"en"}
${"de-DE"} | ${"de"}
${"de-AT"} | ${"de"}
${"de-CH"} | ${"de"}
${"de-LUX"} | ${"de"}
${"es-ES"} | ${"es"}
${"de"} | ${"de"}
${"none-DE"} | ${defaultLanguage}
${"ro-RO"} | ${defaultLanguage}
${undefined} | ${defaultLanguage}
`(
"getNavigatorLanguage $navigatorLanguage <=> $expected",
({ navigatorLanguage, expected }) => {
expect(getNavigatorLanguage(navigatorLanguage)).toEqual(expected);
},
);
});

2 comments on commit 8308f8c

@vercel
Copy link

@vercel vercel bot commented on 8308f8c Nov 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 8308f8c Nov 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.