I18n crowdin (#242)

* #241 init crowdin usage

* #241 convert all convertible copy into i18n value

---------

Co-authored-by: neil <neil@neils-MacBook-Pro.local>
This commit is contained in:
Neil 2023-02-28 13:38:57 +08:00 committed by GitHub
parent d3fa446c8c
commit 32e53ee1ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 260 additions and 93 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ yarn-error.log
.DS_Store .DS_Store
.pnpm-store .pnpm-store
target target
copy.json

View file

@ -88,6 +88,7 @@ pnpm dev
```sh ```sh
pnpm install pnpm install
pnpm --filter desktop exec pnpm predist
pnpm --filter desktop exec pnpm dist pnpm --filter desktop exec pnpm dist
``` ```

View file

@ -1,6 +1,8 @@
const { notarize } = require("@electron/notarize"); const { notarize } = require("@electron/notarize");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const otaClient = require("@crowdin/ota-client");
const _ = require("lodash");
module.exports = { module.exports = {
appId: "xyz.tea.gui", appId: "xyz.tea.gui",
@ -17,8 +19,6 @@ module.exports = {
arch: ["x64", "arm64"] arch: ["x64", "arm64"]
} }
}, },
// TODO: if xcrun altool exists eventually in our self-hosted macos
// SOLUTION: is notarize separately in next pipeline step
afterSign: async (params) => { afterSign: async (params) => {
if (process.platform !== "darwin") { if (process.platform !== "darwin") {
return; return;
@ -51,14 +51,6 @@ module.exports = {
console.log(`Done notarizing`); console.log(`Done notarizing`);
}, },
// publish: {
// provider: "github",
// repo: "gui",
// owner: "teaxyz",
// releaseType: "release"
// },
// this determines the configuration of the auto-update feature // this determines the configuration of the auto-update feature
publish: { publish: {
provider: "generic", provider: "generic",

View file

@ -14,6 +14,7 @@
"dev:main": "cd ./electron && vite build --config ./vite.config.js --watch", "dev:main": "cd ./electron && vite build --config ./vite.config.js --watch",
"build:main": "cp package.json electron && cd ./electron && vite --config ./vite.config.js build --base . && rm package.json", "build:main": "cp package.json electron && cd ./electron && vite --config ./vite.config.js build --base . && rm package.json",
"pack": "electron-builder --dir --config electron-builder.config.cjs", "pack": "electron-builder --dir --config electron-builder.config.cjs",
"predist": "node ./scripts/update-translations.cjs",
"dist": "pnpm build && electron-builder --config electron-builder.config.cjs", "dist": "pnpm build && electron-builder --config electron-builder.config.cjs",
"package": "pnpm build && electron-builder --config electron-builder.config.cjs", "package": "pnpm build && electron-builder --config electron-builder.config.cjs",
"dev:package": "pnpm build && electron-builder --config electron-builder.config.cjs --dir", "dev:package": "pnpm build && electron-builder --config electron-builder.config.cjs --dir",
@ -72,6 +73,7 @@
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@crowdin/ota-client": "^0.7.0",
"@electron/asar": "^3.2.3", "@electron/asar": "^3.2.3",
"@sentry/electron": "^4.3.0", "@sentry/electron": "^4.3.0",
"@sentry/svelte": "^7.38.0", "@sentry/svelte": "^7.38.0",

View file

@ -0,0 +1,36 @@
const fs = require("fs");
const _ = require("lodash");
const translations = require("../src/libs/translations/translations.json");
const englishRaw = translations["en"];
delete englishRaw.lang;
function flattenObject(o, prefix = "", result = {}, keepNull = true) {
if (_.isString(o) || _.isNumber(o) || _.isBoolean(o) || (keepNull && _.isNull(o))) {
result[prefix] = o;
return result;
}
if (_.isArray(o) || _.isPlainObject(o)) {
for (let i in o) {
let pref = prefix;
if (_.isArray(o)) {
pref = pref + `[${i}]`;
} else {
if (_.isEmpty(prefix)) {
pref = i;
} else {
pref = prefix + "." + i;
}
}
flattenObject(o[i], pref, result, keepNull);
}
return result;
}
return result;
}
const flattenedEnglish = flattenObject(englishRaw);
fs.writeFileSync("./copy.json", JSON.stringify(flattenedEnglish, null, 2), "utf-8");

View file

@ -0,0 +1,39 @@
const otaClient = require("@crowdin/ota-client");
const _ = require("lodash");
const fs = require("fs");
const path = require("path");
// this read only hash is from crowdin
const hash = "cf849610ca66250f0954379ct4t";
const client = new otaClient.default(hash);
async function main() {
console.log("getting latest translation!");
const [languagesList, translationsRaw] = await Promise.all([
client.getLanguageObjects(),
client.getStrings()
]);
const lang = languagesList.reduce((map, lang) => {
map[lang.id] = lang.name;
return map;
}, {});
const translations = languagesList.reduce((map, langRaw) => {
map[langRaw.id] = {
lang
};
const translation = translationsRaw[langRaw.id];
for (const k in translation) {
const key = [langRaw.id, k].join(".");
_.set(map, key, translation[k]);
}
return map;
}, {});
const translationsPath = path.join(__dirname, "../src/libs/translations/translations.json");
await fs.writeFileSync(translationsPath, JSON.stringify(translations, null, 2), "utf-8");
}
main();

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import type { AirtablePost } from '@tea/ui/types'; import type { AirtablePost } from '@tea/ui/types';
import Posts from '@tea/ui/posts/posts.svelte'; import Posts from '@tea/ui/posts/posts.svelte';
import PanelHeader from '@tea/ui/panel-header/panel-header.svelte'; import PanelHeader from '@tea/ui/panel-header/panel-header.svelte';
@ -16,7 +17,7 @@
<PanelHeader {title} {ctaLabel} ctaLink="/" /> <PanelHeader {title} {ctaLabel} ctaLink="/" />
{#if courses.length} {#if courses.length}
<Posts posts={courses} linkTarget="_blank" /> <Posts posts={courses} readMoreCta={$t("post.read-more-cta")} linkTarget="_blank" />
{:else} {:else}
<section class="border-gray h-64 border bg-black p-4"> <section class="border-gray h-64 border bg-black p-4">
<Preloader /> <Preloader />

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import { postsStore } from '$libs/stores'; import { postsStore } from '$libs/stores';
import type { Course } from '$libs/types'; import type { Course } from '$libs/types';
@ -20,7 +21,7 @@
</script> </script>
<Gallery <Gallery
title="FEATURED COURSES" title={$t("documentation.featured-courses-title").toUpperCase()}
items={courses.map((course) => ({ items={courses.map((course) => ({
title: course.title, title: course.title,
subTitle: course.sub_title, subTitle: course.sub_title,

View file

@ -1,17 +1,18 @@
<script lang="ts"> <script lang="ts">
import { t } from '$libs/translations';
import Button from '@tea/ui/button/button.svelte'; import Button from '@tea/ui/button/button.svelte';
import * as pub from '$env/static/public'; import * as pub from '$env/static/public';
</script> </script>
<footer class="font-machina relative h-auto w-full bg-black"> <footer class="font-machina relative h-auto w-full bg-black">
<section class="p-4 px-16 py-16"> <section class="p-4 px-16 py-16">
<h3 class="text-primary mb-5 text-2xl">QUICK LINKS</h3> <h3 class="text-primary mb-5 text-2xl">{$t("footer.quick-links-title").toUpperCase()}</h3>
<menu class="flex gap-4"> <menu class="flex gap-4">
<div class="border-gray flex-grow border border-l-0 border-r-0"> <div class="border-gray flex-grow border border-l-0 border-r-0">
<a href="/"> <a href="/">
<Button> <Button>
<div class="text-primary flex justify-between hover:text-black"> <div class="text-primary flex justify-between hover:text-black">
<div class="uppercase">About the tea store</div> <div class="uppercase">{$t("footer.about-tea-store").toUpperCase()}</div>
<div>&#8594</div> <div>&#8594</div>
</div> </div>
</Button> </Button>
@ -21,7 +22,7 @@
<a href="/"> <a href="/">
<Button> <Button>
<div class="text-primary flex justify-between hover:text-black"> <div class="text-primary flex justify-between hover:text-black">
<div class="uppercase">REPORT A PROBLEM</div> <div class="uppercase">{$t("footer.report-a-problem").toUpperCase()}</div>
<div>&#8594</div> <div>&#8594</div>
</div> </div>
</Button> </Button>
@ -31,7 +32,7 @@
<a href="https://tea.xyz" target="_blank" rel="noreferrer"> <a href="https://tea.xyz" target="_blank" rel="noreferrer">
<Button> <Button>
<div class="text-primary flex justify-between hover:text-black"> <div class="text-primary flex justify-between hover:text-black">
<div class="uppercase">VISIT TEA.XYZ</div> <div class="uppercase">{$t("footer.visit-website").toUpperCase()}</div>
<div>&#8594</div> <div>&#8594</div>
</div> </div>
</Button> </Button>
@ -48,7 +49,7 @@
rel="noreferrer" rel="noreferrer"
class="hover:text-white" class="hover:text-white"
> >
TERMS & SERVICES {$t("footer.terms-services").toUpperCase()}
</a> </a>
<a <a
href="https://tea.xyz/privacy-policy/" href="https://tea.xyz/privacy-policy/"
@ -56,7 +57,7 @@
rel="noreferrer" rel="noreferrer"
class="hover:text-white" class="hover:text-white"
> >
PRIVACY POLICY {$t("footer.privacy-policy").toUpperCase()}
</a> </a>
</div> </div>
{#if pub.PUBLIC_VERSION} {#if pub.PUBLIC_VERSION}

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import type { GUIPackage } from '$libs/types'; import type { GUIPackage } from '$libs/types';
import { PackageStates } from '$libs/types'; import { PackageStates } from '$libs/types';
import PanelHeader from '@tea/ui/panel-header/panel-header.svelte'; import PanelHeader from '@tea/ui/panel-header/panel-header.svelte';
@ -13,7 +14,7 @@
}); });
</script> </script>
<PanelHeader title="My installs" ctaLabel="Check for updates >" ctaLink="#" /> <PanelHeader title={$t("package.my-installs-title")} ctaLabel={`${$t("package.check-for-updates")} >`} ctaLink="#" />
<ul class="border-gray grid grid-cols-3 border border-r-0 bg-black"> <ul class="border-gray grid grid-cols-3 border border-r-0 bg-black">
{#if packages.length > 0} {#if packages.length > 0}
@ -21,7 +22,7 @@
<div class="border-gray border border-t-0 border-l-0 p-4"> <div class="border-gray border border-t-0 border-l-0 p-4">
<MiniPackageCard <MiniPackageCard
{pkg} {pkg}
ctaLabel="DETAILS" ctaLabel={$t("package.details").toUpperCase()}
onClickCTA={async () => { onClickCTA={async () => {
console.log('do something with:', pkg.full_name); console.log('do something with:', pkg.full_name);
}} }}

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import { postsStore } from '$libs/stores'; import { postsStore } from '$libs/stores';
import type { AirtablePost } from '@tea/ui/types'; import type { AirtablePost } from '@tea/ui/types';
import Posts from '@tea/ui/posts/posts.svelte'; import Posts from '@tea/ui/posts/posts.svelte';
@ -11,7 +12,7 @@
postsStore.subscribeByTag('news', (posts) => (news = posts)); postsStore.subscribeByTag('news', (posts) => (news = posts));
</script> </script>
<PanelHeader title="Open-source News" ctaLabel="Read more articles >" ctaLink="/" /> <PanelHeader title={$t("home.os-news-title")} ctaLabel={`${$t("post.article-more-cta")} >`} ctaLink="/" />
{#if news.length} {#if news.length}
<Posts posts={news} linkTarget="_blank" /> <Posts posts={news} linkTarget="_blank" />
{:else} {:else}

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import type { GUIPackage } from '$libs/types'; import type { GUIPackage } from '$libs/types';
import { PackageStates } from '$libs/types'; import { PackageStates } from '$libs/types';
import Preloader from '@tea/ui/Preloader/Preloader.svelte'; import Preloader from '@tea/ui/Preloader/Preloader.svelte';
@ -16,10 +17,10 @@
const getCTALabel = (state: PackageStates): string => { const getCTALabel = (state: PackageStates): string => {
return { return {
[PackageStates.AVAILABLE]: 'INSTALL', [PackageStates.AVAILABLE]: $t("package.install-label").toUpperCase(),
[PackageStates.INSTALLED]: 'INSTALLED', [PackageStates.INSTALLED]: $t("package.installed-label").toUpperCase(),
[PackageStates.INSTALLING]: 'INSTALLING', [PackageStates.INSTALLING]: $t("package.installing-label").toUpperCase(),
[PackageStates.UNINSTALLED]: 'RE-INSTALL' [PackageStates.UNINSTALLED]: $t("package.reinstall-label").toUpperCase(),
}[state]; }[state];
}; };
@ -32,7 +33,7 @@
<header class="border-gray text-primary flex items-center justify-between border bg-black p-4"> <header class="border-gray text-primary flex items-center justify-between border bg-black p-4">
<span>{title}</span> <span>{title}</span>
<a href="/packages" class="font-sono text-sm underline">View all packages</a> <a href="/packages" class="font-sono text-sm underline">{$t("package.view-all-cta")}</a>
</header> </header>
<ul class="grid grid-cols-3 bg-black"> <ul class="grid grid-cols-3 bg-black">
{#if packages.length > 0} {#if packages.length > 0}

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import { packagesStore } from '$libs/stores'; import { packagesStore } from '$libs/stores';
import SortingButtons from './sorting-buttons.svelte'; import SortingButtons from './sorting-buttons.svelte';
import type { GUIPackage } from '$libs/types'; import type { GUIPackage } from '$libs/types';
@ -51,10 +52,10 @@
const getCTALabel = (state: PackageStates): string => { const getCTALabel = (state: PackageStates): string => {
return { return {
[PackageStates.AVAILABLE]: 'INSTALL', [PackageStates.AVAILABLE]: $t("package.install-label").toUpperCase(),
[PackageStates.INSTALLED]: 'INSTALLED', [PackageStates.INSTALLED]: $t("package.installed-label").toUpperCase(),
[PackageStates.INSTALLING]: 'INSTALLING', [PackageStates.INSTALLING]: $t("package.installing-label").toUpperCase(),
[PackageStates.UNINSTALLED]: 'RE-INSTALL' [PackageStates.UNINSTALLED]: $t("package.reinstall-label").toUpperCase(),
}[state]; }[state];
}; };
@ -64,7 +65,7 @@
<div class="border-gray border bg-black"> <div class="border-gray border bg-black">
<section class="flex items-center justify-between"> <section class="flex items-center justify-between">
<div> <div>
<SearchInput size="medium" {onSearch} /> <SearchInput size="medium" {onSearch} placeholder={`${$t("search")}_`} />
</div> </div>
<div class="pr-4"> <div class="pr-4">
<section class="border-gray h-12 w-48 border"> <section class="border-gray h-12 w-48 border">

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
export let onSort: (opt: string, dir: 'asc' | 'desc') => void; export let onSort: (opt: string, dir: 'asc' | 'desc') => void;
@ -8,6 +9,11 @@
const sortOptions = ['popularity', 'most recent']; const sortOptions = ['popularity', 'most recent'];
const optionLabels = {
[sortOptions[0]]: $t("sorting.popularity"),
[sortOptions[1]]: $t("sorting.most-recent")
}
const setSortBy = (opt: string) => { const setSortBy = (opt: string) => {
sortBy = opt; sortBy = opt;
if (onSort) { if (onSort) {
@ -22,7 +28,7 @@
<section class="sorting-container font-machina bg-black text-white"> <section class="sorting-container font-machina bg-black text-white">
<div class="dropdown"> <div class="dropdown">
<div class="dropdown-title">SORT ORDER</div> <div class="dropdown-title">{$t("sorting.label")}</div>
<ul class="dropdown-content column flex"> <ul class="dropdown-content column flex">
{#each sortOptions as option} {#each sortOptions as option}
<li class="flex items-center"> <li class="flex items-center">
@ -30,7 +36,7 @@
class={`sort-btn uppercase ${sortBy === option ? 'active' : ''}`} class={`sort-btn uppercase ${sortBy === option ? 'active' : ''}`}
on:click={() => setSortBy(option)} on:click={() => setSortBy(option)}
> >
{option} {optionLabels[option]}
</button> </button>
<div class="direction-arrows"> <div class="direction-arrows">
<button <button

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { searchStore } from '$libs/stores'; import { searchStore } from '$libs/stores';
import { t } from '$libs/translations';
import type { GUIPackage } from '$libs/types'; import type { GUIPackage } from '$libs/types';
import Preloader from '@tea/ui/Preloader/Preloader.svelte'; import Preloader from '@tea/ui/Preloader/Preloader.svelte';
import PackageCard from '@tea/ui/package-card/package-card.svelte'; import PackageCard from '@tea/ui/package-card/package-card.svelte';
@ -40,10 +41,10 @@
const getCTALabel = (state: PackageStates): string => { const getCTALabel = (state: PackageStates): string => {
return { return {
[PackageStates.AVAILABLE]: 'INSTALL', [PackageStates.AVAILABLE]: $t("package.install-label").toUpperCase(),
[PackageStates.INSTALLED]: 'INSTALLED', [PackageStates.INSTALLED]: $t("package.installed-label").toUpperCase(),
[PackageStates.INSTALLING]: 'INSTALLING', [PackageStates.INSTALLING]: $t("package.installing-label").toUpperCase(),
[PackageStates.UNINSTALLED]: 'RE-INSTALL' [PackageStates.UNINSTALLED]: $t("package.reinstall-label").toUpperCase(),
}[state]; }[state];
}; };

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import type { GUIPackage } from '$libs/types'; import type { GUIPackage } from '$libs/types';
import type { Package } from '@tea/ui/types'; import type { Package } from '@tea/ui/types';
import { PackageStates } from '$libs/types'; import { PackageStates } from '$libs/types';
@ -15,10 +16,10 @@
const getCTALabel = (state: PackageStates): string => { const getCTALabel = (state: PackageStates): string => {
return { return {
[PackageStates.AVAILABLE]: 'INSTALL', [PackageStates.AVAILABLE]: $t("package.install-label").toUpperCase(),
[PackageStates.INSTALLED]: 'INSTALLED', [PackageStates.INSTALLED]: $t("package.installed-label").toUpperCase(),
[PackageStates.INSTALLING]: 'INSTALLING', [PackageStates.INSTALLING]: $t("package.installing-label").toUpperCase(),
[PackageStates.UNINSTALLED]: 'RE-INSTALL' [PackageStates.UNINSTALLED]: $t("package.reinstall-label").toUpperCase(),
}[state]; }[state];
}; };

View file

@ -4,6 +4,7 @@
import { searchStore } from '$libs/stores'; import { searchStore } from '$libs/stores';
import SearchInput from '@tea/ui/search-input/search-input.svelte'; import SearchInput from '@tea/ui/search-input/search-input.svelte';
import { navStore } from '$libs/stores'; import { navStore } from '$libs/stores';
import { t } from '$libs/translations';
import ProfileNavButton from './profile-nav-button.svelte'; import ProfileNavButton from './profile-nav-button.svelte';
import SelectLang from '$components/select-lang/select-lang.svelte'; import SelectLang from '$components/select-lang/select-lang.svelte';
@ -31,7 +32,7 @@
<SearchInput <SearchInput
class="flex-grow border border-none py-4" class="flex-grow border border-none py-4"
size="small" size="small"
placeholder="search the tea store" placeholder={$t("store-search-placeholder")}
{onSearch} {onSearch}
/> />
<ul class="text-gray flex gap-4 pr-4 pt-2 align-middle"> <ul class="text-gray flex gap-4 pr-4 pt-2 align-middle">
@ -45,8 +46,8 @@
<menu <menu
class="border-gray text-gray flex h-10 gap-4 border border-l-0 border-r-0 border-t-0 pl-4 align-middle leading-10" class="border-gray text-gray flex h-10 gap-4 border border-l-0 border-r-0 border-t-0 pl-4 align-middle leading-10"
> >
<a href="/cli" class={currentPath === '/cli' ? 'active' : ''}>install teaCli</a> <a href="/cli" class={currentPath === '/cli' ? 'active' : ''}>{$t('cli.install')}</a>
<a href="/documentation" class={currentPath === '/documentation' ? 'active' : ''}>documentation</a <a href="/documentation" class={currentPath === '/documentation' ? 'active' : ''}>{$t('documentation.title')}</a
> >
<a href="/packages" class={currentPath === '/packages' ? 'active' : ''}>packages</a> <a href="/packages" class={currentPath === '/packages' ? 'active' : ''}>packages</a>
<a href="https://github.com/teaxyz" target="_blank" rel="noreferrer"> <a href="https://github.com/teaxyz" target="_blank" rel="noreferrer">

View file

@ -1,6 +1,7 @@
<!-- home / discover / welcome page --> <!-- home / discover / welcome page -->
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import ListAction from '@tea/ui/list-action/list-action.svelte'; import ListAction from '@tea/ui/list-action/list-action.svelte';
import type { ListActionItem } from '@tea/ui/types'; import type { ListActionItem } from '@tea/ui/types';
import { packagesStore } from '$libs/stores'; import { packagesStore } from '$libs/stores';
@ -13,7 +14,7 @@
.map((pkg) => ({ .map((pkg) => ({
title: pkg.full_name, title: pkg.full_name,
sub_title: pkg.version, sub_title: pkg.version,
action_label: 'INSTALL', action_label: $t("package.install-label").toUpperCase(),
image_url: pkg.thumb_image_url, image_url: pkg.thumb_image_url,
detail_url: `/packages/${pkg.slug}` detail_url: `/packages/${pkg.slug}`
})); }));
@ -25,8 +26,8 @@
</script> </script>
<ListAction <ListAction
title="Top packages this week" title={$t("package.top-list-title")}
mainCtaTitle="VIEW ALL SCRIPTS" mainCtaTitle={$t("package.view-all-cta").toUpperCase()}
items={items} items={items}
onSelectItem={onSelectPackage} onSelectItem={onSelectPackage}
/> />

View file

@ -1,47 +1,49 @@
<!-- home / discover / welcome page --> <!-- home / discover / welcome page -->
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import type { ListActionItem } from '@tea/ui/types'; import type { ListActionItem } from '@tea/ui/types';
import ListAction from '@tea/ui/list-action/list-action.svelte'; import ListAction from '@tea/ui/list-action/list-action.svelte';
const action_label = $t("script.use-label");
const items: ListActionItem[] = [ const items: ListActionItem[] = [
{ {
title: 'Script A', title: 'Script A',
sub_title: 'v 0.0.1', sub_title: 'v 0.0.1',
image_url: '/images/bored-ape.png', image_url: '/images/bored-ape.png',
action_label: 'USE' action_label
}, },
{ {
title: 'Script B', title: 'Script B',
sub_title: 'v 0.1.1', sub_title: 'v 0.1.1',
image_url: '/images/bored-ape.png', image_url: '/images/bored-ape.png',
action_label: 'USE' action_label
}, },
{ {
title: 'Script C', title: 'Script C',
sub_title: 'v 2.0.1', sub_title: 'v 2.0.1',
image_url: '/images/bored-ape.png', image_url: '/images/bored-ape.png',
action_label: 'USE' action_label
}, },
{ {
title: 'Script D', title: 'Script D',
sub_title: 'v 0.1.1', sub_title: 'v 0.1.1',
image_url: '/images/bored-ape.png', image_url: '/images/bored-ape.png',
action_label: 'USE' action_label
}, },
{ {
title: 'Script E', title: 'Script E',
sub_title: 'v 0.1.1', sub_title: 'v 0.1.1',
image_url: '/images/bored-ape.png', image_url: '/images/bored-ape.png',
action_label: 'USE' action_label
}, },
]; ];
</script> </script>
<ListAction <ListAction
title="Top scripts this week" title={$t("script.top-list-title")}
mainCtaTitle="VIEW ALL SCRIPTS" mainCtaTitle={$t("script.view-all-cta").toUpperCase()}
items={items} items={items}
onSelectItem={async (script) => { onSelectItem={async (script) => {
console.log(script) console.log(script)

View file

@ -1,9 +1,10 @@
import i18n from "sveltekit-i18n"; import i18n from "sveltekit-i18n";
import translations from "./translations"; import translations from "./translations.json";
/** @type {import('sveltekit-i18n').Config} */ /** @type {import('sveltekit-i18n').Config} */
const config = { const config = {
initLocale: "en", initLocale: "en",
fallbackLocale: "en",
translations translations
}; };

View file

@ -1,4 +0,0 @@
{
"en": "English",
"cs": "Česky"
}

View file

@ -0,0 +1,65 @@
{
"en": {
"lang": {
"en": "English"
},
"cli": {
"install": "install tea"
},
"store-search-placeholder": "search the tea store",
"search": "search",
"home": {
"discover-title": "DISCOVER",
"asset-title": "ASSET TYPE",
"tutorials-title": "TUTORIALS",
"os-news-title": "OPEN-SOURCE NEWS"
},
"package": {
"top-list-title": "Top packages this week",
"browse-cta": "Browse packages",
"what-title": "What are packages?",
"short-description": "Collections of files aggregated to form larger frameworks & functions. Think Python or Node.js.",
"foundation-essentials-title": "FOUNDATION ESSENTIALS",
"view-all-cta": "View all packages",
"install-label": "install",
"installed-label": "installed",
"installing-label": "installing",
"reinstall-label": "re-install",
"my-installs-title": "my installs",
"check-for-updates": "check for updates",
"details": "details"
},
"script": {
"top-list-title": "Top scripts this week",
"view-all-cta": "View all scripts",
"use-label": "use",
"browse-cta": "Browse scripts",
"what-title": "What are scripts?",
"short-description": "Invisible applications that chain packages together in order to perform cool actions on your computer."
},
"post": {
"workshops-title": "workshops to get started",
"article-more-cta": "Read more articles",
"read-more-cta": "read more"
},
"footer": {
"quick-links-title": "quick links",
"about-tea-store": "about the tea store",
"report-a-problem": "report a problem",
"visit-website": "visit tea.xyz",
"terms-services": "terms & services",
"privacy-policy": "privacy-policy"
},
"documentation": {
"title": "documentation",
"featured-courses-title": "featured courses",
"workshops": "workshops"
},
"view-all": "view all",
"sorting": {
"label": "sort order",
"popularity": "popularity",
"most-recent": "most recent"
}
}
}

View file

@ -1,16 +0,0 @@
import lang from "./lang.json";
export default {
en: {
lang,
cli: {
install: "install tea"
}
},
cs: {
lang,
cli: {
install: "nainstalovat cli"
}
}
};

View file

@ -1,6 +1,7 @@
<!-- home / discover / welcome page --> <!-- home / discover / welcome page -->
<script lang="ts"> <script lang="ts">
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import PageHeader from '$components/page-header/page-header.svelte'; import PageHeader from '$components/page-header/page-header.svelte';
import EssentialWorkshops from '$components/essential-workshops/essential-workshops.svelte'; import EssentialWorkshops from '$components/essential-workshops/essential-workshops.svelte';
import Packages from '$components/packages/packages.svelte'; import Packages from '$components/packages/packages.svelte';
@ -12,40 +13,40 @@
</script> </script>
<div> <div>
<PageHeader coverUrl="/images/headers/header_bg_1.png">Discover</PageHeader> <PageHeader coverUrl="/images/headers/header_bg_1.png">{$t("home.discover-title")}</PageHeader>
<section class="mt-8 mb-8"> <section class="mt-8 mb-8">
<Packages title="FOUNDATION ESSENTIALS" category="foundation_essentials" /> <Packages title={$t("package.foundation-essentials-title")} category="foundation_essentials" />
</section> </section>
<PageHeader coverUrl="/images/headers/header_bg_1.png">ASSET TYPE</PageHeader> <PageHeader coverUrl="/images/headers/header_bg_1.png">{$t("home.asset-title")}</PageHeader>
<section class="mt-8 mb-8 flex gap-4"> <section class="mt-8 mb-8 flex gap-4">
<div> <div>
<HeaderCard <HeaderCard
title="Browse Packages" title={$t("package.browse-cta")}
imgUrl="/images/bored-ape.png" imgUrl="/images/bored-ape.png"
ctaUrl="/packages" ctaUrl="/packages"
ctaLabel="Browse packages >" ctaLabel={`${$t("package.browse-cta")} >`}
articleTitle="What are packages?" articleTitle={$t("package.what-title")}
description="Collections of files aggregated to form larger frameworks & functions. Think Python or Node.js." description={$t("package.short-description")}
/> />
<TopPackages /> <TopPackages />
</div> </div>
<div> <div>
<HeaderCard <HeaderCard
title="Browse Scripts" title={$t("script.browse-cta")}
imgUrl="/images/bored-ape.png" imgUrl="/images/bored-ape.png"
ctaUrl="/packages" ctaUrl="/packages"
ctaLabel="Browse scripts >" ctaLabel={`${$t("script.browse-cta")} >`}
articleTitle="What are scripts?" articleTitle={$t("script.what-title")}
description="Invisible applications that chain packages together in order to perform cool actions on your computer." description={$t("script.short-description")}
/> />
<TopScripts/> <TopScripts/>
</div> </div>
</section> </section>
<PageHeader coverUrl="/images/headers/header_bg_1.png">TUTORIALS</PageHeader> <PageHeader coverUrl="/images/headers/header_bg_1.png">{$t("home.tutorials-title")}</PageHeader>
<section class="mt-8 mb-8"> <section class="mt-8 mb-8">
<EssentialWorkshops title="WORKSHOPS TO GET STARTED" ctaLabel="Read more articles >" /> <EssentialWorkshops title={$t("post.workshops-title")} ctaLabel={`${$t('post.article-more-cta')} >`} />
</section> </section>
<PageHeader coverUrl="/images/headers/header_bg_1.png">OPEN-SOURCE NEWS</PageHeader> <PageHeader coverUrl="/images/headers/header_bg_1.png">{$t("home.os-news-title")}</PageHeader>
<section class="mt-8"> <section class="mt-8">
<News /> <News />
</section> </section>

View file

@ -1,18 +1,22 @@
<script> <script>
import '$appcss'; import '$appcss';
import { t } from '$libs/translations';
import PageHeader from '$components/page-header/page-header.svelte'; import PageHeader from '$components/page-header/page-header.svelte';
import FeaturedCourses from '$components/featured-courses/featured-courses.svelte'; import FeaturedCourses from '$components/featured-courses/featured-courses.svelte';
import EssentialWorkshops from '$components/essential-workshops/essential-workshops.svelte'; import EssentialWorkshops from '$components/essential-workshops/essential-workshops.svelte';
</script> </script>
<div> <div>
<PageHeader>Documentation</PageHeader> <PageHeader>{$t('documentation.title').toUpperCase()}</PageHeader>
<section> <section>
<FeaturedCourses /> <FeaturedCourses />
</section> </section>
<section class="mt-8"> <section class="mt-8">
<EssentialWorkshops /> <EssentialWorkshops
title={$t('documentation.workshops').toUpperCase()}
ctaLabel={$t("view-all")}
/>
</section> </section>
</div> </div>

View file

@ -3,6 +3,7 @@
import type { AirtablePost } from "../types"; import type { AirtablePost } from "../types";
export let linkTarget = ""; export let linkTarget = "";
export let readMoreCta = "read more";
export let posts: AirtablePost[] = []; export let posts: AirtablePost[] = [];
</script> </script>
@ -17,7 +18,7 @@
<h1 class="text-xl text-primary">{article.title}</h1> <h1 class="text-xl text-primary">{article.title}</h1>
<p class="my-4 text-sm line-clamp-4">{article.short_description}</p> <p class="my-4 text-sm line-clamp-4">{article.short_description}</p>
<a href={article.link} target={linkTarget} class="text-sm text-primary underline" <a href={article.link} target={linkTarget} class="text-sm text-primary underline"
>Read more ...</a >{readMoreCta} ...</a
> >
</section> </section>
</article> </article>

View file

@ -19,6 +19,8 @@
"url": "https://github.com/teaxyz/gui.git" "url": "https://github.com/teaxyz/gui.git"
}, },
"dependencies": { "dependencies": {
"@crowdin/ota-client": "^0.7.0",
"lodash": "^4.17.21",
"yaml": "^2.2.1" "yaml": "^2.2.1"
} }
} }

View file

@ -4,12 +4,17 @@ importers:
.: .:
specifiers: specifiers:
'@crowdin/ota-client': ^0.7.0
lodash: ^4.17.21
yaml: ^2.2.1 yaml: ^2.2.1
dependencies: dependencies:
'@crowdin/ota-client': 0.7.0
lodash: 4.17.21
yaml: 2.2.1 yaml: 2.2.1
modules/desktop: modules/desktop:
specifiers: specifiers:
'@crowdin/ota-client': ^0.7.0
'@electron/asar': ^3.2.3 '@electron/asar': ^3.2.3
'@electron/notarize': ^1.2.3 '@electron/notarize': ^1.2.3
'@playwright/experimental-ct-svelte': ^1.29.2 '@playwright/experimental-ct-svelte': ^1.29.2
@ -77,6 +82,7 @@ importers:
vitest: ^0.28.3 vitest: ^0.28.3
yaml: ^2.2.1 yaml: ^2.2.1
dependencies: dependencies:
'@crowdin/ota-client': 0.7.0
'@electron/asar': 3.2.3 '@electron/asar': 3.2.3
'@sentry/electron': 4.3.0 '@sentry/electron': 4.3.0
'@sentry/svelte': 7.38.0_svelte@3.55.1 '@sentry/svelte': 7.38.0_svelte@3.55.1
@ -1682,6 +1688,15 @@ packages:
dev: true dev: true
optional: true optional: true
/@crowdin/ota-client/0.7.0:
resolution: {integrity: sha512-RNFnR2ter5dsFJlyQysT8jswDn/TBF/ALosiDRpaj2tcOlAk/amQOoqEMJrCdR46xWqMUNwz/hJ4YIlcN51kPQ==}
engines: {node: '>=12.9.0'}
dependencies:
axios: 0.25.0
transitivePeerDependencies:
- debug
dev: false
/@design-systems/utils/2.12.0: /@design-systems/utils/2.12.0:
resolution: {integrity: sha512-Y/d2Zzr+JJfN6u1gbuBUb1ufBuLMJJRZQk+dRmw8GaTpqKx5uf7cGUYGTwN02dIb3I+Tf+cW8jcGBTRiFxdYFg==} resolution: {integrity: sha512-Y/d2Zzr+JJfN6u1gbuBUb1ufBuLMJJRZQk+dRmw8GaTpqKx5uf7cGUYGTwN02dIb3I+Tf+cW8jcGBTRiFxdYFg==}
peerDependencies: peerDependencies:
@ -5098,6 +5113,14 @@ packages:
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
dev: true dev: true
/axios/0.25.0:
resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==}
dependencies:
follow-redirects: 1.15.2
transitivePeerDependencies:
- debug
dev: false
/axios/1.3.2: /axios/1.3.2:
resolution: {integrity: sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==} resolution: {integrity: sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==}
dependencies: dependencies: