Compare commits
1
Commits
master
...
landing-site
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6733f37fa |
+22
-16
@@ -385,16 +385,19 @@ dotnet build Packaging\Installer\CursorLang.wixproj -p:SuppressValidation=false
|
||||
Partner Center не требует политику от приложения, которое не собирает данных, но
|
||||
страница, сказавшая это вслух, снимает вопрос у проверяющего.
|
||||
|
||||
Всё это — пять файлов в `site`, и ничего больше ниоткуда не подгружается: ни
|
||||
фреймворка, ни сборки, ни шрифта из сети.
|
||||
Ничего больше ниоткуда не подгружается: ни фреймворка, ни сборки, ни шрифта из
|
||||
сети.
|
||||
|
||||
| Файл | Что внутри |
|
||||
|---|---|
|
||||
| `index.html` | Разметка, оба языка сразу |
|
||||
| `index.html` | Английская страница — разметка, оба языка сразу |
|
||||
| `ru/index.html` | Та же разметка, впереди по умолчанию — русский |
|
||||
| `styles.css` | Все правила, включая палитру |
|
||||
| `boot.js` | Язык и тема прошлого визита — до первого кадра |
|
||||
| `main.js` | Остальное: переключатели, меню, демонстрация, предпросмотр |
|
||||
| `favicon.svg` | Та же тёмная плашка с «Aя», что и у иконки приложения |
|
||||
| `robots.txt` | Указывает краулерам на sitemap, ничего не запрещает |
|
||||
| `sitemap.xml` | Обе страницы, связанные между собой через `hreflang` |
|
||||
|
||||
`boot.js` вынесен отдельно и мал по одной причине: он должен отработать до
|
||||
разбора `body`. Он читает выбранное в прошлый раз и ставит это на элемент
|
||||
@@ -402,21 +405,24 @@ Partner Center не требует политику от приложения,
|
||||
на глазах исправлялся бы. `main.js` работает по разметке, которая к тому времени
|
||||
должна существовать, поэтому он отложенный.
|
||||
|
||||
Оба языка живут в разметке одновременно, а переключатель в углу выбирает один.
|
||||
Каждый переведённый кусок — это `<span lang="en">` рядом с `<span lang="ru">`, и
|
||||
тот, который не совпадает с языком на элементе `<html>`, скрывается правилом в
|
||||
две строки. С выключенными скриптами страница всё равно читается — по-английски.
|
||||
Оба языка живут в разметке каждой из страниц одновременно, а переключатель в
|
||||
углу выбирает один. Каждый переведённый кусок — это `<span lang="en">` рядом с
|
||||
`<span lang="ru">`, и тот, который не совпадает с языком на элементе `<html>`,
|
||||
скрывается правилом в две строки. С выключенными скриптами любая из страниц
|
||||
всё равно читается — на том языке, что у неё по умолчанию.
|
||||
|
||||
Выкладка сводится к копированию этих пяти файлов как есть. До неё адреса ждут
|
||||
две вещи.
|
||||
Английский и русский — это две страницы, а не одна с переключателем на клиенте,
|
||||
чтобы каждая могла ранжироваться в поиске сама по себе: `/` и `/ru/`, со
|
||||
ссылками `hreflang` друг на друга и в разметке, и в `sitemap.xml`, и у каждой —
|
||||
свой заголовок, описание и canonical. Клик по EN или RU — это настоящий переход
|
||||
между ними, а не перерисовка на месте, а `boot.js` отправляет посетителя,
|
||||
зашедшего впервые, на страницу под язык его браузера — но никогда не уводит с
|
||||
той из двух, на которую уже привела ссылка: иначе раздельное ранжирование
|
||||
пропадало бы для всех, кто пришёл именно так, включая краулеров.
|
||||
|
||||
Первая — страница в Store: обе кнопки загрузки сейчас не ссылки, а
|
||||
`<span class="btn disabled" role="link">`, потому что заглушка в `href` была бы
|
||||
относительным адресом и всякий, кто по ней пойдёт, получил бы 404. С адресом
|
||||
каждая возвращается в `<a class="btn" href="…">`, а примечание рядом уходит.
|
||||
|
||||
Вторая — адрес самого сайта: его ждут три тега, которых в шапке документа пока
|
||||
нет, — `og:image`, `og:url` и canonical.
|
||||
Выкладка сводится к копированию файлов как есть — на общие файлы (`/styles.css`
|
||||
и другие) ссылаются по абсолютному пути, так что `ru/index.html` обращается к
|
||||
той же копии, не заводя свою.
|
||||
|
||||
Поддержка — `support@alrakis.kz`: адрес стоит в разделе о данных, под кнопками
|
||||
загрузки и в подвале.
|
||||
|
||||
@@ -378,16 +378,19 @@ does, and a privacy policy saying that it collects nothing. Partner Center leave
|
||||
the policy optional for an app that gathers no data, but a page saying so out
|
||||
loud is what takes the question off the reviewer's desk.
|
||||
|
||||
The whole of it is five files in `site`, and nothing is fetched from anywhere
|
||||
else — no framework, no build step, no font from a network:
|
||||
Nothing is fetched from anywhere else — no framework, no build step, no font
|
||||
from a network:
|
||||
|
||||
| File | What is in it |
|
||||
|---|---|
|
||||
| `index.html` | The markup, both languages at once |
|
||||
| `index.html` | The English page — the markup, both languages at once |
|
||||
| `ru/index.html` | The same markup, Russian in front by default |
|
||||
| `styles.css` | Every rule, the palette included |
|
||||
| `boot.js` | The language and the theme of an earlier visit, before the first frame |
|
||||
| `main.js` | The rest: the switches, the menu, the demo, the preview |
|
||||
| `favicon.svg` | The same dark plate with "Aя" as the application icon |
|
||||
| `robots.txt` | Points crawlers at the sitemap, nothing disallowed |
|
||||
| `sitemap.xml` | Both pages, cross-linked by `hreflang` |
|
||||
|
||||
`boot.js` is small and separate for one reason: it has to run before the body is
|
||||
parsed. It reads what was chosen last time and puts it on the `<html>` element,
|
||||
@@ -395,22 +398,25 @@ and without it the first frame would be English in the system theme and correct
|
||||
itself a moment later, in plain sight. `main.js` works on markup that has to
|
||||
exist by then, so it is deferred instead.
|
||||
|
||||
Both languages live in the markup at once, and a switch in the corner picks one.
|
||||
Every translated piece is a `<span lang="en">` beside a `<span lang="ru">`, and
|
||||
whichever does not match the language on the `<html>` element is hidden by a rule
|
||||
of two lines. With the scripts switched off the page still reads, in English.
|
||||
Both languages live in the markup of each page at once, and a switch in the
|
||||
corner picks one. Every translated piece is a `<span lang="en">` beside a
|
||||
`<span lang="ru">`, and whichever does not match the language on the `<html>`
|
||||
element is hidden by a rule of two lines. With the scripts switched off either
|
||||
page still reads, in the language it defaults to.
|
||||
|
||||
Publishing means copying the five files as they are. Before that, two things are
|
||||
still waiting for an address.
|
||||
English and Russian are two pages rather than one page with a client-side
|
||||
switch, so that each can rank in search on its own: `/` and `/ru/`, with
|
||||
`hreflang` links between them in both the markup and `sitemap.xml`, and each
|
||||
carrying its own title, description and canonical address. Clicking EN or RU is
|
||||
a real navigation between the two rather than a rewrite in place, and `boot.js`
|
||||
sends a first-time visitor to the page matching their browser's language —
|
||||
but never away from whichever of the two a link already pointed them at, since
|
||||
that would undo the separate ranking for anyone arriving that way, crawlers
|
||||
included.
|
||||
|
||||
The Store listing is the first: the two download buttons are
|
||||
`<span class="btn disabled" role="link">` rather than links, because a
|
||||
placeholder in `href` would be a relative address and anything following it would
|
||||
land on a 404. The address turns each of them back into
|
||||
`<a class="btn" href="…">` and takes the note beside it away.
|
||||
|
||||
The address of the site itself is the second, wanted by three tags the head does
|
||||
not carry yet: `og:image`, `og:url` and the canonical link.
|
||||
Publishing means copying the files as they are — assets are referenced by an
|
||||
absolute path (`/styles.css` and so on) so `ru/index.html` reaches the same
|
||||
copy rather than needing one of its own.
|
||||
|
||||
Support goes to `support@alrakis.kz`: it stands in the privacy section, under the
|
||||
download buttons and in the footer.
|
||||
|
||||
+22
-8
@@ -2,25 +2,39 @@
|
||||
"use strict";
|
||||
|
||||
var root = document.documentElement;
|
||||
var lang = null;
|
||||
var onRuPage = location.pathname.indexOf("/ru/") === 0 || location.pathname === "/ru";
|
||||
var stored = null;
|
||||
var theme = null;
|
||||
|
||||
try {
|
||||
lang = localStorage.getItem("cursorlang.lang");
|
||||
stored = localStorage.getItem("cursorlang.lang");
|
||||
theme = localStorage.getItem("cursorlang.theme");
|
||||
} catch (error) {
|
||||
// Storage refused: what the markup says stands
|
||||
// Storage refused: what the URL says stands
|
||||
}
|
||||
|
||||
if (!lang && (navigator.language || "").toLowerCase().indexOf("ru") === 0) {
|
||||
lang = "ru";
|
||||
// A stored choice always wins, on either page.
|
||||
if (stored === "ru" && !onRuPage) {
|
||||
location.replace("/ru/" + location.search + location.hash);
|
||||
return;
|
||||
}
|
||||
if (stored === "en" && onRuPage) {
|
||||
location.replace("/" + location.search + location.hash);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lang === "ru" || lang === "en") {
|
||||
root.setAttribute("data-lang", lang);
|
||||
root.setAttribute("lang", lang);
|
||||
// No stored choice yet: send a browser set to Russian to the Russian page,
|
||||
// once. Never redirect away from a page a link already pointed at — a
|
||||
// shared /ru/ link, or a crawler fetching either URL directly, stands.
|
||||
if (!stored && !onRuPage && (navigator.language || "").toLowerCase().indexOf("ru") === 0) {
|
||||
location.replace("/ru/" + location.search + location.hash);
|
||||
return;
|
||||
}
|
||||
|
||||
var lang = onRuPage ? "ru" : "en";
|
||||
root.setAttribute("data-lang", lang);
|
||||
root.setAttribute("lang", lang);
|
||||
|
||||
if (theme === "dark" || theme === "light") {
|
||||
root.setAttribute("data-theme", theme);
|
||||
}
|
||||
|
||||
+38
-6
@@ -3,25 +3,57 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>CursorLang — the keyboard layout at your cursor</title>
|
||||
<title data-title-en="CursorLang — the keyboard layout at your cursor"
|
||||
data-title-ru="CursorLang — раскладка клавиатуры у курсора">CursorLang — the keyboard layout at your cursor</title>
|
||||
<meta name="description" content="A tiny Windows tray app that names the keyboard layout you have just switched to — beside the text caret, beside the mouse pointer, or at a fixed point on the screen. Free, offline, under 9 MB."
|
||||
data-content-en="A tiny Windows tray app that names the keyboard layout you have just switched to — beside the text caret, beside the mouse pointer, or at a fixed point on the screen. Free, offline, under 9 MB."
|
||||
data-content-ru="Небольшая программа в трее Windows, называющая раскладку, на которую вы только что переключились, — у текстового курсора, у указателя мыши или в выбранной точке экрана. Бесплатно, без доступа в сеть, меньше 9 МБ.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="CursorLang — the keyboard layout at your cursor">
|
||||
<meta property="og:description" content="Switch the layout and a small popup names it, right where you are typing. Free, offline, under 9 MB in the tray.">
|
||||
<meta property="og:url" content="https://cursor-lang.alrakis.kz/">
|
||||
<meta property="og:image" content="https://cursor-lang.alrakis.kz/favicon.svg">
|
||||
<meta property="og:image" content="https://cursor-lang.alrakis.kz/og-image.png">
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
<meta property="og:locale" content="en_US">
|
||||
<meta property="og:locale:alternate" content="ru_RU">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:title" content="CursorLang — the keyboard layout at your cursor">
|
||||
<meta name="twitter:description" content="A tiny Windows tray app that names the keyboard layout you have just switched to — beside the text caret, beside the mouse pointer, or at a fixed point on the screen. Free, offline, under 9 MB.">
|
||||
<meta name="twitter:image" content="https://cursor-lang.alrakis.kz/og-image.png">
|
||||
<link rel="canonical" href="https://cursor-lang.alrakis.kz/">
|
||||
<link rel="alternate" hreflang="en" href="https://cursor-lang.alrakis.kz/">
|
||||
<link rel="alternate" hreflang="ru" href="https://cursor-lang.alrakis.kz/ru/">
|
||||
<link rel="alternate" hreflang="x-default" href="https://cursor-lang.alrakis.kz/">
|
||||
<meta name="theme-color" content="#fbfbfd" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#0d0d10" media="(prefers-color-scheme: dark)">
|
||||
<link rel="icon" href="favicon.svg" type="image/svg+xml">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
||||
<link rel="stylesheet" href="/styles.css">
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
"name": "CursorLang",
|
||||
"url": "https://cursor-lang.alrakis.kz/",
|
||||
"image": "https://cursor-lang.alrakis.kz/og-image.png",
|
||||
"description": "A tiny Windows tray app that names the keyboard layout you have just switched to — beside the text caret, beside the mouse pointer, or at a fixed point on the screen. Free, offline, under 9 MB.",
|
||||
"applicationCategory": "UtilitiesApplication",
|
||||
"operatingSystem": "Windows 10 1809 and later, 64-bit",
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "0",
|
||||
"priceCurrency": "USD"
|
||||
},
|
||||
"downloadUrl": "https://apps.microsoft.com/detail/9nvpp6h49kpp",
|
||||
"inLanguage": ["en", "ru"]
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- boot.js runs before the body is parsed, so the language and the theme of an
|
||||
earlier visit are in place for the first frame; everything else waits for
|
||||
the markup it works on -->
|
||||
<script src="boot.js"></script>
|
||||
<script src="main.js" defer></script>
|
||||
<script src="/boot.js"></script>
|
||||
<script src="/main.js" defer></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
+12
-4
@@ -11,10 +11,11 @@
|
||||
|
||||
/* ------------------------------------------------------- the language */
|
||||
|
||||
var titleEl = document.querySelector("title");
|
||||
var description = document.querySelector('meta[name="description"]');
|
||||
var TITLE_EN = document.title;
|
||||
var TITLE_RU = "CursorLang — раскладка клавиатуры у курсора";
|
||||
var DESCRIPTION_EN = description.getAttribute("content");
|
||||
var TITLE_EN = titleEl.getAttribute("data-title-en");
|
||||
var TITLE_RU = titleEl.getAttribute("data-title-ru");
|
||||
var DESCRIPTION_EN = description.getAttribute("data-content-en");
|
||||
var DESCRIPTION_RU = description.getAttribute("data-content-ru");
|
||||
|
||||
function applyLanguage(lang) {
|
||||
@@ -44,8 +45,15 @@
|
||||
if (!button) { return; }
|
||||
|
||||
var lang = button.getAttribute("data-set-lang");
|
||||
applyLanguage(lang);
|
||||
remember("cursorlang.lang", lang);
|
||||
|
||||
// EN and RU live on separate URLs now, for search engines to rank
|
||||
// independently — switching language means a real navigation.
|
||||
var onRuPage = location.pathname.indexOf("/ru") === 0;
|
||||
if (lang === "ru" && !onRuPage) { location.href = "/ru/"; return; }
|
||||
if (lang === "en" && onRuPage) { location.href = "/"; return; }
|
||||
|
||||
applyLanguage(lang);
|
||||
});
|
||||
|
||||
/* ---------------------------------------------------------- the theme */
|
||||
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://cursor-lang.alrakis.kz/sitemap.xml
|
||||
@@ -0,0 +1,703 @@
|
||||
<!doctype html>
|
||||
<html lang="ru" data-lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title data-title-en="CursorLang — the keyboard layout at your cursor"
|
||||
data-title-ru="CursorLang — раскладка клавиатуры у курсора">CursorLang — раскладка клавиатуры у курсора</title>
|
||||
<meta name="description" content="Небольшая программа в трее Windows, называющая раскладку, на которую вы только что переключились, — у текстового курсора, у указателя мыши или в выбранной точке экрана. Бесплатно, без доступа в сеть, меньше 9 МБ."
|
||||
data-content-en="A tiny Windows tray app that names the keyboard layout you have just switched to — beside the text caret, beside the mouse pointer, or at a fixed point on the screen. Free, offline, under 9 MB."
|
||||
data-content-ru="Небольшая программа в трее Windows, называющая раскладку, на которую вы только что переключились, — у текстового курсора, у указателя мыши или в выбранной точке экрана. Бесплатно, без доступа в сеть, меньше 9 МБ.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="CursorLang — раскладка клавиатуры у курсора">
|
||||
<meta property="og:description" content="Переключили раскладку — маленькая подсказка называет её прямо там, где вы печатаете. Бесплатно, без доступа в сеть, меньше 9 МБ в трее.">
|
||||
<meta property="og:url" content="https://cursor-lang.alrakis.kz/ru/">
|
||||
<meta property="og:image" content="https://cursor-lang.alrakis.kz/og-image.png">
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
<meta property="og:locale" content="ru_RU">
|
||||
<meta property="og:locale:alternate" content="en_US">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:title" content="CursorLang — раскладка клавиатуры у курсора">
|
||||
<meta name="twitter:description" content="Небольшая программа в трее Windows, называющая раскладку, на которую вы только что переключились, — у текстового курсора, у указателя мыши или в выбранной точке экрана. Бесплатно, без доступа в сеть, меньше 9 МБ.">
|
||||
<meta name="twitter:image" content="https://cursor-lang.alrakis.kz/og-image.png">
|
||||
<link rel="canonical" href="https://cursor-lang.alrakis.kz/ru/">
|
||||
<link rel="alternate" hreflang="en" href="https://cursor-lang.alrakis.kz/">
|
||||
<link rel="alternate" hreflang="ru" href="https://cursor-lang.alrakis.kz/ru/">
|
||||
<link rel="alternate" hreflang="x-default" href="https://cursor-lang.alrakis.kz/">
|
||||
<meta name="theme-color" content="#fbfbfd" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#0d0d10" media="(prefers-color-scheme: dark)">
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
||||
<link rel="stylesheet" href="/styles.css">
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
"name": "CursorLang",
|
||||
"url": "https://cursor-lang.alrakis.kz/ru/",
|
||||
"image": "https://cursor-lang.alrakis.kz/og-image.png",
|
||||
"description": "Небольшая программа в трее Windows, называющая раскладку, на которую вы только что переключились, — у текстового курсора, у указателя мыши или в выбранной точке экрана. Бесплатно, без доступа в сеть, меньше 9 МБ.",
|
||||
"applicationCategory": "UtilitiesApplication",
|
||||
"operatingSystem": "Windows 10 1809 and later, 64-bit",
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "0",
|
||||
"priceCurrency": "USD"
|
||||
},
|
||||
"downloadUrl": "https://apps.microsoft.com/detail/9nvpp6h49kpp",
|
||||
"inLanguage": ["en", "ru"]
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- boot.js runs before the body is parsed, so the language and the theme of an
|
||||
earlier visit are in place for the first frame; everything else waits for
|
||||
the markup it works on -->
|
||||
<script src="/boot.js"></script>
|
||||
<script src="/main.js" defer></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<span id="top"></span>
|
||||
<a class="skip" href="#main"><span lang="en">Skip to content</span><span lang="ru">К содержанию</span></a>
|
||||
|
||||
<header data-menu="closed">
|
||||
<div class="wrap bar">
|
||||
<div class="brand">
|
||||
<svg width="26" height="26" viewBox="0 0 64 64" aria-hidden="true">
|
||||
<rect width="64" height="64" rx="12" fill="#202020"></rect>
|
||||
<text x="32" y="34" font-family="Segoe UI, sans-serif" font-size="29" font-weight="700"
|
||||
fill="#fff" text-anchor="middle" dominant-baseline="central">Aя</text>
|
||||
</svg>
|
||||
CursorLang
|
||||
</div>
|
||||
|
||||
<nav class="links" id="siteNav">
|
||||
<a href="#position"><span lang="en">Position</span><span lang="ru">Положение</span></a>
|
||||
<a href="#appearance"><span lang="en">Appearance</span><span lang="ru">Оформление</span></a>
|
||||
<a href="#capslock">Caps Lock</a>
|
||||
<a href="#lightweight"><span lang="en">Lightweight</span><span lang="ru">Легковесность</span></a>
|
||||
<a href="#privacy"><span lang="en">Privacy</span><span lang="ru">Данные</span></a>
|
||||
<a href="#download"><span lang="en">Download</span><span lang="ru">Загрузка</span></a>
|
||||
</nav>
|
||||
|
||||
<div class="controls">
|
||||
<div class="seg" role="group" aria-label="Language"
|
||||
data-label-en="Language" data-label-ru="Язык">
|
||||
<button type="button" data-set-lang="en" aria-pressed="false">EN</button>
|
||||
<button type="button" data-set-lang="ru" aria-pressed="true">RU</button>
|
||||
</div>
|
||||
<button type="button" class="icon-btn" id="themeBtn" aria-label="Light or dark theme"
|
||||
data-label-en="Light or dark theme" data-label-ru="Светлая или тёмная тема">
|
||||
<svg class="sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"
|
||||
stroke-linecap="round" aria-hidden="true">
|
||||
<circle cx="12" cy="12" r="4.2"></circle>
|
||||
<path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.4 5.4l1.6 1.6M17 17l1.6 1.6M18.6 5.4L17 7M7 17l-1.6 1.6"></path>
|
||||
</svg>
|
||||
<svg class="moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M20 14.2A8.2 8.2 0 0 1 9.8 4a8.2 8.2 0 1 0 10.2 10.2z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button type="button" class="icon-btn" id="menuBtn"
|
||||
aria-label="Menu" data-label-en="Menu" data-label-ru="Меню"
|
||||
aria-controls="siteNav" aria-expanded="false">
|
||||
<svg class="bars" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" aria-hidden="true">
|
||||
<path d="M4 7h16M4 12h16M4 17h16"></path>
|
||||
</svg>
|
||||
<svg class="cross" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" aria-hidden="true">
|
||||
<path d="M6 6l12 12M18 6L6 18"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="scrim" aria-hidden="true"></div>
|
||||
|
||||
<main id="main">
|
||||
|
||||
<!-- ============================================================== hero -->
|
||||
<section class="hero">
|
||||
<div class="wrap">
|
||||
<h1>
|
||||
<span lang="en">Your layout — right where you type.</span>
|
||||
<span lang="ru">Раскладка — там, где вы печатаете.</span>
|
||||
</h1>
|
||||
|
||||
<p class="lede">
|
||||
<span lang="en">CursorLang is a lightweight Windows utility that lives in your system tray. Whenever you
|
||||
switch your keyboard layout, a brief popup indicates the new language next to your text caret,
|
||||
mouse pointer, or a fixed screen position. Half a second later, it fades away.
|
||||
Simple and unobtrusive.</span>
|
||||
<span lang="ru">CursorLang — это легковесная утилита для Windows, которая находится в системном трее.
|
||||
При смене раскладки клавиатуры рядом с курсором, указателем мыши или фиксированной точкой на экране
|
||||
появляется короткое всплывающее окно, указывающее на новый язык. Через полсекунды оно исчезает.
|
||||
Просто и ненавязчиво.</span>
|
||||
</p>
|
||||
|
||||
<div class="cta">
|
||||
<a class="btn" role="link" href="https://apps.microsoft.com/detail/9nvpp6h49kpp">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
||||
<path d="M3 3h8.5v8.5H3V3zm9.5 0H21v8.5h-8.5V3zM3 12.5h8.5V21H3v-8.5zm9.5 0H21V21h-8.5v-8.5z"></path>
|
||||
</svg>
|
||||
<span lang="en">Download from Microsoft Store</span>
|
||||
<span lang="ru">Скачать из Microsoft Store</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="facts">
|
||||
<span lang="en">Free</span><span lang="ru">Бесплатно</span>
|
||||
<span lang="en">Windows 10 1809 and later, 64-bit</span>
|
||||
<span lang="ru">Windows 10 1809 и новее, 64 бита</span>
|
||||
<span lang="en">Uses under 9 MB of memory</span><span lang="ru">Использует менее 9 МБ памяти</span>
|
||||
<span lang="en">No internet connection required, zero telemetry</span><span lang="ru">Без доступа в сеть, без телеметрии.</span>
|
||||
</div>
|
||||
|
||||
<figure class="stage">
|
||||
<div class="window">
|
||||
<div class="titlebar" aria-hidden="true">
|
||||
<span class="dots"><i></i><i></i><i></i></span>
|
||||
<span class="name">
|
||||
<span lang="en">Team chat</span><span lang="ru">Рабочий чат</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="screen">
|
||||
<p class="msg" aria-hidden="true">
|
||||
<span lang="en">Is the build green?</span>
|
||||
<span lang="ru">Сборка прошла?</span>
|
||||
</p>
|
||||
|
||||
<div class="field">
|
||||
<span class="typed" id="demoText"></span><span class="caret" id="demoCaret"><span
|
||||
class="chip right fade" id="demoChip" hidden>EN</span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="taskbar" aria-hidden="true">
|
||||
<span class="ind" id="demoIndicator">ENG</span>
|
||||
<span>21:14</span>
|
||||
</div>
|
||||
</div>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ========================================================== position -->
|
||||
<section id="position">
|
||||
<div class="wrap">
|
||||
<h2><span lang="en">Position</span><span lang="ru">Положение</span></h2>
|
||||
<p class="deck">
|
||||
<span lang="en">Three placement modes</span>
|
||||
<span lang="ru">Три режима размещения подсказки</span>
|
||||
</p>
|
||||
<p class="lede">
|
||||
<span lang="en">Choose your preferred placement in the settings. Each mode maintains its own independent
|
||||
position, offset, and appearance.</span>
|
||||
<span lang="ru">Выберите желаемое положение в настройках. Каждый режим сохраняет свое независимое положение,
|
||||
смещение и внешний вид.</span>
|
||||
</p>
|
||||
|
||||
<div class="cards">
|
||||
<article class="card">
|
||||
<figure class="sketch">
|
||||
<svg viewBox="0 0 260 130" role="img"
|
||||
aria-label="A screen with the mouse pointer and the popup by its bottom right corner"
|
||||
data-label-en="A screen with the mouse pointer and the popup by its bottom right corner"
|
||||
data-label-ru="Экран с указателем мыши и подсказкой у его правого нижнего угла">
|
||||
<rect class="frame" x="1" y="1" width="258" height="128" rx="10" stroke-width="1.5"></rect>
|
||||
<path class="line" d="M28 30h120M28 46h86M28 62h104" stroke-width="4"></path>
|
||||
<path class="ink" d="M120 66l0 30 7-8 5 11 5-2-5-11 10 0z"></path>
|
||||
<rect class="plate" x="140" y="94" width="34" height="22" rx="6"></rect>
|
||||
<text class="glyph" x="157" y="108" text-anchor="middle">RU</text>
|
||||
</svg>
|
||||
</figure>
|
||||
<h3><span lang="en">Near the mouse pointer</span><span lang="ru">Рядом с указателем мыши</span></h3>
|
||||
<p>
|
||||
<span lang="en">Position the indicator at any of the six sides or corners with a custom offset.
|
||||
The popup dynamically follows your mouse pointer.</span>
|
||||
<span lang="ru">Разместите индикатор на любой из шести сторон или углов с заданным смещением.
|
||||
Всплывающее окно динамически следует за указателем мыши.</span>
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="card">
|
||||
<figure class="sketch">
|
||||
<svg viewBox="0 0 260 130" role="img"
|
||||
aria-label="A screen with lines of text and the popup beside the caret"
|
||||
data-label-en="A screen with lines of text and the popup beside the caret"
|
||||
data-label-ru="Экран со строками текста и подсказкой рядом с курсором">
|
||||
<rect class="frame" x="1" y="1" width="258" height="128" rx="10" stroke-width="1.5"></rect>
|
||||
<path class="line" d="M28 34h204M28 54h120" stroke-width="4"></path>
|
||||
<rect class="mark" x="152" y="44" width="2.5" height="20" rx="1"></rect>
|
||||
<rect class="plate" x="164" y="43" width="34" height="22" rx="6"></rect>
|
||||
<text class="glyph" x="181" y="57" text-anchor="middle">RU</text>
|
||||
<path class="line" d="M28 78h178M28 98h96" stroke-width="4"></path>
|
||||
</svg>
|
||||
</figure>
|
||||
<h3><span lang="en">Near the text caret</span><span lang="ru">Рядом с текстовым курсором</span></h3>
|
||||
<p>
|
||||
<span lang="en">Displays to the left or right of the caret, aligned with your current text line.</span>
|
||||
<span lang="ru">Отображается слева или справа от курсора, выравниваясь по текущей текстовой строке.</span>
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="card">
|
||||
<figure class="sketch">
|
||||
<svg viewBox="0 0 260 130" role="img"
|
||||
aria-label="A screen with the popup in the middle and the other six places marked faintly"
|
||||
data-label-en="A screen with the popup in the middle and the other six places marked faintly"
|
||||
data-label-ru="Экран с подсказкой посередине и еле намеченными шестью другими местами">
|
||||
<rect class="frame" x="1" y="1" width="258" height="128" rx="10" stroke-width="1.5"></rect>
|
||||
<rect class="ghost" x="24" y="22" width="26" height="16" rx="5"></rect>
|
||||
<rect class="ghost" x="117" y="22" width="26" height="16" rx="5"></rect>
|
||||
<rect class="ghost" x="210" y="22" width="26" height="16" rx="5"></rect>
|
||||
<rect class="ghost" x="24" y="92" width="26" height="16" rx="5"></rect>
|
||||
<rect class="ghost" x="117" y="92" width="26" height="16" rx="5"></rect>
|
||||
<rect class="ghost" x="210" y="92" width="26" height="16" rx="5"></rect>
|
||||
<rect class="plate" x="113" y="54" width="34" height="22" rx="6"></rect>
|
||||
<text class="glyph" x="130" y="68" text-anchor="middle">RU</text>
|
||||
</svg>
|
||||
</figure>
|
||||
<h3><span lang="en">A fixed point on the screen</span><span lang="ru">В выбранной точке экрана</span></h3>
|
||||
<p>
|
||||
<span lang="en">Choose from seven preset positions on your active monitor, complete with
|
||||
customizable margins. The indicator stays pinned to a consistent spot, so you always
|
||||
know where to look.</span>
|
||||
<span lang="ru">Выберите одно из семи предустановленных положений на активном мониторе с
|
||||
настраиваемыми полями. Индикатор остается зафиксированным в одном и том же месте,
|
||||
поэтому вы всегда будете знать, куда смотреть.</span>
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<p class="aside">
|
||||
<span lang="en"><b>Not every application exposes its text caret.</b> Standard Win32 fields respond
|
||||
instantly, while Chromium and Electron apps rely on accessibility APIs. However, applications
|
||||
rendering text onto custom canvases—like certain tool windows in a JetBrains IDE—may not report
|
||||
caret coordinates at all.
|
||||
In these fallback scenarios, the indicator automatically defaults to your configured fixed point
|
||||
placement, using that mode's appearance. It avoids jumping to the mouse pointer, as your eyes are
|
||||
focused on typing and the mouse might be left anywhere on the screen.</span>
|
||||
<span lang="ru"><b>Не всякое приложение сообщает, где его курсор.</b> Стандартные поля Win32 реагируют
|
||||
мгновенно, в то время как приложения Chromium и Electron используют API специальных возможностей.
|
||||
Однако приложения, отображающие текст на пользовательских холстах — например, некоторые окна
|
||||
инструментов в IDE JetBrains — могут вообще не сообщать координаты курсора.
|
||||
В таких резервных сценариях индикатор автоматически переключается на заданное вами фиксированное
|
||||
положение, используя внешний вид этого режима. Это позволяет избежать переключения на указатель мыши,
|
||||
поскольку ваши глаза сосредоточены на наборе текста, а курсор может находиться в любой точке экрана.</span>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================== look -->
|
||||
<section id="appearance">
|
||||
<div class="wrap">
|
||||
<h2><span lang="en">Appearance</span><span lang="ru">Оформление</span></h2>
|
||||
<p class="deck">
|
||||
<span lang="en">Each mode has its own unique look</span>
|
||||
<span lang="ru">У каждого режима своё оформление</span>
|
||||
</p>
|
||||
<p class="lede">
|
||||
<span lang="en">The caret popup lives right inside the text you're reading, keeping it compact and
|
||||
unobtrusive. The fixed-screen popup, on the other hand, is meant to be larger and more prominent.
|
||||
Therefore, offset, font size, opacity, and colors are saved independently for each mode — changing
|
||||
one leaves the rest untouched.</span>
|
||||
<span lang="ru">Всплывающее окно с курсором располагается прямо внутри читаемого текста, оставаясь
|
||||
компактным и ненавязчивым. Всплывающее окно с фиксированным экраном, напротив, предназначено для
|
||||
большего размера и большей заметности. Поэтому смещение, размер шрифта, прозрачность и цвета
|
||||
сохраняются независимо для каждого режима — изменение одного параметра не влияет на остальные.</span>
|
||||
</p>
|
||||
|
||||
<div class="playground">
|
||||
<form class="panel" id="lookForm">
|
||||
<h3><span lang="en">Layout popup</span><span lang="ru">Подсказка с раскладкой</span></h3>
|
||||
|
||||
<div class="row">
|
||||
<label for="offset">
|
||||
<span><span lang="en">Offset</span><span lang="ru">Отступ</span></span>
|
||||
<span class="val" id="offsetVal">16</span>
|
||||
</label>
|
||||
<input type="range" id="offset" min="0" max="80" step="1" value="16">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="fontSize">
|
||||
<span><span lang="en">Font size</span><span lang="ru">Размер шрифта</span></span>
|
||||
<span class="val" id="fontSizeVal">20</span>
|
||||
</label>
|
||||
<input type="range" id="fontSize" min="10" max="72" step="1" value="20">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="opacity">
|
||||
<span><span lang="en">Opacity</span><span lang="ru">Непрозрачность</span></span>
|
||||
<span class="val" id="opacityVal">90%</span>
|
||||
</label>
|
||||
<input type="range" id="opacity" min="10" max="100" step="1" value="90">
|
||||
</div>
|
||||
|
||||
<div class="row pair">
|
||||
<div class="row tight">
|
||||
<label for="bgColor"><span lang="en">Background</span><span lang="ru">Фон</span></label>
|
||||
<input type="color" id="bgColor" value="#202020">
|
||||
</div>
|
||||
<div class="row tight">
|
||||
<label for="fgColor"><span lang="en">Text</span><span lang="ru">Текст</span></label>
|
||||
<input type="color" id="fgColor" value="#ffffff">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<span class="lbl" id="sideLabel">
|
||||
<span><span lang="en">Side of the caret</span><span lang="ru">Сторона от курсора</span></span>
|
||||
</span>
|
||||
<div class="seg" id="side" role="group" aria-labelledby="sideLabel">
|
||||
<button type="button" data-side="left" aria-pressed="false">
|
||||
<span lang="en">Left</span><span lang="ru">Слева</span>
|
||||
</button>
|
||||
<button type="button" data-side="right" aria-pressed="true">
|
||||
<span lang="en">Right</span><span lang="ru">Справа</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="duration">
|
||||
<span><span lang="en">Display time</span><span lang="ru">Время показа</span></span>
|
||||
<span class="val" id="durationVal">500 ms</span>
|
||||
</label>
|
||||
<input type="range" id="duration" min="200" max="5000" step="100" value="500">
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn ghost block" id="previewBtn">
|
||||
<span lang="en">Preview</span><span lang="ru">Предпросмотр</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="preview-stage">
|
||||
<div class="preview-line">
|
||||
<span lang="en">Sent you a </span><span lang="ru">Отправил тебе </span>
|
||||
<span class="typed">pull request</span><span class="caret" id="previewCaret"><span
|
||||
class="chip right fade" id="previewChip">RU</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="aside">
|
||||
<span lang="en"><b>The popup only answers a question you explicitly asked.</b> It appears when you switch the
|
||||
layout yourself. When you switch to another window, Windows may change the layout automatically in
|
||||
the background, but the popup stays silent. After all, you didn't ask.</span>
|
||||
<span lang="ru"><b>Всплывающее окно отвечает только на заданный вами вопрос.</b> Оно появляется, когда вы
|
||||
сами меняете расположение окон. При переключении на другое окно Windows может автоматически изменить
|
||||
расположение окон в фоновом режиме, но всплывающее окно остается незамеченным. В конце концов, вы же
|
||||
не спрашивали.</span>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ========================================================== capslock -->
|
||||
<section id="capslock">
|
||||
<div class="wrap">
|
||||
<h2>Caps Lock</h2>
|
||||
<p class="deck">
|
||||
<span lang="en">A key that could be doing more</span>
|
||||
<span lang="ru">Клавиша, которая могла бы работать</span>
|
||||
</p>
|
||||
<p class="lede">
|
||||
<span lang="en">When enabled in settings, a quick tap of Caps Lock switches your keyboard layout instead
|
||||
of toggling letter casing. Hold it longer than your custom threshold, and nothing changes: the popup
|
||||
simply displays your current layout — a quick look, without switching.</span>
|
||||
<span lang="ru">Если эта функция включена в настройках, быстрое нажатие клавиши Caps Lock переключает
|
||||
раскладку клавиатуры вместо изменения регистра букв. Если удерживать клавишу дольше заданного вами
|
||||
порога, ничего не изменится: во всплывающем окне просто отобразится текущая раскладка — быстрый
|
||||
взгляд без переключения.</span>
|
||||
</p>
|
||||
|
||||
<ul class="bullets two-up">
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M4 12a8 8 0 1 1 16 0 8 8 0 0 1-16 0z"></path><path d="M12 8v4l2.5 2"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>Disabled by default.</b> This shortcut is disabled by default in the app, so
|
||||
the Caps Lock key continues to function as usual.</span>
|
||||
<span lang="ru"><b>По умолчанию выключено.</b> В приложении Caps Lock отключен по умолчанию,
|
||||
поэтому он продолжает работать так, как работал всегда.</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M5 12h14M12 5v14"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>No administrator rights required.</b> Built as a standard user-level
|
||||
application, it runs under your active user account and simply doesn't need higher
|
||||
privileges.</span>
|
||||
<span lang="ru"><b>Права администратора не запрашиваются.</b> Приложение разработано как
|
||||
стандартное приложение для пользователей и работает под вашей активной учетной записью,
|
||||
поэтому более высокие привилегии не требуются.</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M12 3l7.5 3v5.5c0 4.4-3 7.9-7.5 9.5-4.5-1.6-7.5-5.1-7.5-9.5V6L12 3z"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>Only one key is monitored.</b> The low-level hook watches strictly for
|
||||
Caps Lock. No other keystrokes are recorded, stored, or transmitted anywhere — and since
|
||||
the app is offline, they physically can't be.</span>
|
||||
<span lang="ru"><b>Отслеживается одна клавиша.</b> Низкоуровневый перехватчик следит исключительно
|
||||
за нажатием клавиши Caps Lock. Никакие другие нажатия клавиш не записываются, не сохраняются и
|
||||
не передаются никуда — а поскольку приложение работает в автономном режиме, это
|
||||
физически невозможно.</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M12 4.5l8 14H4l8-14z"></path><path d="M12 10v4M12 16.5v.01"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>Doesn't interfere with elevated apps.</b> Windows blocks ordinary apps from
|
||||
injecting shortcuts into windows running as administrator (like Task Manager, Registry Editor,
|
||||
or UAC prompts).</span>
|
||||
<span lang="ru"><b>Не работает в окнах, запущенных от администратора.</b>
|
||||
Windows блокирует возможность передачу нажатия клавиш в окнах, запущенные от имени
|
||||
администратора, и служебных приложениях (например, диспетчером задач, редактором реестра
|
||||
или запросами UAC).</span>
|
||||
</span>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ===================================================== lightweight -->
|
||||
<section id="lightweight">
|
||||
<div class="wrap">
|
||||
<h2><span lang="en">Lightweight</span><span lang="ru">Легковесность</span></h2>
|
||||
<p class="deck">
|
||||
<span lang="en">Small enough to forget about</span>
|
||||
<span lang="ru">Настолько маленькое, что о нём легко забыть</span>
|
||||
</p>
|
||||
<p class="lede">
|
||||
<span lang="en">CursorLang is split into two executables. The one that lives in your tray all day is
|
||||
built without a UI rendering stack — a tooltip that Win32 draws in eight megabytes has no business
|
||||
costing a hundred. Anything heavier is strictly kept out of the background process. The second
|
||||
executable handles the settings: it loads only when you open the window and completely unloads
|
||||
from memory the moment you close it.</span>
|
||||
<span lang="ru">CursorLang разделен на два исполняемых файла. Тот, что находится в системном трее весь
|
||||
день, создан без стека рендеринга пользовательского интерфейса — всплывающая подсказка, которую
|
||||
Win32 отрисовывает за восемь мегабайт, не должна стоить сто. Все, что потребляет больше ресурсов,
|
||||
строго исключено из фонового процесса. Второй исполняемый файл обрабатывает настройки: он загружается
|
||||
только при открытии окна и полностью выгружается из памяти в момент его закрытия.</span>
|
||||
</p>
|
||||
|
||||
<ul class="bullets two-up">
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M4 7l8-4 8 4v10l-8 4-8-4V7z"></path><path d="M4 7l8 4 8-4M12 11v10"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>Under 9 MB in the tray.</b> The settings window is a separate
|
||||
process: it starts when you ask for it and gives its memory back when you
|
||||
close it.</span>
|
||||
<span lang="ru"><b>Меньше 9 МБ в трее.</b> Окно настроек — отдельный процесс: он
|
||||
запускается, когда его просят, и возвращает память, когда окно
|
||||
закрывают.</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M12 3v9M8.2 6.4a6.5 6.5 0 1 0 7.6 0"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>Starts with Windows if you ask it to</b> — and Windows always keeps the final
|
||||
word. Turn off startup in Settings → Apps → Startup, and the application respects your choice
|
||||
instead of quietly re-enabling itself.</span>
|
||||
<span lang="ru"><b>Запускается вместе с Windows, если попросить</b> — и последнее слово всегда
|
||||
остается за Windows. Отключите автозагрузку в Параметры → Приложения → Автозагрузка, и
|
||||
приложение будет уважать ваш выбор, вместо того чтобы незаметно включаться снова.</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<circle cx="12" cy="12" r="8.5"></circle><path d="M12 3.5v17"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>Light and dark themes,</b> following Windows or pinned to one
|
||||
of them. Available in English and Russian.</span>
|
||||
<span lang="ru"><b>Светлая и тёмная тема,</b> вслед за Windows или закреплённая.
|
||||
Интерфейс — русский и английский.</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M20 6L9 17l-5-5"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>Nothing else to install.</b> The application carries its own
|
||||
copy of .NET, and the Microsoft Store keeps it up to date.</span>
|
||||
<span lang="ru"><b>Ничего дополнительно устанавливать не нужно.</b> Приложение несёт с собой
|
||||
свою копию .NET, a обновляет его Microsoft Store.</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- =========================================================== privacy -->
|
||||
<section id="privacy">
|
||||
<div class="wrap">
|
||||
<h2><span lang="en">Privacy policy</span><span lang="ru">Политика конфиденциальности</span></h2>
|
||||
<p class="deck">
|
||||
<span lang="en">CursorLang collects nothing</span>
|
||||
<span lang="ru">CursorLang ничего не собирает</span>
|
||||
</p>
|
||||
<p class="lede">
|
||||
<span lang="en">It really is that simple. The points below just provide the technical details.</span>
|
||||
<span lang="ru">Всё действительно так просто. Приведённые ниже пункты содержат лишь технические подробности.</span>
|
||||
</p>
|
||||
|
||||
<div class="panel">
|
||||
<ul class="bullets">
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M20 6L9 17l-5-5"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>No personal data is collected</b>, stored remotely, or shared with anyone.
|
||||
There are no accounts, no ads, and no analytics.</span>
|
||||
<span lang="ru"><b>Персональные данные не собираются,</b> не хранятся удаленно и не
|
||||
передаются никому. Нет учетных записей, рекламы и аналитики.</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M20 6L9 17l-5-5"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>The application makes no network requests.</b> It contains no networking
|
||||
code, telemetry, or internal update checks — the Microsoft Store handles updates
|
||||
automatically.</span>
|
||||
<span lang="ru"><b>Приложение не обращается в сеть.</b> Не содержит сетевого кода, телеметрии
|
||||
или внутренних проверок обновлений — обновления обрабатываются Microsoft Store
|
||||
автоматически.</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M20 6L9 17l-5-5"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>Settings are stored locally in a single file.</b> The Store version keeps
|
||||
this in the app's local data folder, which Windows removes entirely upon uninstallation —
|
||||
leaving no trace behind.</span>
|
||||
<span lang="ru"><b>Настройки хранятся локально в одном файле.</b> В версии из магазина
|
||||
приложений они хранятся в локальной папке данных приложения, которую Windows полностью
|
||||
удаляет при деинсталляции, не оставляя никаких следов.</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M20 6L9 17l-5-5"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>The optional Caps Lock shortcut uses a low-level keyboard hook.</b>
|
||||
It monitors strictly the Caps Lock key and nothing else. Your keystrokes are never
|
||||
recorded or transmitted, and the feature is disabled by default.</span>
|
||||
<span lang="ru"><b>Горячая клавиша Caps Lock использует низкоуровневый
|
||||
перехват клавиатуры.</b> Она отслеживает исключительно нажатие клавиши Caps Lock и
|
||||
ничего больше. Ваши нажатия клавиш никогда не записываются и не передаются, и эта
|
||||
функция отсутствует по умолчанию.</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M20 6L9 17l-5-5"></path>
|
||||
</svg>
|
||||
<span>
|
||||
<span lang="en"><b>To position the popup, the app asks Windows for the active layout and
|
||||
caret location.</b> This data never leaves the app's memory, and your actual typed
|
||||
text is never read or accessed.</span>
|
||||
<span lang="ru"><b>Для позиционирования всплывающего окна приложение запрашивает у Windows
|
||||
активную компоновку и положение курсора.</b> Эти данные никогда не покидают память
|
||||
приложения, и фактический введенный вами текст никогда не считывается и не используется.</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ========================================================== download -->
|
||||
<section id="download">
|
||||
<div class="wrap">
|
||||
<h2><span lang="en">Download</span><span lang="ru">Загрузка</span></h2>
|
||||
<p class="deck">
|
||||
<span lang="en">One click from the Microsoft Store</span>
|
||||
<span lang="ru">Устанавливается из Microsoft Store в один клик</span>
|
||||
</p>
|
||||
<p class="lede">
|
||||
<span lang="en">CursorLang is distributed through the Microsoft Store, which installs it and keeps it
|
||||
updated on its own — nothing else is asked of you in between. It runs on Windows 10 version 1809
|
||||
(build 17763) or later, 64-bit.</span>
|
||||
<span lang="ru">CursorLang распространяется через Microsoft Store: он же его устанавливает и сам держит
|
||||
обновлённым — больше от вас ничего не требуется. Работает на Windows 10 версии 1809
|
||||
(сборка 17763) или новее, 64 бита.</span>
|
||||
</p>
|
||||
|
||||
<div class="cta">
|
||||
<a class="btn" role="link" href="https://apps.microsoft.com/detail/9nvpp6h49kpp">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
||||
<path d="M3 3h8.5v8.5H3V3zm9.5 0H21v8.5h-8.5V3zM3 12.5h8.5V21H3v-8.5zm9.5 0H21V21h-8.5v-8.5z"></path>
|
||||
</svg>
|
||||
<span lang="en">Download from Microsoft Store</span>
|
||||
<span lang="ru">Скачать из Microsoft Store</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p class="support">
|
||||
<span lang="en">Something not working, or a question about the application? Write to
|
||||
<a href="mailto:support@alrakis.kz">support@alrakis.kz</a> and name the version in
|
||||
the letter — it is in the title of the settings window.</span>
|
||||
<span lang="ru">Что-то не работает или есть вопрос о приложении? Напишите на
|
||||
<a href="mailto:support@alrakis.kz">support@alrakis.kz</a> и назовите в письме
|
||||
версию — она есть в заголовке окна настроек.</span>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="wrap footrow">
|
||||
<span>
|
||||
CursorLang · © 2026 Aleksandr Neichev
|
||||
</span>
|
||||
<nav>
|
||||
<a href="#privacy"><span lang="en">Privacy</span><span lang="ru">Конфиденциальность</span></a>
|
||||
<a href="mailto:support@alrakis.kz"><span lang="en">Support</span><span lang="ru">Поддержка</span></a>
|
||||
<a href="#top"><span lang="en">Back to top</span><span lang="ru">Наверх</span></a>
|
||||
</nav>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||
<url>
|
||||
<loc>https://cursor-lang.alrakis.kz/</loc>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://cursor-lang.alrakis.kz/"/>
|
||||
<xhtml:link rel="alternate" hreflang="ru" href="https://cursor-lang.alrakis.kz/ru/"/>
|
||||
<xhtml:link rel="alternate" hreflang="x-default" href="https://cursor-lang.alrakis.kz/"/>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://cursor-lang.alrakis.kz/ru/</loc>
|
||||
<xhtml:link rel="alternate" hreflang="en" href="https://cursor-lang.alrakis.kz/"/>
|
||||
<xhtml:link rel="alternate" hreflang="ru" href="https://cursor-lang.alrakis.kz/ru/"/>
|
||||
<xhtml:link rel="alternate" hreflang="x-default" href="https://cursor-lang.alrakis.kz/"/>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
</urlset>
|
||||
Reference in New Issue
Block a user