Skip to content

Commit

Permalink
Merge pull request #216 from pvdthings/main
Browse files Browse the repository at this point in the history
Spanish lang support and other improvements
  • Loading branch information
dillonfagan authored Mar 12, 2023
2 parents 6dfe449 + 2bb9f6c commit 267f136
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 19 deletions.
8 changes: 6 additions & 2 deletions src/lib/filters.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// Will be automatically chosen on refresh as the filtered category
export const defaultFilterCategory = "All";

export const filter = (things, { keyword, onlyWishList, category }) => {
let filtered = things;
if (category)

if (category && category.toLowerCase() !== "all")
filtered = filtered.filter(thing => thing.categories.includes(category));
if (keyword.length > 0)
filtered = filtered.filter(thing => thing.name.toLowerCase().includes(keyword.toLowerCase()));
Expand All @@ -13,5 +17,5 @@ export const filter = (things, { keyword, onlyWishList, category }) => {
}

export const filterByCategory = (things, category) => {
return things.filter(thing => thing.categories?.includes(category));
return category.toLowerCase() === "all" ? things : things.filter(thing => thing.categories?.includes(category));
}
13 changes: 9 additions & 4 deletions src/lib/foundation/Chooser.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<script lang="ts">
import { createEventDispatcher } from "svelte";
import { t, locale } from "$lib/language/translate";
import { defaultFilterCategory } from "../filters";
export let options = [];
let chosenOption = options[0];
let chosenOption = defaultFilterCategory;
let dropdownHidden = true;
$: isEnglish = $locale === "en";
const dispatch = createEventDispatcher();
const toggleDropdown = () => {
Expand All @@ -26,12 +30,13 @@
<span class="mr-1">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="inline"><polyline points="6 9 12 15 18 9"></polyline></svg>
</span>
<span>{chosenOption}</span>
<span>{isEnglish ? chosenOption : $t(chosenOption)}</span>
</button>
<div class:dropdownHidden class="fixed top-0 left-0 w-full h-full overflow-y-scroll md:h-fit md:absolute md:top-14 bg-indigo-50 md:brutal md:hovers-static p-4 md:rounded-md flex flex-col gap-y-4 md:gap-y-2 z-50">
<div class="text-xl font-bold md:hidden">Choose a category&colon;</div>
<div class="text-xl font-bold md:hidden">{$t('Chooser.CategoryPrompt')}</div>
<button on:click={() => optionChosen(defaultFilterCategory)} class="text-2xl md:text-lg text-left active:underline hover:underline hover:underline-offset-2 hover:decoration-2">{isEnglish ? defaultFilterCategory : $t(defaultFilterCategory)}</button>
{#each options as option}
<button on:click={() => optionChosen(option)} class="text-2xl md:text-lg text-left active:underline hover:underline hover:underline-offset-2 hover:decoration-2">{option}</button>
<button on:click={() => optionChosen(option)} class="text-2xl md:text-lg text-left active:underline hover:underline hover:underline-offset-2 hover:decoration-2">{isEnglish ? option : $t(option)}</button>
{/each}
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/lib/icons/box.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions src/lib/language/translate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Code unapologetically copied from: https://dev.to/danawoodman/svelte-quick-tip-adding-basic-internationalization-i18n-to-you-app-2lm

import { derived, writable } from "svelte/store";
import translations from "./translations";

export const locale = writable("en");
export const locales = Object.keys(translations);

function translate(locale, key, vars) {
// Let's throw some errors if we're trying to use keys/locales that don't exist.
// We could improve this by using Typescript and/or fallback values.
if (!key) throw new Error("no key provided to $t()");
if (!locale) throw new Error(`no translation for key "${key}"`);

// Grab the translation from the translations object.
let text = translations[locale][key];

if (!text) throw new Error(`no translation found for ${locale}.${key}`);

// Replace any passed in variables in the translation string.
Object.keys(vars).map((k) => {
const regex = new RegExp(`{{${k}}}`, "g");
text = text.replace(regex, vars[k]);
});

return text;
}

export const t = derived(locale, ($locale) => (key, vars = {}) =>
translate($locale, key, vars)
);
36 changes: 36 additions & 0 deletions src/lib/language/translations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export default {
en: {
"Button.Home": "Home",
"Button.Donate": "Donate",
"Button.WishList": "Wish List",
"Chooser.CategoryPrompt": "Choose a category:",
"Input.Search": "Search...",
"Thing.Tags.Available": "Available",
"A project by": "A project by",
"No Results": "No Results"
},
es: {
"Button.Home": "Inicio",
"Button.Donate": "Donar",
"Button.WishList": "Donaciones",
"Chooser.CategoryPrompt": "Elija una categoría:",
"Input.Search": "Buscar...",
"Thing.Tags.Available": "Disponible",
"A project by": "Un proyecto de",
"No Results": "No hay resultados",
"All": "Todas",
"DIY": "Bricolaje",
"Media": "Media",
"Games": "Juegos",
"Outdoors": "Aire libre",
"Sports": "Deportes",
"Entertainment": "Diversión",
"Yard": "Patio",
"Cleaning": "Limpia",
"Cooking": "Cocina",
"Crafts": "Artesanía",
"Pet": "Mascotas",
"Automotive": "Automotor",
"Health": "Salud"
}
}
3 changes: 2 additions & 1 deletion src/lib/layout/Footer.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script>
import { Column, Link, Row, Text } from "$lib/Foundation.svelte";
import { t } from "$lib/language/translate";
</script>

<footer class="bg-bg py-10 relative z-40">
Expand Down Expand Up @@ -42,7 +43,7 @@
</a>
</Row>
<Text body light center>
A project by <Link to="https://starboard.coop">Starboard Co-op</Link>
{$t("A project by")} <Link to="https://starboard.coop">Starboard Co-op</Link>
</Text>
</Column>
</footer>
17 changes: 15 additions & 2 deletions src/lib/layout/Header.svelte
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<script>
import { t, locale, locales } from "$lib/language/translate"
</script>

<header class="w-full p-4 flex flex-col space-y-8 justify-center">
<div class="grid grid-cols-3">
<div class="flex flex-row justify-start">
Expand All @@ -7,7 +11,7 @@
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<polyline points="15 6 9 12 15 18" />
</svg>
<div class="text-xl font-bold font-display hover:underline">HOME</div>
<div class="text-xl font-bold font-display hover:underline uppercase">{$t("Button.Home")}</div>
</a>
</div>
</div>
Expand All @@ -16,7 +20,16 @@
<img src="/PVD_Things_Logo_White.png" alt="PVD Things" class="h-16 lg:h-20"/>
</a>
</div>
<div class="flex flex-row justify-end"></div>
<div class="flex flex-row gap-x-3 justify-end align-top">
{#each locales as localeKey}
<button
class="text-xl font-bold font-display h-fit {($locale === localeKey) && 'underline'} hover:underline uppercase"
on:click={() => locale.set(localeKey)}
>
{localeKey}
</button>
{/each}
</div>
</div>
<h1 hidden>PVD Things</h1>
</header>
10 changes: 6 additions & 4 deletions src/lib/things/Thing.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<script>
import { Card, Text } from "$lib/Foundation.svelte";
import { Card, Text } from "$lib/Foundation.svelte";
import BoxIcon from "$lib/icons/box.svg";
import { t } from "$lib/language/translate";
export let thing;
Expand All @@ -11,15 +13,15 @@

<div class="flex flex-col {className}">
<Card>
<img src={thing.image} alt={thing.name} class="h-full w-full object-contain" />
<img src={thing.image ?? BoxIcon} alt={thing.name} class="h-full w-full object-contain" />
</Card>
<div class="pl-1 pt-2 flex flex-col gap-2 justify-between flex-grow">
<Text display bold smallauto>{thing.name}</Text>
<div class="flex flex-col lg:flex-row gap-2">
{#if thing.stock > 0}
<div class="px-2 py-1 rounded bg-green-300 w-max font-medium text-sm">Available</div>
<div class="px-2 py-1 rounded bg-green-300 w-max font-medium text-sm">{$t("Thing.Tags.Available")}</div>
{:else}
<a class="px-2 py-1 rounded brutal hover:hovers-static bg-primary w-max font-bold font-display text-sm" href={donateURL} target="_blank" rel="noreferrer">Donate</a>
<a class="px-2 py-1 rounded brutal hover:hovers-static bg-primary w-max font-bold font-display text-sm" href={donateURL} target="_blank" rel="noreferrer">{$t("Button.Donate")}</a>
{/if}
</div>
</div>
Expand Down
17 changes: 11 additions & 6 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
<script>
import { onMount } from "svelte";
import { filter } from "$lib/filters";
import { defaultFilterCategory, filter } from "$lib/filters";
import Things from "$lib/things/Things.svelte";
import { Button, TextInput } from "$lib/Foundation.svelte";
import { ButtonTheme } from "$lib/foundation/button";
import LoadingIndicator from "$lib/LoadingIndicator.svelte";
import Chooser from "$lib/foundation/Chooser.svelte";
import EyeOffIcon from "$lib/icons/eye-off.svg";
import EyeIcon from "$lib/icons/eye.svg";
import { t } from "$lib/language/translate";
export let data;
let shownThings = data.things;
let shownCategory = "DIY";
let shownCategory = defaultFilterCategory;
let searchText = "";
let showingOnlyWishList = false;
Expand Down Expand Up @@ -50,20 +51,24 @@
selectedIcon={EyeIcon}
on:click={toggleWishList}
theme={ButtonTheme.default}
text="Wish List"
text={$t("Button.WishList")}
selected={showingOnlyWishList}>
Wish List
{$t("Button.WishList")}
</Button>
{/key}
</div>
<TextInput
bind:value={searchText}
on:input={filterThings}
placeholder="Search..."
placeholder={$t("Input.Search")}
/>
</div>
<div class="mb-8">
<Things things={shownThings} categories={data.categories} {shownCategory} />
{#if shownThings.length > 0}
<Things things={shownThings} categories={data.categories} {shownCategory} />
{:else}
<div class="text-lg text-center font-bold uppercase">{$t("No Results")}</div>
{/if}
</div>
{/if}
</div>

0 comments on commit 267f136

Please sign in to comment.