mirror of
https://github.com/ivabus/gui
synced 2025-04-23 05:57:11 +03:00
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:
parent
d3fa446c8c
commit
32e53ee1ad
28 changed files with 260 additions and 93 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@ yarn-error.log
|
|||
.DS_Store
|
||||
.pnpm-store
|
||||
target
|
||||
copy.json
|
|
@ -88,6 +88,7 @@ pnpm dev
|
|||
|
||||
```sh
|
||||
pnpm install
|
||||
pnpm --filter desktop exec pnpm predist
|
||||
pnpm --filter desktop exec pnpm dist
|
||||
```
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
const { notarize } = require("@electron/notarize");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const otaClient = require("@crowdin/ota-client");
|
||||
const _ = require("lodash");
|
||||
|
||||
module.exports = {
|
||||
appId: "xyz.tea.gui",
|
||||
|
@ -17,8 +19,6 @@ module.exports = {
|
|||
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) => {
|
||||
if (process.platform !== "darwin") {
|
||||
return;
|
||||
|
@ -51,14 +51,6 @@ module.exports = {
|
|||
|
||||
console.log(`Done notarizing`);
|
||||
},
|
||||
|
||||
// publish: {
|
||||
// provider: "github",
|
||||
// repo: "gui",
|
||||
// owner: "teaxyz",
|
||||
// releaseType: "release"
|
||||
// },
|
||||
|
||||
// this determines the configuration of the auto-update feature
|
||||
publish: {
|
||||
provider: "generic",
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"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",
|
||||
"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",
|
||||
"package": "pnpm build && electron-builder --config electron-builder.config.cjs",
|
||||
"dev:package": "pnpm build && electron-builder --config electron-builder.config.cjs --dir",
|
||||
|
@ -72,6 +73,7 @@
|
|||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@crowdin/ota-client": "^0.7.0",
|
||||
"@electron/asar": "^3.2.3",
|
||||
"@sentry/electron": "^4.3.0",
|
||||
"@sentry/svelte": "^7.38.0",
|
||||
|
|
36
modules/desktop/scripts/prepare-crowdin-import.cjs
Normal file
36
modules/desktop/scripts/prepare-crowdin-import.cjs
Normal 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");
|
39
modules/desktop/scripts/update-translations.cjs
Normal file
39
modules/desktop/scripts/update-translations.cjs
Normal 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();
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import type { AirtablePost } from '@tea/ui/types';
|
||||
import Posts from '@tea/ui/posts/posts.svelte';
|
||||
import PanelHeader from '@tea/ui/panel-header/panel-header.svelte';
|
||||
|
@ -16,7 +17,7 @@
|
|||
|
||||
<PanelHeader {title} {ctaLabel} ctaLink="/" />
|
||||
{#if courses.length}
|
||||
<Posts posts={courses} linkTarget="_blank" />
|
||||
<Posts posts={courses} readMoreCta={$t("post.read-more-cta")} linkTarget="_blank" />
|
||||
{:else}
|
||||
<section class="border-gray h-64 border bg-black p-4">
|
||||
<Preloader />
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import { postsStore } from '$libs/stores';
|
||||
import type { Course } from '$libs/types';
|
||||
|
||||
|
@ -20,7 +21,7 @@
|
|||
</script>
|
||||
|
||||
<Gallery
|
||||
title="FEATURED COURSES"
|
||||
title={$t("documentation.featured-courses-title").toUpperCase()}
|
||||
items={courses.map((course) => ({
|
||||
title: course.title,
|
||||
subTitle: course.sub_title,
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
<script lang="ts">
|
||||
import { t } from '$libs/translations';
|
||||
import Button from '@tea/ui/button/button.svelte';
|
||||
import * as pub from '$env/static/public';
|
||||
</script>
|
||||
|
||||
<footer class="font-machina relative h-auto w-full bg-black">
|
||||
<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">
|
||||
<div class="border-gray flex-grow border border-l-0 border-r-0">
|
||||
<a href="/">
|
||||
<Button>
|
||||
<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>→</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
@ -21,7 +22,7 @@
|
|||
<a href="/">
|
||||
<Button>
|
||||
<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>→</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
@ -31,7 +32,7 @@
|
|||
<a href="https://tea.xyz" target="_blank" rel="noreferrer">
|
||||
<Button>
|
||||
<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>→</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
@ -48,7 +49,7 @@
|
|||
rel="noreferrer"
|
||||
class="hover:text-white"
|
||||
>
|
||||
TERMS & SERVICES
|
||||
{$t("footer.terms-services").toUpperCase()}
|
||||
</a>
|
||||
<a
|
||||
href="https://tea.xyz/privacy-policy/"
|
||||
|
@ -56,7 +57,7 @@
|
|||
rel="noreferrer"
|
||||
class="hover:text-white"
|
||||
>
|
||||
PRIVACY POLICY
|
||||
{$t("footer.privacy-policy").toUpperCase()}
|
||||
</a>
|
||||
</div>
|
||||
{#if pub.PUBLIC_VERSION}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import type { GUIPackage } from '$libs/types';
|
||||
import { PackageStates } from '$libs/types';
|
||||
import PanelHeader from '@tea/ui/panel-header/panel-header.svelte';
|
||||
|
@ -13,7 +14,7 @@
|
|||
});
|
||||
</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">
|
||||
{#if packages.length > 0}
|
||||
|
@ -21,7 +22,7 @@
|
|||
<div class="border-gray border border-t-0 border-l-0 p-4">
|
||||
<MiniPackageCard
|
||||
{pkg}
|
||||
ctaLabel="DETAILS"
|
||||
ctaLabel={$t("package.details").toUpperCase()}
|
||||
onClickCTA={async () => {
|
||||
console.log('do something with:', pkg.full_name);
|
||||
}}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import { postsStore } from '$libs/stores';
|
||||
import type { AirtablePost } from '@tea/ui/types';
|
||||
import Posts from '@tea/ui/posts/posts.svelte';
|
||||
|
@ -11,7 +12,7 @@
|
|||
postsStore.subscribeByTag('news', (posts) => (news = posts));
|
||||
</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}
|
||||
<Posts posts={news} linkTarget="_blank" />
|
||||
{:else}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import type { GUIPackage } from '$libs/types';
|
||||
import { PackageStates } from '$libs/types';
|
||||
import Preloader from '@tea/ui/Preloader/Preloader.svelte';
|
||||
|
@ -16,10 +17,10 @@
|
|||
|
||||
const getCTALabel = (state: PackageStates): string => {
|
||||
return {
|
||||
[PackageStates.AVAILABLE]: 'INSTALL',
|
||||
[PackageStates.INSTALLED]: 'INSTALLED',
|
||||
[PackageStates.INSTALLING]: 'INSTALLING',
|
||||
[PackageStates.UNINSTALLED]: 'RE-INSTALL'
|
||||
[PackageStates.AVAILABLE]: $t("package.install-label").toUpperCase(),
|
||||
[PackageStates.INSTALLED]: $t("package.installed-label").toUpperCase(),
|
||||
[PackageStates.INSTALLING]: $t("package.installing-label").toUpperCase(),
|
||||
[PackageStates.UNINSTALLED]: $t("package.reinstall-label").toUpperCase(),
|
||||
}[state];
|
||||
};
|
||||
|
||||
|
@ -32,7 +33,7 @@
|
|||
|
||||
<header class="border-gray text-primary flex items-center justify-between border bg-black p-4">
|
||||
<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>
|
||||
<ul class="grid grid-cols-3 bg-black">
|
||||
{#if packages.length > 0}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import { packagesStore } from '$libs/stores';
|
||||
import SortingButtons from './sorting-buttons.svelte';
|
||||
import type { GUIPackage } from '$libs/types';
|
||||
|
@ -51,10 +52,10 @@
|
|||
|
||||
const getCTALabel = (state: PackageStates): string => {
|
||||
return {
|
||||
[PackageStates.AVAILABLE]: 'INSTALL',
|
||||
[PackageStates.INSTALLED]: 'INSTALLED',
|
||||
[PackageStates.INSTALLING]: 'INSTALLING',
|
||||
[PackageStates.UNINSTALLED]: 'RE-INSTALL'
|
||||
[PackageStates.AVAILABLE]: $t("package.install-label").toUpperCase(),
|
||||
[PackageStates.INSTALLED]: $t("package.installed-label").toUpperCase(),
|
||||
[PackageStates.INSTALLING]: $t("package.installing-label").toUpperCase(),
|
||||
[PackageStates.UNINSTALLED]: $t("package.reinstall-label").toUpperCase(),
|
||||
}[state];
|
||||
};
|
||||
|
||||
|
@ -64,7 +65,7 @@
|
|||
<div class="border-gray border bg-black">
|
||||
<section class="flex items-center justify-between">
|
||||
<div>
|
||||
<SearchInput size="medium" {onSearch} />
|
||||
<SearchInput size="medium" {onSearch} placeholder={`${$t("search")}_`} />
|
||||
</div>
|
||||
<div class="pr-4">
|
||||
<section class="border-gray h-12 w-48 border">
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
|
||||
export let onSort: (opt: string, dir: 'asc' | 'desc') => void;
|
||||
|
||||
|
@ -8,6 +9,11 @@
|
|||
|
||||
const sortOptions = ['popularity', 'most recent'];
|
||||
|
||||
const optionLabels = {
|
||||
[sortOptions[0]]: $t("sorting.popularity"),
|
||||
[sortOptions[1]]: $t("sorting.most-recent")
|
||||
}
|
||||
|
||||
const setSortBy = (opt: string) => {
|
||||
sortBy = opt;
|
||||
if (onSort) {
|
||||
|
@ -22,7 +28,7 @@
|
|||
|
||||
<section class="sorting-container font-machina bg-black text-white">
|
||||
<div class="dropdown">
|
||||
<div class="dropdown-title">SORT ORDER</div>
|
||||
<div class="dropdown-title">{$t("sorting.label")}</div>
|
||||
<ul class="dropdown-content column flex">
|
||||
{#each sortOptions as option}
|
||||
<li class="flex items-center">
|
||||
|
@ -30,7 +36,7 @@
|
|||
class={`sort-btn uppercase ${sortBy === option ? 'active' : ''}`}
|
||||
on:click={() => setSortBy(option)}
|
||||
>
|
||||
{option}
|
||||
{optionLabels[option]}
|
||||
</button>
|
||||
<div class="direction-arrows">
|
||||
<button
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { searchStore } from '$libs/stores';
|
||||
import { t } from '$libs/translations';
|
||||
import type { GUIPackage } from '$libs/types';
|
||||
import Preloader from '@tea/ui/Preloader/Preloader.svelte';
|
||||
import PackageCard from '@tea/ui/package-card/package-card.svelte';
|
||||
|
@ -40,10 +41,10 @@
|
|||
|
||||
const getCTALabel = (state: PackageStates): string => {
|
||||
return {
|
||||
[PackageStates.AVAILABLE]: 'INSTALL',
|
||||
[PackageStates.INSTALLED]: 'INSTALLED',
|
||||
[PackageStates.INSTALLING]: 'INSTALLING',
|
||||
[PackageStates.UNINSTALLED]: 'RE-INSTALL'
|
||||
[PackageStates.AVAILABLE]: $t("package.install-label").toUpperCase(),
|
||||
[PackageStates.INSTALLED]: $t("package.installed-label").toUpperCase(),
|
||||
[PackageStates.INSTALLING]: $t("package.installing-label").toUpperCase(),
|
||||
[PackageStates.UNINSTALLED]: $t("package.reinstall-label").toUpperCase(),
|
||||
}[state];
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import type { GUIPackage } from '$libs/types';
|
||||
import type { Package } from '@tea/ui/types';
|
||||
import { PackageStates } from '$libs/types';
|
||||
|
@ -15,10 +16,10 @@
|
|||
|
||||
const getCTALabel = (state: PackageStates): string => {
|
||||
return {
|
||||
[PackageStates.AVAILABLE]: 'INSTALL',
|
||||
[PackageStates.INSTALLED]: 'INSTALLED',
|
||||
[PackageStates.INSTALLING]: 'INSTALLING',
|
||||
[PackageStates.UNINSTALLED]: 'RE-INSTALL'
|
||||
[PackageStates.AVAILABLE]: $t("package.install-label").toUpperCase(),
|
||||
[PackageStates.INSTALLED]: $t("package.installed-label").toUpperCase(),
|
||||
[PackageStates.INSTALLING]: $t("package.installing-label").toUpperCase(),
|
||||
[PackageStates.UNINSTALLED]: $t("package.reinstall-label").toUpperCase(),
|
||||
}[state];
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import { searchStore } from '$libs/stores';
|
||||
import SearchInput from '@tea/ui/search-input/search-input.svelte';
|
||||
import { navStore } from '$libs/stores';
|
||||
import { t } from '$libs/translations';
|
||||
|
||||
import ProfileNavButton from './profile-nav-button.svelte';
|
||||
import SelectLang from '$components/select-lang/select-lang.svelte';
|
||||
|
@ -31,7 +32,7 @@
|
|||
<SearchInput
|
||||
class="flex-grow border border-none py-4"
|
||||
size="small"
|
||||
placeholder="search the tea store"
|
||||
placeholder={$t("store-search-placeholder")}
|
||||
{onSearch}
|
||||
/>
|
||||
<ul class="text-gray flex gap-4 pr-4 pt-2 align-middle">
|
||||
|
@ -45,8 +46,8 @@
|
|||
<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"
|
||||
>
|
||||
<a href="/cli" class={currentPath === '/cli' ? 'active' : ''}>install teaCli</a>
|
||||
<a href="/documentation" class={currentPath === '/documentation' ? 'active' : ''}>documentation</a
|
||||
<a href="/cli" class={currentPath === '/cli' ? 'active' : ''}>{$t('cli.install')}</a>
|
||||
<a href="/documentation" class={currentPath === '/documentation' ? 'active' : ''}>{$t('documentation.title')}</a
|
||||
>
|
||||
<a href="/packages" class={currentPath === '/packages' ? 'active' : ''}>packages</a>
|
||||
<a href="https://github.com/teaxyz" target="_blank" rel="noreferrer">
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<!-- home / discover / welcome page -->
|
||||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import ListAction from '@tea/ui/list-action/list-action.svelte';
|
||||
import type { ListActionItem } from '@tea/ui/types';
|
||||
import { packagesStore } from '$libs/stores';
|
||||
|
@ -13,7 +14,7 @@
|
|||
.map((pkg) => ({
|
||||
title: pkg.full_name,
|
||||
sub_title: pkg.version,
|
||||
action_label: 'INSTALL',
|
||||
action_label: $t("package.install-label").toUpperCase(),
|
||||
image_url: pkg.thumb_image_url,
|
||||
detail_url: `/packages/${pkg.slug}`
|
||||
}));
|
||||
|
@ -25,8 +26,8 @@
|
|||
</script>
|
||||
|
||||
<ListAction
|
||||
title="Top packages this week"
|
||||
mainCtaTitle="VIEW ALL SCRIPTS"
|
||||
title={$t("package.top-list-title")}
|
||||
mainCtaTitle={$t("package.view-all-cta").toUpperCase()}
|
||||
items={items}
|
||||
onSelectItem={onSelectPackage}
|
||||
/>
|
|
@ -1,47 +1,49 @@
|
|||
<!-- home / discover / welcome page -->
|
||||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import type { ListActionItem } from '@tea/ui/types';
|
||||
import ListAction from '@tea/ui/list-action/list-action.svelte';
|
||||
|
||||
const action_label = $t("script.use-label");
|
||||
const items: ListActionItem[] = [
|
||||
{
|
||||
title: 'Script A',
|
||||
sub_title: 'v 0.0.1',
|
||||
image_url: '/images/bored-ape.png',
|
||||
action_label: 'USE'
|
||||
action_label
|
||||
},
|
||||
{
|
||||
title: 'Script B',
|
||||
sub_title: 'v 0.1.1',
|
||||
image_url: '/images/bored-ape.png',
|
||||
action_label: 'USE'
|
||||
action_label
|
||||
},
|
||||
{
|
||||
title: 'Script C',
|
||||
sub_title: 'v 2.0.1',
|
||||
image_url: '/images/bored-ape.png',
|
||||
action_label: 'USE'
|
||||
action_label
|
||||
},
|
||||
{
|
||||
title: 'Script D',
|
||||
sub_title: 'v 0.1.1',
|
||||
image_url: '/images/bored-ape.png',
|
||||
action_label: 'USE'
|
||||
action_label
|
||||
},
|
||||
{
|
||||
title: 'Script E',
|
||||
sub_title: 'v 0.1.1',
|
||||
image_url: '/images/bored-ape.png',
|
||||
action_label: 'USE'
|
||||
action_label
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
|
||||
<ListAction
|
||||
title="Top scripts this week"
|
||||
mainCtaTitle="VIEW ALL SCRIPTS"
|
||||
title={$t("script.top-list-title")}
|
||||
mainCtaTitle={$t("script.view-all-cta").toUpperCase()}
|
||||
items={items}
|
||||
onSelectItem={async (script) => {
|
||||
console.log(script)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import i18n from "sveltekit-i18n";
|
||||
import translations from "./translations";
|
||||
import translations from "./translations.json";
|
||||
|
||||
/** @type {import('sveltekit-i18n').Config} */
|
||||
const config = {
|
||||
initLocale: "en",
|
||||
fallbackLocale: "en",
|
||||
translations
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"en": "English",
|
||||
"cs": "Česky"
|
||||
}
|
65
modules/desktop/src/libs/translations/translations.json
Normal file
65
modules/desktop/src/libs/translations/translations.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import lang from "./lang.json";
|
||||
|
||||
export default {
|
||||
en: {
|
||||
lang,
|
||||
cli: {
|
||||
install: "install tea"
|
||||
}
|
||||
},
|
||||
cs: {
|
||||
lang,
|
||||
cli: {
|
||||
install: "nainstalovat cli"
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,6 +1,7 @@
|
|||
<!-- home / discover / welcome page -->
|
||||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import PageHeader from '$components/page-header/page-header.svelte';
|
||||
import EssentialWorkshops from '$components/essential-workshops/essential-workshops.svelte';
|
||||
import Packages from '$components/packages/packages.svelte';
|
||||
|
@ -12,40 +13,40 @@
|
|||
</script>
|
||||
|
||||
<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">
|
||||
<Packages title="FOUNDATION ESSENTIALS" category="foundation_essentials" />
|
||||
<Packages title={$t("package.foundation-essentials-title")} category="foundation_essentials" />
|
||||
</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">
|
||||
<div>
|
||||
<HeaderCard
|
||||
title="Browse Packages"
|
||||
title={$t("package.browse-cta")}
|
||||
imgUrl="/images/bored-ape.png"
|
||||
ctaUrl="/packages"
|
||||
ctaLabel="Browse packages >"
|
||||
articleTitle="What are packages?"
|
||||
description="Collections of files aggregated to form larger frameworks & functions. Think Python or Node.js."
|
||||
ctaLabel={`${$t("package.browse-cta")} >`}
|
||||
articleTitle={$t("package.what-title")}
|
||||
description={$t("package.short-description")}
|
||||
/>
|
||||
<TopPackages />
|
||||
</div>
|
||||
<div>
|
||||
<HeaderCard
|
||||
title="Browse Scripts"
|
||||
title={$t("script.browse-cta")}
|
||||
imgUrl="/images/bored-ape.png"
|
||||
ctaUrl="/packages"
|
||||
ctaLabel="Browse scripts >"
|
||||
articleTitle="What are scripts?"
|
||||
description="Invisible applications that chain packages together in order to perform cool actions on your computer."
|
||||
ctaLabel={`${$t("script.browse-cta")} >`}
|
||||
articleTitle={$t("script.what-title")}
|
||||
description={$t("script.short-description")}
|
||||
/>
|
||||
<TopScripts/>
|
||||
</div>
|
||||
</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">
|
||||
<EssentialWorkshops title="WORKSHOPS TO GET STARTED" ctaLabel="Read more articles >" />
|
||||
<EssentialWorkshops title={$t("post.workshops-title")} ctaLabel={`${$t('post.article-more-cta')} >`} />
|
||||
</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">
|
||||
<News />
|
||||
</section>
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
<script>
|
||||
import '$appcss';
|
||||
import { t } from '$libs/translations';
|
||||
import PageHeader from '$components/page-header/page-header.svelte';
|
||||
import FeaturedCourses from '$components/featured-courses/featured-courses.svelte';
|
||||
import EssentialWorkshops from '$components/essential-workshops/essential-workshops.svelte';
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<PageHeader>Documentation</PageHeader>
|
||||
<PageHeader>{$t('documentation.title').toUpperCase()}</PageHeader>
|
||||
|
||||
<section>
|
||||
<FeaturedCourses />
|
||||
</section>
|
||||
|
||||
<section class="mt-8">
|
||||
<EssentialWorkshops />
|
||||
<EssentialWorkshops
|
||||
title={$t('documentation.workshops').toUpperCase()}
|
||||
ctaLabel={$t("view-all")}
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import type { AirtablePost } from "../types";
|
||||
|
||||
export let linkTarget = "";
|
||||
export let readMoreCta = "read more";
|
||||
export let posts: AirtablePost[] = [];
|
||||
</script>
|
||||
|
||||
|
@ -17,7 +18,7 @@
|
|||
<h1 class="text-xl text-primary">{article.title}</h1>
|
||||
<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"
|
||||
>Read more ...</a
|
||||
>{readMoreCta} ...</a
|
||||
>
|
||||
</section>
|
||||
</article>
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
"url": "https://github.com/teaxyz/gui.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@crowdin/ota-client": "^0.7.0",
|
||||
"lodash": "^4.17.21",
|
||||
"yaml": "^2.2.1"
|
||||
}
|
||||
}
|
|
@ -4,12 +4,17 @@ importers:
|
|||
|
||||
.:
|
||||
specifiers:
|
||||
'@crowdin/ota-client': ^0.7.0
|
||||
lodash: ^4.17.21
|
||||
yaml: ^2.2.1
|
||||
dependencies:
|
||||
'@crowdin/ota-client': 0.7.0
|
||||
lodash: 4.17.21
|
||||
yaml: 2.2.1
|
||||
|
||||
modules/desktop:
|
||||
specifiers:
|
||||
'@crowdin/ota-client': ^0.7.0
|
||||
'@electron/asar': ^3.2.3
|
||||
'@electron/notarize': ^1.2.3
|
||||
'@playwright/experimental-ct-svelte': ^1.29.2
|
||||
|
@ -77,6 +82,7 @@ importers:
|
|||
vitest: ^0.28.3
|
||||
yaml: ^2.2.1
|
||||
dependencies:
|
||||
'@crowdin/ota-client': 0.7.0
|
||||
'@electron/asar': 3.2.3
|
||||
'@sentry/electron': 4.3.0
|
||||
'@sentry/svelte': 7.38.0_svelte@3.55.1
|
||||
|
@ -1682,6 +1688,15 @@ packages:
|
|||
dev: 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:
|
||||
resolution: {integrity: sha512-Y/d2Zzr+JJfN6u1gbuBUb1ufBuLMJJRZQk+dRmw8GaTpqKx5uf7cGUYGTwN02dIb3I+Tf+cW8jcGBTRiFxdYFg==}
|
||||
peerDependencies:
|
||||
|
@ -5098,6 +5113,14 @@ packages:
|
|||
engines: {node: '>= 0.4'}
|
||||
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:
|
||||
resolution: {integrity: sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==}
|
||||
dependencies:
|
||||
|
|
Loading…
Reference in a new issue