Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try to fix lang select #875

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions src/components/ChooseLanguage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { createForm } from "@modular-forms/solid";
import { useNavigate } from "@solidjs/router";
import { createSignal, For, Show } from "solid-js";

import { Button, ExternalLink, InfoBox, NiceP, VStack } from "~/components";
import { useI18n } from "~/i18n/context";
import { useMegaStore } from "~/state/megaStore";
import { eify, EN_OPTION, Language, LANGUAGE_OPTIONS, timeout } from "~/utils";

type ChooseLanguageForm = {
selectedLanguage: string;
};

const COMBINED_OPTIONS: Language[] = [EN_OPTION, ...LANGUAGE_OPTIONS];

export function ChooseLanguage() {
const i18n = useI18n();
const [error, setError] = createSignal<Error>();
const [state, actions] = useMegaStore();
const [loading, setLoading] = createSignal(false);
const navigate = useNavigate();

function findLanguageByValue(value: string) {
return (
COMBINED_OPTIONS.find((language) => language.value === value) ??
EN_OPTION
);
}
Comment on lines +23 to +28
Copy link
Collaborator

@benalleng benalleng Feb 10, 2024

Choose a reason for hiding this comment

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

This function is trying to find the Language object based on the value that is stored in localStorage or state which is acutally the shortName but as you'll se below we are searching for the form value based on the shortname already we don't need this function anymore and it can be removed


const [_chooseLanguageForm, { Form, Field }] =
createForm<ChooseLanguageForm>({
initialValues: {
selectedLanguage: findLanguageByValue(state.lang ?? "").value
Copy link
Collaborator

@benalleng benalleng Feb 10, 2024

Choose a reason for hiding this comment

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

this is selecting the default value to display the user in the select form, but since we are using the shortName as the returned value of the selectField we should still use shortName here

selectedLanguage: state.lang ?? ""

},
validate: (values) => {
const errors: Record<string, string> = {};
if (values.selectedLanguage === undefined) {
errors.selectedLanguage = i18n.t(
"settings.language.error_unsupported_language"
);
}
return errors;
}
});

const handleFormSubmit = async (f: ChooseLanguageForm) => {
setLoading(true);
try {
actions.saveLanguage(findLanguageByValue(f.selectedLanguage).value);

await i18n.changeLanguage(
findLanguageByValue(f.selectedLanguage).label
Comment on lines +49 to +52
Copy link
Collaborator

@benalleng benalleng Feb 10, 2024

Choose a reason for hiding this comment

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

these values are saving the state and passing the new language to the i18n api and setting the new lang state so again they should be using the shortName and with the following code we actually do not need the findLanguageByValue() function

actions.saveLanguage(f.selectedLanguage);

await i18n.changeLanguage(f.selectedLanguage);

);

await timeout(1000);
navigate("/");
} catch (e) {
console.error(e);
setError(eify(e));
setLoading(false);
}
};

return (
<VStack>
<Form onSubmit={handleFormSubmit} class="flex flex-col gap-4">
<NiceP>{i18n.t("settings.language.caption")}</NiceP>
<ExternalLink href="https://github.com/MutinyWallet/mutiny-web/issues/new">
{i18n.t("settings.language.request_language_support_link")}
</ExternalLink>
<div />
<VStack>
<Field name="selectedLanguage">
{(field, props) => (
<select
{...props}
value={field.value}
class="w-full rounded-lg bg-m-grey-750 py-2 pl-4 pr-12 text-base font-normal text-white"
>
<For each={COMBINED_OPTIONS}>
{({ value }) => (
<option
selected={field.value === value}
value={value}
Copy link
Collaborator

@benalleng benalleng Feb 10, 2024

Choose a reason for hiding this comment

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

Since we are already iterating over the COMBINED_OPTIONS object we already have access to both value and shortName and can simply select the shortname to be sent to the i18n api while displaying the values to the user

<For each={COMBINED_OPTIONS}>
    {({ value, shortName }) => (
        <option
            selected={field.value === shortName}
            value={shortName}
        >
            {value}
        </option>
    )}
</For>

>
{value}
</option>
)}
</For>
</select>
)}
</Field>
<Show when={error()}>
<InfoBox accent="red">{error()?.message}</InfoBox>
</Show>
<div />
<Button intent="blue" loading={loading()}>
{i18n.t("settings.language.select_language")}
</Button>
</VStack>
</Form>
</VStack>
);
}
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export * from "./AmountEditable";
export * from "./BalanceBox";
export * from "./BetaWarningModal";
export * from "./ChooseCurrency";
export * from "./ChooseLanguage";
export * from "./ContactEditor";
export * from "./ContactForm";
export * from "./ContactViewer";
Expand Down
6 changes: 4 additions & 2 deletions src/i18n/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ const i18n = use(LanguageDetector).init(
fallbackNS: false,
debug: true,
detection: {
order: ["querystring", "navigator", "htmlTag"],
lookupQuerystring: "lang"
order: ["localStorage", "querystring", "navigator", "htmlTag"],
lookupQuerystring: "lang",
lookupLocalStorage: "i18nextLng",
caches: ["localStorage"]
},
resources: resources
// FIXME: this doesn't work when deployed
Expand Down
10 changes: 10 additions & 0 deletions src/i18n/en/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,16 @@ export default {
"Request support for more currencies",
error_unsupported_currency: "Please Select a supported currency."
},
language: {
title: "Language",
caption: "Choose your preferred language",
select_language: "Select Language",
select_language_label: "Language",
select_language_caption:
"Choosing a new currency will change the wallet language, ignoring current browser language",
request_language_support_link: "Request support for more languages",
error_unsupported_language: "Please Select a supported language."
},
lnurl_auth: {
title: "LNURL Auth",
auth: "Auth",
Expand Down
2 changes: 2 additions & 0 deletions src/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
EmergencyKit,
Encrypt,
Gift,
Language,
ManageFederations,
Plus,
Restore,
Expand Down Expand Up @@ -109,6 +110,7 @@ export function Router() {
<Route path="/channels" component={Channels} />
<Route path="/connections" component={Connections} />
<Route path="/currency" component={Currency} />
<Route path="/language" component={Language} />
<Route path="/emergencykit" component={EmergencyKit} />
<Route path="/encrypt" component={Encrypt} />
<Route path="/gift" component={Gift} />
Expand Down
35 changes: 35 additions & 0 deletions src/routes/settings/Language.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
BackLink,
Card,
ChooseLanguage,
DefaultMain,
LargeHeader,
MutinyWalletGuard,
NavBar,
SafeArea
} from "~/components";
import { useI18n } from "~/i18n/context";

export function Language() {
const i18n = useI18n();
return (
<MutinyWalletGuard>
<SafeArea>
<DefaultMain>
<BackLink
href="/settings"
title={i18n.t("settings.header")}
/>
<LargeHeader>
{i18n.t("settings.language.title")}
</LargeHeader>
<Card title={i18n.t("settings.language.select_language")}>
<ChooseLanguage />
</Card>
<div class="h-full" />
</DefaultMain>
<NavBar activeTab="settings" />
</SafeArea>
</MutinyWalletGuard>
);
}
5 changes: 5 additions & 0 deletions src/routes/settings/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ export function Settings() {
text: i18n.t("settings.currency.title"),
caption: i18n.t("settings.currency.caption")
},
{
href: "/settings/language",
text: i18n.t("settings.language.title"),
caption: i18n.t("settings.language.caption")
},
{
href: "/settings/servers",
text: i18n.t("settings.servers.title"),
Expand Down
1 change: 1 addition & 0 deletions src/routes/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from "./Backup";
export * from "./Channels";
export * from "./Connections";
export * from "./Currency";
export * from "./Language";
export * from "./EmergencyKit";
export * from "./Encrypt";
export * from "./Gift";
Expand Down
7 changes: 7 additions & 0 deletions src/state/megaStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type MegaStore = [
price_sync_backoff_multiple?: number;
price: number;
fiat: Currency;
lang?: string;
has_backed_up: boolean;
wallet_loading: boolean;
setup_error?: Error;
Expand Down Expand Up @@ -83,6 +84,7 @@ type MegaStore = [
checkForSubscription(justPaid?: boolean): Promise<void>;
fetchPrice(fiat: Currency): Promise<number>;
saveFiat(fiat: Currency): void;
saveLanguage(lang: string): void;
saveNpub(npub: string): void;
setPreferredInvoiceType(
type: "unified" | "lightning" | "onchain"
Expand Down Expand Up @@ -132,6 +134,7 @@ export const Provider: ParentComponent = (props) => {
load_stage: "fresh" as LoadStage,
settings: undefined as MutinyWalletSettingStrings | undefined,
safe_mode: searchParams.safe_mode === "true",
lang: localStorage.getItem("lang") || undefined,
npub: localStorage.getItem("npub") || undefined,
preferredInvoiceType: "unified" as "unified" | "lightning" | "onchain",
betaWarned: localStorage.getItem("betaWarned") === "true",
Expand Down Expand Up @@ -332,6 +335,10 @@ export const Provider: ParentComponent = (props) => {
fiat: fiat
});
},
saveLanguage(lang: string) {
localStorage.setItem("i18nextLng", lang);
setState({ lang });
},
saveNpub(npub: string) {
localStorage.setItem("npub", npub);
setState({ npub });
Expand Down
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export * from "./vibrate";
export * from "./openLinkProgrammatically";
export * from "./nostr";
export * from "./currencies";
export * from "./languages";
export * from "./bech32";
export * from "./keypad";
export * from "./debounce";
20 changes: 20 additions & 0 deletions src/utils/languages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export interface Language {
value: string;
label: string;
}

export const EN_OPTION: Language = {
value: "English",
label: "en"
};

export const LANGUAGE_OPTIONS: Language[] = [
{
value: "Português",
label: "pt"
},
{
value: "Korean",
label: "ko"
}
];
Loading