mirror of
https://github.com/sergeyyarkov/yarkov.tech.git
synced 2026-10-11 18:39:14 +03:00
translate pages
This commit is contained in:
parent
cb0ae84515
commit
c311050b65
@ -1,5 +1,9 @@
|
||||
---
|
||||
import Button from "@components/Button.astro";
|
||||
import UIString from "./UIString.astro";
|
||||
import { useTranslation } from "@i18n/utils";
|
||||
|
||||
const t = useTranslation(Astro);
|
||||
---
|
||||
|
||||
<form name="contact" method="post" netlify-honeypot="bot-field" data-netlify="true">
|
||||
@ -9,17 +13,44 @@ import Button from "@components/Button.astro";
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div>
|
||||
<input name="name" placeholder={"Имя"} type="text" maxlength="20" autocomplete="off" required />
|
||||
<input
|
||||
name="name"
|
||||
placeholder={t("input.nameField")}
|
||||
type="text"
|
||||
maxlength="20"
|
||||
autocomplete="off"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<input name="email" placeholder="example@email.com" autocomplete="off" type="email" required />
|
||||
<input
|
||||
name="email"
|
||||
placeholder="example@email.com"
|
||||
autocomplete="off"
|
||||
type="email"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<input name="subject" placeholder={"Тема"} type="text" autocomplete="off" required />
|
||||
<textarea name="message" placeholder={"Сообщение"} id="message" autocomplete="off" cols={30} rows={10} required
|
||||
></textarea>
|
||||
<input
|
||||
name="subject"
|
||||
placeholder={t("input.subjectField")}
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
required
|
||||
/>
|
||||
<textarea
|
||||
name="message"
|
||||
placeholder={t("input.messageField")}
|
||||
id="message"
|
||||
autocomplete="off"
|
||||
cols={30}
|
||||
rows={10}
|
||||
required></textarea>
|
||||
<div class="footer">
|
||||
<Button type="submit">{"Отправить"}</Button>
|
||||
<Button type="submit">
|
||||
<UIString key={"btn.submit"} />
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@ -1,59 +1,47 @@
|
||||
---
|
||||
import { SITE_METADATA } from "@root/constants";
|
||||
import { Icon } from "astro-icon";
|
||||
import TranslatedLink from "./TranslatedLink.astro";
|
||||
import UIString from "./UIString.astro";
|
||||
const date = new Date();
|
||||
---
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://astro.build/" target="_blank">Astro</a>
|
||||
<Icon name="astro" width="20" height="20" />
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.netlify.com/" target="_blank">Netlify</a>
|
||||
<Icon name="netlify" width="20" height="20" />
|
||||
</li>
|
||||
<li>
|
||||
<a href="/rss.xml" target="_blank">RSS</a>
|
||||
<div>
|
||||
<i>
|
||||
Разработка: <TranslatedLink to="/contacts">{SITE_METADATA.author}</TranslatedLink>
|
||||
© {date.getFullYear()}
|
||||
</i>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/rss.xml" target="_blank"><UIString key={"rss.feed"} /></a>
|
||||
<span>
|
||||
<Icon name="rss" width="20" height="20" />
|
||||
</li>
|
||||
</ul>
|
||||
<small>© Sergey Yarkov, {date.getFullYear()}</small>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<style lang="scss">
|
||||
footer {
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
margin-top: 5rem;
|
||||
color: var(--color-gray-200);
|
||||
font-size: var(--font-size-sm);
|
||||
& .container {
|
||||
padding: 25px 0 10px 0;
|
||||
padding: 15px 0 15px 0;
|
||||
border-top: 1px solid var(--border-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
row-gap: 15px;
|
||||
}
|
||||
& ul {
|
||||
justify-content: space-between;
|
||||
& div:last-child {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: 25px;
|
||||
& li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: 7px;
|
||||
& a {
|
||||
color: var(--font-color);
|
||||
font-size: var(--font-size-sm);
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
& small {
|
||||
text-align: center;
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -23,7 +23,7 @@ import TranslatedLink from "@components/TranslatedLink.astro";
|
||||
<TranslatedLink
|
||||
itemprop={"url"}
|
||||
to={link.url}
|
||||
class:list={[{ active: link.url === Astro.url.pathname }]}
|
||||
class:list={[{ active: Astro.url.pathname.includes(link.url) }]}
|
||||
>
|
||||
<UIString key={link.key} />
|
||||
</TranslatedLink>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
---
|
||||
import { Icon } from "astro-icon";
|
||||
// import TranslatedLink from "@components/TranslatedLink";
|
||||
import TranslatedLink from "@components/TranslatedLink.astro";
|
||||
|
||||
export interface Props {
|
||||
icon: string;
|
||||
@ -12,9 +12,9 @@ const { icon, href } = Astro.props as Props;
|
||||
|
||||
<div>
|
||||
<Icon name={icon} width="18" height="18" />
|
||||
<a href={href}>
|
||||
<TranslatedLink to={href}>
|
||||
<slot />
|
||||
</a>
|
||||
</TranslatedLink>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@ -16,7 +16,8 @@ export default {
|
||||
/* Page descriptions */
|
||||
"pageDescription.articles":
|
||||
"Technical articles, tutorials and various reference materials related to IT topics can be found here.",
|
||||
"pageDescription.projects": "A few of my main projects that have been developed and published in open access.",
|
||||
"pageDescription.projects":
|
||||
"A few of my main projects that have been developed and published in open access.",
|
||||
"pageDescription.contacts": "Use the feedback form or write to me on social networks.",
|
||||
/* Navigation */
|
||||
"navigation.articles": "Articles",
|
||||
@ -52,4 +53,6 @@ export default {
|
||||
"form.contactError": "An error occurred while sending. Please try again later.",
|
||||
/* Error messages */
|
||||
"error.invalidEmail": "Fill in the field in the e-mail format.",
|
||||
/* Other */
|
||||
"rss.feed": "RSS Feed",
|
||||
};
|
||||
|
||||
@ -16,8 +16,10 @@ export default {
|
||||
/* Page descriptions */
|
||||
"pageDescription.articles":
|
||||
"Технические статьи, туториалы и различные справочные материалы которые связаны с IT тематикой находятся здесь.",
|
||||
"pageDescription.projects": "Несколько моих основных проектов которые были разработаны и выложены в открытый доступ.",
|
||||
"pageDescription.contacts": "Воспользуйтесь формой обратной связи или напишите мне в социальные сети.",
|
||||
"pageDescription.projects":
|
||||
"Несколько моих основных проектов которые были разработаны и выложены в открытый доступ.",
|
||||
"pageDescription.contacts":
|
||||
"Воспользуйтесь формой обратной связи или напишите мне в социальные сети.",
|
||||
/* Navigation */
|
||||
"navigation.articles": "Статьи",
|
||||
"navigation.projects": "Проекты",
|
||||
@ -52,4 +54,6 @@ export default {
|
||||
"form.contactError": "При отправке произошла ошибка. Повторите запрос позже.",
|
||||
/* Error messages */
|
||||
"error.invalidEmail": "Заполните поле в формате e-mail.",
|
||||
/* Other */
|
||||
"rss.feed": "RSS Лента",
|
||||
};
|
||||
|
||||
@ -2,13 +2,9 @@ import type { AstroGlobal } from "astro";
|
||||
import { DEFAULT_LANGUAGE, SUPPORTED_LANGUAGES } from "@root/constants";
|
||||
import languages from "./languages";
|
||||
|
||||
function transformExports<T>(modules: Record<string, { default: T }>): Record<string, string> {
|
||||
const translations: Record<string, T> = {};
|
||||
for (const [path, module] of Object.entries(modules)) {
|
||||
const [, lang] = path.split("/");
|
||||
translations[lang] = module.default;
|
||||
}
|
||||
return translations;
|
||||
export function useTranslation(Astro: Readonly<AstroGlobal>): (key: UIDictionaryKeys) => string {
|
||||
const pageLang = getLanguageFromURL(Astro.url.pathname);
|
||||
return (key: UIDictionaryKeys) => translate(key, pageLang);
|
||||
}
|
||||
|
||||
export function getLanguageKeys(): Array<string> {
|
||||
@ -27,19 +23,21 @@ export function removeLangFromURL(pathname: string): string {
|
||||
return pathname.split("/").slice(2).join("/");
|
||||
}
|
||||
|
||||
const translations = transformExports(import.meta.glob("./*/ui.ts", { eager: true }));
|
||||
function transformExports<T>(modules: Record<string, { default: T }>) {
|
||||
const translations: Record<string, T> = {};
|
||||
for (const [path, module] of Object.entries(modules)) {
|
||||
const [, lang] = path.split("/");
|
||||
translations[lang as LanguageKeys] = module.default;
|
||||
}
|
||||
return translations;
|
||||
}
|
||||
|
||||
const s = translations["ru"];
|
||||
const translations = transformExports<Record<string, UIDictionaryKeys>>(
|
||||
import.meta.glob("./*/ui.ts", { eager: true })
|
||||
);
|
||||
|
||||
function translate(key: UIDictionaryKeys, lang: LanguageKeys): string | undefined {
|
||||
function translate(key: UIDictionaryKeys, lang: LanguageKeys): string {
|
||||
const value = translations[lang]?.[key] || translations[DEFAULT_LANGUAGE][key];
|
||||
if (value === undefined) console.log(`Cannot find any string for translation key "${key}".`);
|
||||
return value;
|
||||
}
|
||||
|
||||
export function useTranslation(
|
||||
Astro: Readonly<AstroGlobal>
|
||||
): (key: UIDictionaryKeys) => string | undefined {
|
||||
const pageLang = getLanguageFromURL(Astro.url.pathname);
|
||||
return (key: UIDictionaryKeys) => translate(key, pageLang);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
---
|
||||
import { getCollection, getEntryBySlug } from "astro:content";
|
||||
import { getLanguageFromURL } from "@i18n/utils";
|
||||
import { getLanguageFromURL, useTranslation } from "@i18n/utils";
|
||||
import PageLayout from "@layouts/default.astro";
|
||||
import PageHeading from "@components/PageHeading.astro";
|
||||
import SkillsList from "@components/SkillsList.astro";
|
||||
@ -11,12 +11,11 @@ const pageLang = getLanguageFromURL(Astro.url.pathname);
|
||||
const skills = await getCollection("skills", (e) => e.id.startsWith(`${pageLang}/`));
|
||||
const about = await getEntryBySlug("authors", `${pageLang}/сергей-ярков`);
|
||||
const data = await about?.render();
|
||||
|
||||
// const t = useTranslation(Astro);
|
||||
const t = useTranslation(Astro);
|
||||
---
|
||||
|
||||
<PageLayout noIndex lang={pageLang} title={"Обо мне"}>
|
||||
<PageHeading heading={"Обо мне"} />
|
||||
<PageLayout noIndex lang={pageLang} title={t("pageTitle.about")}>
|
||||
<PageHeading heading={t("pageTitle.about")} />
|
||||
<section>
|
||||
<ArticleContent>
|
||||
{data && <data.Content />}
|
||||
|
||||
@ -1,29 +1,20 @@
|
||||
---
|
||||
import PageLayout from "@layouts/default.astro";
|
||||
import PageHeading from "@components/PageHeading.astro";
|
||||
// import ArticlesList from "@components/ArticlesList";
|
||||
// import * as utils from "@utils/articles";
|
||||
import { getLanguageFromURL } from "@i18n/utils";
|
||||
// import { useTranslation } from "@i18n/utils";
|
||||
// import * as API from "@root/lib/api";
|
||||
// const t = useTranslation(Astro);
|
||||
// const data = API.fetchTranslatedArticles(Astro);
|
||||
// const tags = new Set(data.map((article) => article.frontmatter.tags).flat());
|
||||
const lang = getLanguageFromURL(Astro.url.pathname);
|
||||
// const articles = utils.transformArticles(data);
|
||||
import { useTranslation, getLanguageFromURL } from "@i18n/utils";
|
||||
|
||||
const t = useTranslation(Astro);
|
||||
const pageLang = getLanguageFromURL(Astro.url.pathname);
|
||||
const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
|
||||
---
|
||||
|
||||
<PageLayout
|
||||
lang={lang}
|
||||
title={"Статьи"}
|
||||
description={"Технические статьи, туториалы и различные справочные материалы которые связаны с IT тематикой находятся здесь."}
|
||||
lang={pageLang}
|
||||
title={t("pageTitle.articles")}
|
||||
description={t("pageDescription.articles")}
|
||||
canonicalUrl={canonicalUrl.href}
|
||||
>
|
||||
<PageHeading
|
||||
heading={"Статьи"}
|
||||
description={"Технические статьи, туториалы и различные справочные материалы которые связаны с IT тематикой находятся здесь."}
|
||||
/>
|
||||
<PageHeading heading={t("pageTitle.articles")} description={t("pageDescription.articles")} />
|
||||
<section>
|
||||
...
|
||||
<!-- <ArticlesList
|
||||
|
||||
@ -3,21 +3,18 @@ import PageLayout from "@layouts/default.astro";
|
||||
import PageHeading from "@components/PageHeading.astro";
|
||||
import ContactForm from "@components/ContactForm.astro";
|
||||
import ContactsList from "@components/ContactsList.astro";
|
||||
import { getLanguageFromURL } from "@i18n/utils";
|
||||
// const t = useTranslation(Astro);
|
||||
import { getLanguageFromURL, useTranslation } from "@i18n/utils";
|
||||
const t = useTranslation(Astro);
|
||||
const lang = getLanguageFromURL(Astro.url.pathname);
|
||||
---
|
||||
|
||||
<PageLayout
|
||||
noIndex
|
||||
lang={lang}
|
||||
title={"Контакты"}
|
||||
description={"Воспользуйтесь формой обратной связи или напишите мне в социальные сети."}
|
||||
title={t("pageTitle.contacts")}
|
||||
description={t("pageDescription.contacts")}
|
||||
>
|
||||
<PageHeading
|
||||
heading={"Контакты"}
|
||||
description={"Воспользуйтесь формой обратной связи или напишите мне в социальные сети."}
|
||||
/>
|
||||
<PageHeading heading={t("pageTitle.contacts")} description={t("pageDescription.contacts")} />
|
||||
<section>
|
||||
<ContactForm />
|
||||
<ContactsList />
|
||||
|
||||
@ -4,9 +4,9 @@ import PageLayout from "@layouts/default.astro";
|
||||
import ProjectsList from "@components/ProjectsList.astro";
|
||||
import ProjectItem from "@components/ProjectItem.astro";
|
||||
import PageHeading from "@components/PageHeading.astro";
|
||||
import { getLanguageFromURL } from "@i18n/utils";
|
||||
import { getLanguageFromURL, useTranslation } from "@i18n/utils";
|
||||
|
||||
// const t = useTranslation(Astro);
|
||||
const t = useTranslation(Astro);
|
||||
const pageLang = getLanguageFromURL(Astro.url.pathname);
|
||||
const projects = (await getCollection("projects", (e) => e.slug.startsWith(`${pageLang}/`))).sort(
|
||||
(a, b) => b.data.year - a.data.year
|
||||
@ -16,13 +16,10 @@ const projects = (await getCollection("projects", (e) => e.slug.startsWith(`${pa
|
||||
<PageLayout
|
||||
noIndex
|
||||
lang={pageLang}
|
||||
title={"Проекты"}
|
||||
description={"Несколько моих основных проектов которые были разработаны и выложены в открытый доступ."}
|
||||
title={t("pageTitle.projects")}
|
||||
description={t("pageDescription.projects")}
|
||||
>
|
||||
<PageHeading
|
||||
heading={"Проекты"}
|
||||
description={"Несколько моих основных проектов которые были разработаны и выложены в открытый доступ."}
|
||||
/>
|
||||
<PageHeading heading={t("pageTitle.projects")} description={t("pageDescription.projects")} />
|
||||
<section>
|
||||
<ProjectsList>
|
||||
{projects.map((project) => <ProjectItem data={project.data} />)}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user