Some fixes and translations

pull/1/head
Zakhar Timoshenko 3 years ago
parent a59c286c6b
commit 108d24a1c8

@ -1,6 +1,5 @@
import type { DefaultTheme, LocaleConfig } from 'vitepress' import type { DefaultTheme, LocaleConfig } from 'vitepress'
import type { Theme } from '../theme/types' import type { Theme } from '../theme/types'
import { components } from '../theme/plugins/component'
import 'dotenv/config' import 'dotenv/config'
export const SITE_NAME = 'Kotatsu Website' export const SITE_NAME = 'Kotatsu Website'
@ -65,8 +64,6 @@ export const config: LocaleConfig<Theme.Config> = {
message: "<a href=\"https://www.gnu.org/licenses/gpl-3.0.en.html\" target=\"_blank\">GPL-3.0 Licensed</a> <span class=\"divider\">|</span> <a href=\"/privacy/\">Privacy policy</a>", message: "<a href=\"https://www.gnu.org/licenses/gpl-3.0.en.html\" target=\"_blank\">GPL-3.0 Licensed</a> <span class=\"divider\">|</span> <a href=\"/privacy/\">Privacy policy</a>",
copyright: `Copyright © 2020 - ${new Date().getFullYear()} Kotatsu Developers`, copyright: `Copyright © 2020 - ${new Date().getFullYear()} Kotatsu Developers`,
}, },
components: components.filter(component => component.path.startsWith('components/')),
}, },
} }
} }
@ -80,10 +77,10 @@ function defaultSidebar(): DefaultTheme.SidebarItem[] {
text: "Download", text: "Download",
link: "/download/", link: "/download/",
}, },
{ /* {
text: "Parsers", text: "Parsers",
link: "/parsers/", link: "/parsers/",
}, }, */
{ {
text: "Changelogs", text: "Changelogs",
link: "/changelogs/", link: "/changelogs/",
@ -209,7 +206,7 @@ function getNav(): DefaultTheme.NavItem[] {
link: "/manuals/guides/getting-started", link: "/manuals/guides/getting-started",
activeMatch: "/manuals/", activeMatch: "/manuals/",
}, },
{ /* {
text: "News", text: "News",
link: "/news/", link: "/news/",
activeMatch: "/news/", activeMatch: "/news/",
@ -218,6 +215,6 @@ function getNav(): DefaultTheme.NavItem[] {
text: "Account", text: "Account",
link: "/account/", link: "/account/",
activeMatch: "/account/" activeMatch: "/account/"
} } */
] ]
} }

@ -1,5 +1,5 @@
import type { HeadConfig, TransformContext } from "vitepress" import type { HeadConfig, TransformContext } from "vitepress"
import type { DocsPageData } from '../../theme/plugins/component' import type { DocsPageData } from '../../theme/plugins/section'
function generateMeta(context: TransformContext, hostname: string) { function generateMeta(context: TransformContext, hostname: string) {
const head: HeadConfig[] = [] const head: HeadConfig[] = []

@ -1,15 +1,13 @@
import type { Theme } from '../theme/types' import type { Theme } from '../theme/types'
import type { DocsPageData } from '../theme/plugins/component' import { defineConfigWithTheme } from 'vitepress'
import { type HeadConfig, defineConfigWithTheme } from 'vitepress'
import { config as ru, searchLocale as searchLocaleRu } from './ru' import { config as ru, searchLocale as searchLocaleRu } from './ru'
import { config as root, searchLocale as searchLocaleEn } from './en' import { config as root, searchLocale as searchLocaleEn } from './en'
import { config as ua, searchLocale as searchLocaleUa } from './ua' import { config as ua, searchLocale as searchLocaleUa } from './ua'
import { addPlugins } from '../theme/plugins/markdown' import { addPlugins } from '../theme/plugins/markdown'
import { components, prepareData } from '../theme/plugins/component' import { sections, prepareData } from '../theme/plugins/section'
import { slugify } from 'transliteration' import { slugify } from 'transliteration'
import { fileURLToPath, URL } from 'node:url' import { fileURLToPath, URL } from 'node:url'
import { telegram } from '../../website/icons' import { telegram } from '../../website/icons'
import { normalize } from 'vitepress/dist/client/shared'
import { tabsMarkdownPlugin } from "vitepress-plugin-tabs" import { tabsMarkdownPlugin } from "vitepress-plugin-tabs"
import pluginRewriteAll from 'vite-plugin-rewrite-all'; import pluginRewriteAll from 'vite-plugin-rewrite-all';
@ -63,7 +61,7 @@ export default defineConfigWithTheme<Theme.Config>({
['link', { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap' }], ['link', { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap' }],
['link', { rel: 'icon', href: '/favicon.ico?v=2', sizes: 'any' }], ['link', { rel: 'icon', href: '/favicon.ico?v=2', sizes: 'any' }],
['link', { rel: 'icon', href: '/icon.svg?v=2', type: 'image/svg+xml' }], ['link', { rel: 'icon', href: '/logo.svg?v=2', type: 'image/svg+xml' }],
['link', { rel: 'apple-touch-icon', href: '/apple-touch-icon.png?v=2' }], ['link', { rel: 'apple-touch-icon', href: '/apple-touch-icon.png?v=2' }],
['link', { rel: 'manifest', href: '/site.webmanifest' }], ['link', { rel: 'manifest', href: '/site.webmanifest' }],
], ],
@ -87,9 +85,16 @@ export default defineConfigWithTheme<Theme.Config>({
search: { search: {
provider: 'local', provider: 'local',
options: {
locales: {
...searchLocaleEn,
...searchLocaleRu,
...searchLocaleUa,
},
},
}, },
components, sections,
}, },
locales: { locales: {

@ -1,6 +1,5 @@
import type { DefaultTheme, LocaleConfig } from 'vitepress' import type { DefaultTheme, LocaleConfig } from 'vitepress'
import type { Theme } from '../theme/types' import type { Theme } from '../theme/types'
import { components } from '../theme/plugins/component'
import 'dotenv/config' import 'dotenv/config'
export const SITE_NAME = 'Kotatsu Website' export const SITE_NAME = 'Kotatsu Website'
@ -75,8 +74,6 @@ export const config: LocaleConfig<Theme.Config> = {
message: "<a href=\"https://www.gnu.org/licenses/gpl-3.0.en.html\" target=\"_blank\">Лицензия GPL-3.0</a> <span class=\"divider\">|</span> <a href=\"/privacy/\">Политика конфиденциальности</a>", message: "<a href=\"https://www.gnu.org/licenses/gpl-3.0.en.html\" target=\"_blank\">Лицензия GPL-3.0</a> <span class=\"divider\">|</span> <a href=\"/privacy/\">Политика конфиденциальности</a>",
copyright: `Copyright © 2020 - ${new Date().getFullYear()} Kotatsu Developers`, copyright: `Copyright © 2020 - ${new Date().getFullYear()} Kotatsu Developers`,
}, },
components: components.filter(component => component.path.startsWith('ru/components/')),
}, },
} }
} }

@ -1,3 +1,10 @@
import { type Ref, computed } from 'vue'
import { type PageData, useData } from 'vitepress'
export interface Data {
lang: Ref<string>
}
const iconMappings = { const iconMappings = {
about: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>information-outline</title><path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z" /></svg>', about: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>information-outline</title><path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z" /></svg>',
bookmark: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>bookmark-outline</title><path d="M17,18L12,15.82L7,18V5H17M17,3H7A2,2 0 0,0 5,5V21L12,18L19,21V5C19,3.89 18.1,3 17,3Z" /></svg>', bookmark: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>bookmark-outline</title><path d="M17,18L12,15.82L7,18V5H17M17,3H7A2,2 0 0,0 5,5V21L12,18L19,21V5C19,3.89 18.1,3 17,3Z" /></svg>',

@ -1,6 +1,6 @@
import type { DefaultTheme, LocaleConfig } from 'vitepress' import type { DefaultTheme, LocaleConfig } from 'vitepress'
import type { Theme } from '../theme/types' import type { Theme } from '../theme/types'
import { components } from '../theme/plugins/component' import { sections } from '../theme/plugins/section'
export const SITE_NAME = 'Kotatsu Website' export const SITE_NAME = 'Kotatsu Website'
export const META_DESCRIPTION = 'Проста і зручна читалка манги з відкритим вихідним кодом від спільноти і для спільноти, де ви можете знайти і читати вашу улюблену мангу простіше як ніколи.' export const META_DESCRIPTION = 'Проста і зручна читалка манги з відкритим вихідним кодом від спільноти і для спільноти, де ви можете знайти і читати вашу улюблену мангу простіше як ніколи.'
@ -73,8 +73,6 @@ export const config: LocaleConfig<Theme.Config> = {
message: "<a href=\"https://www.gnu.org/licenses/gpl-3.0.en.html\" target=\"_blank\">Ліцензія GPL-3.0</a> <span class=\"divider\">|</span> <a href=\"/privacy/\">Політика конфіденційності</a>", message: "<a href=\"https://www.gnu.org/licenses/gpl-3.0.en.html\" target=\"_blank\">Ліцензія GPL-3.0</a> <span class=\"divider\">|</span> <a href=\"/privacy/\">Політика конфіденційності</a>",
copyright: `Copyright © 2020 - ${new Date().getFullYear()} Kotatsu Developers`, copyright: `Copyright © 2020 - ${new Date().getFullYear()} Kotatsu Developers`,
}, },
components: components.filter(component => component.path.startsWith('ru/components/')),
} }
} }
} }

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Ref } from 'vue' import { Ref } from 'vue'
import { useData, withBase, useRoute } from 'vitepress' import { useData, withBase, useRoute } from 'vitepress'
import type { DocsPageData } from '../plugins/component' import type { DocsPageData } from '../plugins/section'
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue' import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'

@ -3,7 +3,7 @@ import DefaultTheme from 'vitepress/theme-without-fonts'
import Home from './Home.vue' import Home from './Home.vue'
import TranslatorWidget from './TranslatorWidget.vue' import TranslatorWidget from './TranslatorWidget.vue'
import ScreenAuthorWidget from './ScreenAuthorWidget.vue' import ScreenTranslatorWidget from './ScreenTranslatorWidget.vue'
import Breadcrumbs from './Breadcrumbs.vue' import Breadcrumbs from './Breadcrumbs.vue'
import NotFound from './NotFound.vue' import NotFound from './NotFound.vue'
@ -22,7 +22,7 @@ const { Layout } = DefaultTheme
<Breadcrumbs /> <Breadcrumbs />
</template> </template>
<template #doc-footer-before> <template #doc-footer-before>
<ScreenAuthorWidget /> <ScreenTranslatorWidget />
</template> </template>
<template #not-found> <template #not-found>
<NotFound /> <NotFound />

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { type Ref, computed } from 'vue' import { type Ref, computed } from 'vue'
import { type PageData, useData } from 'vitepress' import { type PageData, useData } from 'vitepress'
import type { DocsPageData } from '../plugins/component' import type { DocsPageData } from '../plugins/section'
import { type Translator, translators } from '../../../website/translators' import { type Translator, translators } from '../../../website/translators'
import { VPImage } from 'vitepress/theme-without-fonts' import { VPImage } from 'vitepress/theme-without-fonts'
@ -15,9 +15,10 @@ export interface Data {
const { page, frontmatter, lang }: Data = useData() const { page, frontmatter, lang }: Data = useData()
const translatorLabel = computed<string>(() => lang.value === 'ru' ? 'Переводчик' : 'Translator') const translatorLabel = computed<string>(() => (lang.value === 'ru') ? ('Переводчик') : ((lang.value === 'ua') ? ('Перекладач') : ('Translator')))
const translator = computed<Translator>(() => { const translator = computed<Translator>(() => {
const data = page.value?.component?.translator || translators[frontmatter.value.translator] const data = page.value?.section?.translator || translators[frontmatter.value.translator]
if (!data) { if (!data) {
return return
@ -33,7 +34,7 @@ const translator = computed<Translator>(() => {
<template> <template>
<article <article
v-if="translator" v-if="translator"
class="ScreenAuthorWidget" class="ScreenTranslatorWidget"
> >
<VPLink <VPLink
:href="translator.github" :href="translator.github"
@ -55,12 +56,12 @@ const translator = computed<Translator>(() => {
<style scoped> <style scoped>
.ScreenAuthorWidget { .ScreenTranslatorWidget {
margin-bottom: 20px; margin-bottom: 20px;
} }
@media (min-width: 1280px) { @media (min-width: 1280px) {
.ScreenAuthorWidget { .ScreenTranslatorWidget {
display: none; display: none;
} }
} }

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { type Ref, computed } from 'vue' import { type Ref, computed } from 'vue'
import { type PageData, useData } from 'vitepress' import { type PageData, useData } from 'vitepress'
import type { DocsPageData } from '../plugins/component' import type { DocsPageData } from '../plugins/section'
import { type Translator, translators } from '../../../website/translators' import { type Translator, translators } from '../../../website/translators'
import { VPImage } from 'vitepress/theme-without-fonts' import { VPImage } from 'vitepress/theme-without-fonts'
@ -15,9 +15,9 @@ export interface Data {
const { page, frontmatter, lang }: Data = useData() const { page, frontmatter, lang }: Data = useData()
const translatorLabel = computed<string>(() => lang.value === 'en' ? 'Translator' : 'Переводчик') const translatorLabel = computed<string>(() => (lang.value === 'ru') ? ('Переводчик') : ((lang.value === 'ua') ? ('Перекладач') : ('Translator')))
const translator = computed<Translator>(() => { const translator = computed<Translator>(() => {
const data = page.value?.component?.translator || translators[frontmatter.value.author] const data = page.value?.section?.translator || translators[frontmatter.value.translator]
if (!data) { if (!data) {
return return

@ -1,6 +1,6 @@
import { Ref, computed } from 'vue' import { Ref, computed } from 'vue'
import type { DefaultTheme, SiteData } from 'vitepress' import type { DefaultTheme, SiteData } from 'vitepress'
import type { DocsPageData } from '../plugins/component' import type { DocsPageData } from '../plugins/section'
import { useData } from 'vitepress' import { useData } from 'vitepress'
import { ensureStartingSlash } from '../utils' import { ensureStartingSlash } from '../utils'
import { getFlatSideBarLinks } from 'vitepress/dist/client/theme-default/support/sidebar' import { getFlatSideBarLinks } from 'vitepress/dist/client/theme-default/support/sidebar'
@ -74,15 +74,15 @@ export function useLangs({
} }
} }
if (!page.value.component) { if (!page.value.section) {
return { return {
text: value.label, text: value.label,
link: rootLink, link: rootLink,
} }
} }
const component = themeConfig.components.find(component => component.title === page.value.component.title) const section = themeConfig.sections.find(section => section.title === page.value.section.title)
if (!component) { if (!section) {
return { return {
text: value.label, text: value.label,
link: rootLink, link: rootLink,
@ -91,7 +91,7 @@ export function useLangs({
return { return {
text, text,
link: component.link link: section.link
} }
} }
)) ))

@ -1,6 +1,6 @@
import { computed } from 'vue' import { computed } from 'vue'
import type { ComputedRef, Ref } from 'vue' import type { ComputedRef, Ref } from 'vue'
import type { DocsPageData } from '../plugins/component' import type { DocsPageData } from '../plugins/section'
import { useData } from 'vitepress' import { useData } from 'vitepress'
import { isActive } from 'vitepress/dist/client/shared' import { isActive } from 'vitepress/dist/client/shared'
import { getFlatSideBarLinks } from 'vitepress/dist/client/theme-default/support/sidebar' import { getFlatSideBarLinks } from 'vitepress/dist/client/theme-default/support/sidebar'
@ -15,13 +15,13 @@ export function usePrevNext(): ComputedRef {
const { page, theme, frontmatter }: Data = useData() const { page, theme, frontmatter }: Data = useData()
return computed(() => { return computed(() => {
const component = page.value.component const section = page.value.section
if (!component) { if (!section) {
return '' return ''
} }
const candidates = getFlatSideBarLinks([component]) const candidates = getFlatSideBarLinks([section])
const index = candidates.findIndex((link) => isActive(page.value.relativePath, link.link)) const index = candidates.findIndex((link) => isActive(page.value.relativePath, link.link))
const hidePrev = const hidePrev =

@ -12,7 +12,7 @@ import { generateSidebarItem, getTitleFromContent } from './sidebar'
import type { Translator } from '../../../website/translators' import type { Translator } from '../../../website/translators'
import { findPath } from '../utils' import { findPath } from '../utils'
export interface ComponentData { export interface SectionData {
path: string path: string
link: string link: string
title: string title: string
@ -31,14 +31,26 @@ export interface ComponentData {
} }
export interface DocsPageData extends PageData { export interface DocsPageData extends PageData {
component?: ComponentData section?: SectionData
breadcrumbs?: DefaultTheme.SidebarItem[] breadcrumbs?: DefaultTheme.SidebarItem[]
} }
export const components: ComponentData[] = fg export const sections: SectionData[] = fg
.sync([ .sync([
'website/manuals/faq/explore/*.md', 'website/manuals/*.md',
'!website/manuals/faq/explore/index.md', '!website/manuals/index.md',
'!website/manuals/faq/*/index.md',
'!website/manuals/guides/*/index.md',
'website/ua/manuals/*.md',
'!website/ua/manuals/index.md',
'!website/ua/manuals/faq/*/index.md',
'!website/ua/manuals/guides/*/index.md',
'website/ru/manuals/*.md',
'!website/ru/manuals/index.md',
'!website/ru/manuals/faq/*/index.md',
'!website/ru/manuals/guides/*/index.md',
]) ])
.map(file => { .map(file => {
const content = readFileSync(file, 'utf-8') const content = readFileSync(file, 'utf-8')
@ -55,7 +67,7 @@ export const components: ComponentData[] = fg
} = data } = data
const filePath = file.substring(file.indexOf('/') + 1) const filePath = file.substring(file.indexOf('/') + 1)
const component: ComponentData = { const section: SectionData = {
path: filePath, path: filePath,
link: ensureStartingSlash(normalize(filePath)), link: ensureStartingSlash(normalize(filePath)),
repository, repository,
@ -68,24 +80,24 @@ export const components: ComponentData[] = fg
categories: Array.isArray(categories) ? categories : Array(categories), categories: Array.isArray(categories) ? categories : Array(categories),
} }
component.translator = getTranslator(translator) section.translator = getTranslator(translator)
if (items) { if (items) {
component.items = generateSidebarItem(items, component.link) section.items = generateSidebarItem(items, section.link)
} }
return component return section
}) })
.sort((a, b) => (a.text && b.text) ? a.text.localeCompare(b.text) : 0) .sort((a, b) => (a.text && b.text) ? a.text.localeCompare(b.text) : 0)
export default class DocsComponent { export default class DocsSection {
static prepareData( static prepareData(
pageData: DocsPageData, pageData: DocsPageData,
siteConfig: SiteConfig, siteConfig: SiteConfig,
): DocsPageData { ): DocsPageData {
const component = components.find(component => pageData.relativePath.startsWith(component.path.replace(/index\.md$/, ''))) const section = sections.find(section => pageData.relativePath.startsWith(section.path.replace(/index\.md$/, '')))
pageData.component = component pageData.section = section
pageData.breadcrumbs = findPath(pageData, siteConfig.userConfig) pageData.breadcrumbs = findPath(pageData, siteConfig.userConfig)
pageData.title = !pageData.frontmatter.title && pageData.breadcrumbs.length pageData.title = !pageData.frontmatter.title && pageData.breadcrumbs.length
@ -93,17 +105,17 @@ export default class DocsComponent {
: pageData.title : pageData.title
if ( if (
component section
&& !pageData.description && !pageData.description
&& pageData.component.description && pageData.section.description
) { ) {
pageData.description = pageData.component.description pageData.description = pageData.section.description
} }
return pageData return pageData
} }
} }
export { DocsComponent } export { DocsSection }
export const { prepareData } = DocsComponent export const { prepareData } = DocsSection

@ -68,6 +68,10 @@
[lang|="ru"] { [lang|="ru"] {
--vp-code-copy-copied-text-content: 'Скопировано'; --vp-code-copy-copied-text-content: 'Скопировано';
} }
[lang|="ua"] {
--vp-code-copy-copied-text-content: 'Скопійовано';
}
.dark { .dark {
--vp-c-blue-1: #7da1e9; --vp-c-blue-1: #7da1e9;

@ -1,5 +1,5 @@
import { DefaultTheme } from 'vitepress' import { DefaultTheme } from 'vitepress'
import type { ComponentData } from '../plugins/component' import type { SectionData } from '../plugins/section'
export namespace Theme { export namespace Theme {
export interface Sponsor { export interface Sponsor {
@ -10,11 +10,7 @@ export namespace Theme {
export interface Config extends DefaultTheme.Config { export interface Config extends DefaultTheme.Config {
titleSeparator?: string titleSeparator?: string
components?: Array<ComponentData> sections?: Array<SectionData>
teamSectionTitle?: string
sponsorLink?: string
sponsor?: Sponsor
} }
export interface TeamMember extends Omit<DefaultTheme.TeamMember, 'name'> { export interface TeamMember extends Omit<DefaultTheme.TeamMember, 'name'> {

@ -1,5 +1,5 @@
import type { DefaultTheme, UserConfig } from 'vitepress' import type { DefaultTheme, UserConfig } from 'vitepress'
import type { ComponentData, DocsPageData } from './plugins/component' import type { SectionData, DocsPageData } from './plugins/section'
import { normalize } from 'vitepress/dist/client/shared' import { normalize } from 'vitepress/dist/client/shared'
import { type Translator, translators } from '../../website/translators' import { type Translator, translators } from '../../website/translators'
@ -29,11 +29,11 @@ export function findPath(
path.push({ text: root.text, link: root.link }) path.push({ text: root.text, link: root.link })
} }
let tree: DefaultTheme.SidebarItem | ComponentData let tree: DefaultTheme.SidebarItem | SectionData
if (pageData.component) { if (pageData.section) {
const { title, link, items } = pageData.component const { title, link, items } = pageData.section
tree = pageData.component tree = pageData.section
path.push({ text: title, link, items }) path.push({ text: title, link, items })
} else { } else {
const sidebar = Object.entries(localeConfig.sidebar).find(([link]) => searchable.startsWith(link)) const sidebar = Object.entries(localeConfig.sidebar).find(([link]) => searchable.startsWith(link))

@ -25,7 +25,7 @@ Learn more in this [Wikipedia article](https://en.wikipedia.org/wiki/Scanlation)
Check the removed [parsers list](https://github.com/KotatsuApp/kotatsu-parsers/issues/39) first. Check the removed [parsers list](https://github.com/KotatsuApp/kotatsu-parsers/issues/39) first.
## Why was a source removed? ## Why was a source removed?
Extensions can be removed due to several reasons: Sources can be removed due to several reasons:
* Frequent website changes. * Frequent website changes.
* Image scrambling. * Image scrambling.

@ -52,7 +52,7 @@ These are general guidelines as each site has its specific undisclosed limits an
::: :::
## Widespread issue ## Widespread issue
When everyone experiences a problem, it could be with the extension or app: When everyone experiences a problem, it could be with the source or app:
1. Check open issues [for the app](https://github.com/KotatsuApp/Kotatsu/issues) and/or [**parsers**](https://github.com/KotatsuApp/kotatsu-parsers/issues). 1. Check open issues [for the app](https://github.com/KotatsuApp/Kotatsu/issues) and/or [**parsers**](https://github.com/KotatsuApp/kotatsu-parsers/issues).
1. Check closed issues ([app](https://github.com/KotatsuApp/Kotatsu/issues?q=is%3Aissue+is%3Aclosed)/[parsers](https://github.com/KotatsuApp/kotatsu-parsers/issues?q=is%3Aissue+is%3Aclosed)) in case it's resolved but not yet released. 1. Check closed issues ([app](https://github.com/KotatsuApp/Kotatsu/issues?q=is%3Aissue+is%3Aclosed)/[parsers](https://github.com/KotatsuApp/kotatsu-parsers/issues?q=is%3Aissue+is%3Aclosed)) in case it's resolved but not yet released.

@ -1,7 +1,6 @@
--- ---
title: Зробити свій внесок title: Зробити свій внесок
description: Дізнайтеся, як допомогти у перекладі або створенні програми та парсерів. description: Дізнайтеся, як допомогти у перекладі або створенні програми та парсерів.
translator: CakesTwix
lastUpdated: false lastUpdated: false
editLink: false editLink: false
prev: false prev: false

@ -3,7 +3,7 @@ title: Завантаження
description: Поширені запитання про завантаження. description: Поширені запитання про завантаження.
--- ---
# Downloads # Завантаження
Поширені запитання про завантаження. Поширені запитання про завантаження.
## Чому мої завантаження зупинилися на середині? ## Чому мої завантаження зупинилися на середині?

@ -1,6 +1,6 @@
--- ---
title: Explore title: Огляд
description: Help center of Explore section. description: Довідковий центр розділу Огляд.
lastUpdated: false lastUpdated: false
editLink: false editLink: false
prev: false prev: false

@ -1,4 +1,4 @@
--- ---
title: Local storage title: Локальне сховище
description: Frequently Asked Questions about Local storage. description: Поширені запитання про локальне сховище.
--- ---

@ -1,4 +1,4 @@
--- ---
title: Random title: Випадкові серії
description: Frequently Asked Questions about Random. description: Часті запитання про випадкові серії.
--- ---

@ -1,37 +1,37 @@
--- ---
title: Sources title: Джерела
description: Frequently Asked Questions about Sources. description: Поширені запитання про джерела.
--- ---
# Sources # Джерела
Frequently Asked Questions about Sources. Поширені запитання про джерела.
## What are some recommended sources? ## Які джерела рекомендується використовувати?
**Kotatsu** does not endorse or recommend any source, and there is no best source. **Kotatsu** не схвалює і не рекомендує жодне джерело, і найкращого джерела не існує.
Instead, we encourage users to spend some time trying out a few sources themselves and discover what sources work best for them. Натомість ми заохочуємо користувачів витратити деякий час на самостійне випробування декількох джерел і виявити, які з них найкраще підходять для них.
What works well for somebody else might not work well for you. Те, що добре працює для когось іншого, може не працювати добре для вас.
::: info Disclaimer ::: info Відмова від відповідальності
**Kotatsu** isn't responsible for slow, down, missing chapters, or subpar image quality of sources as it doesn't host content. **Kotatsu** не несе відповідальності за повільну роботу, відсутність розділів або низьку якість зображення джерел, оскільки не є хостером контенту.
::: :::
## What is a scanlator source? ## Що таке джерело сканлятора?
Non-officially licensed series are translated by scanlators, often found on their websites or [MangaDex](https://mangadex.org/). Неофіційно ліцензовані серії перекладають сканлятори, часто їх можна знайти на їхніх сайтах або на [MangaDex](https://mangadex.org/).
Learn more in this [Wikipedia article](https://en.wikipedia.org/wiki/Scanlation). Дізнайтеся більше в цій [статті Вікіпедії] (https://en.wikipedia.org/wiki/Scanlation).
## How do I request new sources? ## Як запросити нові джерела?
[Open an issue](https://github.com/KotatsuApp/kotatsu-parsers/issues) on **GitHub** if not already there. [Створіть проблему](https://github.com/KotatsuApp/kotatsu-parsers/issues) на **GitHub**, якщо вона ще не створена.
Check the removed [parsers list](https://github.com/KotatsuApp/kotatsu-parsers/issues/39) first. Спочатку перевірте [список вилучених парсерів](https://github.com/KotatsuApp/kotatsu-parsers/issues/39).
## Why was a source removed? ## Чому було видалено джерело?
Extensions can be removed due to several reasons: Парсери можуть бути видалені з кількох причин:
* Frequent website changes. * Часті зміни на сайті.
* Image scrambling. * Шифрування зображень.
* Scanlator removal request. * Запит на видалення.
* Paywall implementation. * Реалізація платного входу.
* Reverse engineering needs. * Потреби в реінжинірингу.
* Site shutdown. * Закриття сайту.
Find the list of removed sources [here](https://github.com/KotatsuApp/kotatsu-parsers/issues/39), excluding offline sites. Список вилучених джерел можна знайти [тут](https://github.com/KotatsuApp/kotatsu-parsers/issues/39).

@ -1,4 +1,4 @@
--- ---
title: Suggestions title: Рекомендації
description: Frequently Asked Questions about Suggestions. description: Поширені запитання про рекомендації.
--- ---

@ -1,15 +1,14 @@
--- ---
title: Feed title: Стрічка
titleTemplate: Frequently Asked Questions description: Поширені запитання про стрічку.
description: Frequently Asked Questions about the Feed.
--- ---
# Feed # Стрічка
Frequently Asked Questions about the Feed. Поширені запитання про стрічку.
## Why aren't series updates working? ## Чому не працюють оновлення серій?
Some Android skins (e.g., **MIUI**) aggressively save battery, potentially shutting down apps in the background. Деякі скіни Android (наприклад, **MIUI**) агресивно економлять заряд акумулятора, потенційно закриваючи програми у фоновому режимі.
Whitelist **Kotatsu** from your battery saver by going to <nav to="checking"> and tapping **Disable battery optimization**. Вилучіть **Kotatsu** з екрана економії заряду батареї, перейшовши до <nav to="checking"> і натиснувши **Вимкнути оптимізацію заряду батареї**.
If unsuccessful, refer to [Don't Kill My App](https://dontkillmyapp.com/) for how to disable specific battery-saving options for your device. Якщо це не вдасться, зверніться до [Don't Kill My App](https://dontkillmyapp.com/), щоб дізнатися, як вимкнути певні опції економії заряду акумулятора для вашого пристрою.

@ -1,19 +1,20 @@
--- ---
title: General title: Загальне
description: Frequently Asked Questions description: Поширені запитання
translator: CakesTwix
--- ---
# General # Загальне
Frequently Asked Questions Поширені запитання
## Why isn't Kotatsu on the Google Play Store? ## Чому Kotatsu немає в Google Play Маркеті?
**Kotatsu** won't be on the **Google Play Store**. **Google** might take down the app due to certain content, which the developers wishes to avoid. **Kotatsu** не буде в магазині **Google Play**. **Google** може видалити додаток через певний контент, якого розробники хотіли б уникнути.
To report **Kotatsu** copycats on the **Google Play Store**, fill out [this form](https://support.google.com/googleplay/android-developer/contact/takedown) following the steps below. Щоб повідомити про підробки **Kotatsu** в **Google Play Store**, заповніть [цю форму](https://support.google.com/googleplay/android-developer/contact/takedown) дотримуючись наведених нижче інструкцій.
:::details Steps to report Kotatsu copycats :::details Кроки для повідомлення про копії Kotatsu
1. Go to the page -> three dots menu -> Flag as inappropriate -> Other objection. 1. Перейдіть на сторінку -> меню з трьома крапками -> Позначити як недоречне -> Інше заперечення.
1. After choosing "Other objection", you may choose to put down any or all of the following: 1. Вибравши "Інше заперечення", ви можете вказати будь-яке або всі наступні заперечення:
The app infringes on the Google Play Developer Policy by The app infringes on the Google Play Developer Policy by
@ -34,16 +35,16 @@ To report **Kotatsu** copycats on the **Google Play Store**, fill out [this form
> - Apps that are improperly categorized. > - Apps that are improperly categorized.
::: :::
## Is Kotatsu available for iOS/iPadOS? ## Чи є Kotatsu на iOS/iPadOS?
There is no iOS or iPadOS version and neither are there plans for one. Версії для iOS чи iPadOS не існує і не планується.
Porting is difficult due to the separate codebases of iOS and Android apps. Портування ускладнене через окремі кодові бази додатків для iOS та Android.
Any app proclaiming to be "**Kotatsu for iOS**" is not by us and should be treated as a scam. Будь-який додаток, що проголошує себе "**Kotatsu для iOS**", не створений нами, і його слід розглядати як шахрайство.
## Can I read light novels? ## Чи можна читати ранобе?
**Kotatsu** can't read light novels; it's an image parser, not a text parser. **Kotatsu** не може читати ранобе; це аналізатор зображень, а не тексту.
## Can I stream anime? ## Чи можна дивитися аніме?
**Kotatsu** isn't designed for anime streaming. **Kotatsu** не призначений для показу аніме.
Projects using the **Kotatsu** name for anime streaming aren't affiliated with the main project. Проекти, що використовують ім'я **Kotatsu** для показу аніме, не пов'язані з основним проектом.

@ -1,18 +1,17 @@
--- ---
title: Reader title: Читання
titleTemplate: Frequently Asked Questions description: Поширені запитання про читання.
description: Frequently Asked Questions about the Reader.
--- ---
# Reader # Читання
Frequently Asked Questions about the Reader. Поширені запитання про читання.
## Why didn't the page load? ## Чому сторінка не завантажилася?
Besides network-related problems, **Kotatsu** may occasionally fail to recognize certain images. Окрім проблем, пов'язаних з мережею, **Kotatsu** іноді може не розпізнавати певні зображення.
To address this, simply exit and re-enter the reader or click **Try again** button, often resolving the issue. Щоб вирішити цю проблему, просто вийдіть і знову увійдіть у програму або натисніть кнопку **Повторити**, що часто вирішує проблему.
## Can I see two pages at once? ## Чи можу я бачити дві сторінки одночасно?
Not currently. Creating an effective dual-page reader that accommodates scanlator page inconsistencies and other complexities poses challenges. This feature may be added in the future. Створення ефективної програми для читання двох сторінок, яка враховує невідповідність сторінок та інші складнощі, є складним завданням. Ця функція може бути додана в майбутньому.
## What do all the settings do? ## Що роблять всі налаштування?
For detailed instructions, please consult the guides section on the website here. Для отримання детальних інструкцій, будь ласка, зверніться до розділу гайдів на сайті тут.

@ -1,14 +1,14 @@
--- ---
title: Settings title: Налаштування
description: Frequently Asked Questions about various app settings. description: Поширені запитання щодо різних налаштувань програми.
--- ---
# Settings # Налаштування
Frequently Asked Questions about various app settings. Поширені запитання щодо різних налаштувань програми.
## Why is taking screenshots blocked? ## Чому заблоковано створення скріншотів?
Turn off **Screenshot policy** in <nav to="reader">. Вимкніть **Політику скріншотів** у <nav to="reader">.
## What is DNS over HTTPS? ## Що таке DNS через HTTPS?
**DNS over HTTPS** (in <nav to="network">) offers secure DNS resolution through HTTPS, preventing attacks. **DNS через HTTPS** (у <nav to="network">) пропонує безпечне вирішення DNS через HTTPS, запобігаючи атакам.
Learn more [here](https://www.cloudflare.com/learning/dns/dns-over-tls/). This may help bypass some basic website blocking. Дізнайтеся більше [тут](https://www.cloudflare.com/learning/dns/dns-over-tls/). Це може допомогти обійти деякі основні блокування веб-сайтів.

@ -1,74 +1,73 @@
--- ---
title: Common issues title: Загальні проблеми
description: Facing issues with a source or the app? Here's how to tackle common challenges. description: Виникли проблеми з джерелом або додатком? Ось як вирішити найпоширеніші проблеми.
--- ---
# Common issues # Загальні проблеми
Facing issues with a source or the app? Виникли проблеми з джерелом або додатком? Ось як вирішити найпоширеніші проблеми.
Here's how to tackle common challenges.
## Basic issues ## Базові проблеми
### Slow loading ### Повільне завантаження
Sources being slow could stem from site slowness, your internet, or source-imposed rate limits/IP bans. Повільна робота джерел може бути пов'язана з повільною роботою сайту, вашого інтернету або обмеженнями швидкості, встановленими джерелом, чи заборонами на IP-адреси.
## Advanced errors ## Розширені помилки
### `Unable to resolve host` / `Connection failed` / `Failed to connect to` / `timeout` / `connection reset` ### `Unable to resolve host` / `Connection failed` / `Failed to connect to` / `timeout` / `connection reset`
These errors indicate connection issues. Possible causes include: Ці помилки вказують на проблеми зі з'єднанням. Можливі причини включають:
* Weak internet connection. * Слабке з'єднання з Інтернетом.
* App lacks internet access. * Додаток не має доступу до Інтернету.
* Your ISP has blocked the site. * Ваш провайдер заблокував сайт.
* The site is down. * Сайт не працює.
Try these solutions: Спробуйте ці рішення:
* Enable **DNS over HTTPS**. * Увімкніть **DNS через HTTPS**.
* Change network (Wi-Fi, mobile data, VPN). * Змініть мережу (Wi-Fi, мобільна передача даних, VPN).
* Reboot router. * Перезавантажте роутер.
### `java.security.cert.CertPathValidatorException` / `Chain validation failed` ### `java.security.cert.CertPathValidatorException` / `Chain validation failed`
Validation issue with source's certificate. Проблема з валідацією сертифіката джерела.
Try these solutions: Спробуйте ці рішення:
* Check expired certificate, use SSL checker. * Перевірте прострочений сертифікат, скористайтеся перевіркою SSL.
* Set correct device date and time. * Встановіть правильну дату та час на пристрої.
* Change network (Wi-Fi, mobile data, VPN). * Змініть мережу (Wi-Fi, мобільна передача даних, VPN).
* Enable **Ignore SSL errors** in <nav to="network"/> * Увімкніть **Ігнорувати помилки SSL** у <nav to="network"/>.
* Reboot device. * Перезавантажте пристрій.
## HTTP errors ## Помилки HTTP
Encountering HTTP errors? Here's what they mean and how to address them. Виникли помилки HTTP? Ось що вони означають і як їх усунути.
### `HTTP Error: 403` - Forbidden ### `HTTP Error: 403` - Forbidden
Possible reasons for this error: Можливі причини цієї помилки:
* The selected source has Cloudflare protection. Check the [Cloudflare guide](/manuals/guides/troubleshooting/#cloudflare) for solutions. * Вибране джерело має захист Cloudflare. Зверніться до [Посібника з Cloudflare] (/ua/manuals/guides/troubleshooting/#cloudflare) для вирішення проблеми.
* The source might be down, removed the series, or banned your IP. * Джерело може не працювати, видалити серію або забанити вашу IP-адресу.
> Open WebView to confirm. > Відкрийте WebView, щоб перевірити.
### `HTTP Error: 404` - Not Found ### `HTTP Error: 404` - Not Found
This error likely indicates a down source or removed series. Ця помилка, ймовірно, вказує на непрацююче джерело або видалену серію.
* Use **WebView** to verify. * Використовуйте **WebView** для перевірки.
> Consider switching to a different source for the series. > Спробуйте переключитися на інше джерело для цієї серії.
### `HTTP Error: 429` - Too Many Requests ### `HTTP Error: 429` - Too Many Requests
This error suggests the source temporarily banned your IP due to fast downloads/reads. Ця помилка означає, що джерело тимчасово заблокувало ваш IP через швидке завантаження/читання.
### `HTTP Error: 5xx` ### `HTTP Error: 5xx`
Errors like `500`, `502`, etc., indicate server-side issues on the source's end. Помилки типу `500`, `502` і т.д. вказують на проблеми на стороні сервера на стороні джерела.
[Check the source in WebView](/manuals/guides/troubleshooting/#accessing-websites-via-webview) to confirm if it's down. [Перевірте джерело у WebView](/ua/manuals/guides/troubleshooting/#accessing-websites-via-webview), щоб переконатися, що воно не працює.
### `HTTP Error: 1006` ### `HTTP Error: 1006`
This error means a temporary IP ban by the source. Ця помилка означає тимчасову заборону IP-адреси джерелом.
### `HTTP Error: 1020` ### `HTTP Error: 1020`
This error points to violating a firewall rule set by the site owner. Ця помилка вказує на порушення правил брандмауера, встановлених власником сайту.
The owner might raise Cloudflare protection or block IPs from outside their country. Власник може підвищити рівень захисту Cloudflare або заблокувати IP-адреси з-за меж своєї країни.
::: warning ::: warning Попередження
For unlisted errors or if instructions don't help, refer to [Diagnosis](/manuals/guides/troubleshooting/diagnosis). Якщо помилки не вказані в списку або якщо інструкції не допомагають, зверніться до розділу [Діагностика](/ua/manuals/guides/troubleshooting/diagnosis).
::: :::

@ -1,63 +1,62 @@
--- ---
title: Diagnosis title: Діагностика
description: Facing issues with a source or the app? Follow these steps to troubleshoot and find solutions. description: Виникли проблеми з джерелом або додатком? Виконайте ці кроки, щоб усунути несправності та знайти рішення.
--- ---
# Diagnosis # Діагностика
Facing issues with a source or the app? Виникли проблеми з джерелом або додатком? Виконайте ці кроки, щоб усунути несправності та знайти рішення.
Follow these steps to troubleshoot and find solutions.
## Первинний діагноз
## Primary diagnosis
1. **Оновити програму**: Перейдіть до <nav to="about"> і натисніть **Перевірити наявність оновлень**.
1. **Update app**: Go to <nav to="about"> and tap **Check for updates**. 1. **Оновлення серій вручну**: Перейдіть до <nav to="main_feed"> і перетягніть вниз, щоб вручну оновити проблемні серії.
1. **Manual series refresh**: Go to <nav to="main_feed"> and drag down to manually refresh problematic series. 1. **Перевірити інші серії**: Спробуйте інші серії з того самого джерела.
1. **Test other series**: Try different series from the same source. 1. **Оновити WebView**: Переконайтеся, що ваш WebView актуальний.
1. **Update WebView**: Ensure your WebView is current. 1. **Публічний WebView**: Спробуйте відкрити серію у загальнодоступному WebView. Вирішіть проблему за допомогою CAPTCHA або захисту Cloudflare, якщо це необхідно.
1. **Public WebView**: Attempt opening series in public WebView. Solve for CAPTCHA or Cloudflare protection if needed. 1. **Змінити з'єднання**: Переключити мережі (Wi-Fi, мобільні дані, VPN) і підтвердити зміну IP-адреси.
1. **Change connection**: Switch networks (Wi-Fi, mobile data, VPN) and confirm IP change. 1. **Спільна перевірка**: Попросіть інших повторити помилку.
1. **Collaborative check**: Get others to replicate the error. 1. **Статус джерела**: Перевірте статус джерела у браузері.
1. **Source status**: Verify the source's status in a browser. 1. **Кнопка повтору**: Натисніть кнопку повтору на сторінці серії.
1. **Retry button**: Look for a retry button on the series page. 1. **Розширені налаштування**: У розділі <nav to="data"> спробуйте ці параметри:
1. **Advanced settings**: Under <nav to="data">, try these options: - Очистити кеш мініатюр
- Clear thumbnails cache - Очистити кеш сторінок
- Clear page cache - Очистити кеш мережі
- Clear network cache - Очистити файли cookie
- Clear cookies - У розділі <nav to="network"> спробуйте увімкнути DNS через HTTPS
- Under <nav to="network">, try to enable DNS over HTTPS 1. **Проблеми із завантаженням**: Видаліть чергу та повторіть завантаження.
1. **Download issues**: Delete the queue and retry downloads. 1. **Перезапустіть Kotatsu**: Примусово закрити та перезапустити програму.
1. **Restart Kotatsu**: Force close and reopen the app.
Якщо будь-яке з цих рішень допоможе, перейдіть до [Персоналізована проблема](#personalized-issue).
If any of these solutions help, go to [Personalized Issue](#personalized-issue). Якщо проблема не лише у вас, перейдіть до [Поширена проблема](#widespread-issue).
If it is not just you, go to [Widespread Issue](#widespread-issue).
Якщо жодне з цих рішень не допомогло, спробуйте запитати в нашій [Telegram-групі](https://t.me/kotatsuapp).
If none of these solutions help, try asking in our [Telegram group](https://t.me/kotatsuapp).
Вкажіть версію програми, а також джерело, серію та розділ, в якому виникла проблема.
State your app version and the source, series, and chapter with the problem.
::: tip Оновлення програми може вирішити вашу проблему
::: tip An app update may fix your issue Зачекайте або перевірте оновлення додатку, якщо ви ще не зробили цього.
Wait or check for an app update if you have not already. Очікуваних дат для оновлень немає.
There are no ETAs for updates.
::: :::
## Personalized issue ## Персоналізована проблема
If you're the only one facing a problem, you might be encountering an IP ban, or other countermeasures set by website owners against programs like **Kotatsu**. Якщо ви єдиний, хто зіткнувся з проблемою, можливо, ви зіткнулися з забороною IP-адреси або іншими контрзаходами, встановленими власниками веб-сайтів проти таких програм, як **Kotatsu**.
**To minimize future issues:** **Щоб мінімізувати майбутні проблеми:**
- Avoid using downloads with the source. - Уникайте завантажень з джерела.
- Reduce the number of series in your favourites/history from that source. - Зменшіть кількість серії у вибраному/історії з цього джерела.
::: warning ::: warning Попередження
These are general guidelines as each site has its specific undisclosed limits and triggers. Це загальні рекомендації, оскільки кожен сайт має свої специфічні нерозкриті ліміти та тригери.
::: :::
## Widespread issue ## Поширена проблема
When everyone experiences a problem, it could be with the extension or app: Коли у всіх виникають проблеми, це може бути пов'язано з джерелом або додатком:
1. Check open issues [for the app](https://github.com/KotatsuApp/Kotatsu/issues) and/or [**parsers**](https://github.com/KotatsuApp/kotatsu-parsers/issues). 1. Перевірте відкриті проблеми [для додатку](https://github.com/KotatsuApp/Kotatsu/issues) та/або [**парсерів**](https://github.com/KotatsuApp/kotatsu-parsers/issues).
1. Check closed issues ([app](https://github.com/KotatsuApp/Kotatsu/issues?q=is%3Aissue+is%3Aclosed)/[parsers](https://github.com/KotatsuApp/kotatsu-parsers/issues?q=is%3Aissue+is%3Aclosed)) in case it's resolved but not yet released. 1. Перевірте закриті проблеми ([додаток](https://github.com/KotatsuApp/Kotatsu/issues?q=is%3Aissue+is%3Aclosed)/[парсери](https://github.com/KotatsuApp/kotatsu-parsers/issues?q=is%3Aissue+is%3Aclosed)), якщо вони вирішені, але ще не випущені.
1. If not found, create a new issue. 1. Якщо не знайдено, створіть нову проблему.
::: warning ::: warning Попередження
If the site itself is problematic, patience is the only solution until it becomes functional again. Якщо сайт сам по собі проблематичний, терпіння - єдине рішення, поки він не стане функціональним.
::: :::
Loading…
Cancel
Save