xkcd: add more translations (#9793)
* Spanish * French * Russian * Korean
This commit is contained in:
		
							parent
							
								
									e210beeca4
								
							
						
					
					
						commit
						8c16b03bb9
					
				@ -6,7 +6,7 @@ ext {
 | 
			
		||||
    extName = 'xkcd'
 | 
			
		||||
    pkgNameSuffix = 'all.xkcd'
 | 
			
		||||
    extClass = '.XkcdFactory'
 | 
			
		||||
    extVersionCode = 11
 | 
			
		||||
    extVersionCode = 12
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
apply from: "$rootDir/common.gradle"
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@ open class Xkcd(
 | 
			
		||||
    protected open val creator = "Randall Munroe"
 | 
			
		||||
 | 
			
		||||
    protected open val synopsis =
 | 
			
		||||
        "A webcomic of romance, sarcasm, math and language"
 | 
			
		||||
        "A webcomic of romance, sarcasm, math and language."
 | 
			
		||||
 | 
			
		||||
    protected open val interactiveText =
 | 
			
		||||
        "To experience the interactive version of this comic," +
 | 
			
		||||
@ -47,6 +47,25 @@ open class Xkcd(
 | 
			
		||||
 | 
			
		||||
    protected open fun String.numbered(number: Any) = "$number - $this"
 | 
			
		||||
 | 
			
		||||
    // TODO: maybe use BreakIterator
 | 
			
		||||
    protected fun wordWrap(title: String, altText: String) = buildString {
 | 
			
		||||
        title.split(' ').forEachIndexed { i, w ->
 | 
			
		||||
            if (i != 0 && i % 7 == 0) append("\n")
 | 
			
		||||
            append(w).append(' ')
 | 
			
		||||
        }
 | 
			
		||||
        append("\n\n")
 | 
			
		||||
 | 
			
		||||
        var charCount = 0
 | 
			
		||||
        altText.replace("\r\n", " ").split(' ').forEach { w ->
 | 
			
		||||
            if (charCount > 25) {
 | 
			
		||||
                append("\n")
 | 
			
		||||
                charCount = 0
 | 
			
		||||
            }
 | 
			
		||||
            append(w).append(' ')
 | 
			
		||||
            charCount += w.length + 1
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    final override fun fetchPopularManga(page: Int) =
 | 
			
		||||
        SManga.create().apply {
 | 
			
		||||
            title = name
 | 
			
		||||
@ -88,27 +107,7 @@ open class Xkcd(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // create a text image for the alt text
 | 
			
		||||
        val titleWords = img.attr("alt").split(' ')
 | 
			
		||||
        val altTextWords = img.attr("title").split(' ')
 | 
			
		||||
 | 
			
		||||
        // TODO: maybe use BreakIterator
 | 
			
		||||
        val text = buildString {
 | 
			
		||||
            titleWords.forEachIndexed { i, w ->
 | 
			
		||||
                if (i != 0 && i % 7 == 0) append("\n")
 | 
			
		||||
                append(w).append(' ')
 | 
			
		||||
            }
 | 
			
		||||
            append("\n\n")
 | 
			
		||||
 | 
			
		||||
            var charCount = 0
 | 
			
		||||
            altTextWords.forEach { w ->
 | 
			
		||||
                if (charCount > 25) {
 | 
			
		||||
                    append("\n")
 | 
			
		||||
                    charCount = 0
 | 
			
		||||
                }
 | 
			
		||||
                append(w).append(' ')
 | 
			
		||||
                charCount += w.length + 1
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        val text = wordWrap(img.attr("alt"), img.attr("title"))
 | 
			
		||||
 | 
			
		||||
        return listOf(Page(0, "", image), Page(1, "", text.image()))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,19 @@
 | 
			
		||||
package eu.kanade.tachiyomi.extension.all.xkcd
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.extension.all.xkcd.translations.XkcdES
 | 
			
		||||
import eu.kanade.tachiyomi.extension.all.xkcd.translations.XkcdFR
 | 
			
		||||
import eu.kanade.tachiyomi.extension.all.xkcd.translations.XkcdKO
 | 
			
		||||
import eu.kanade.tachiyomi.extension.all.xkcd.translations.XkcdRU
 | 
			
		||||
import eu.kanade.tachiyomi.extension.all.xkcd.translations.XkcdZH
 | 
			
		||||
import eu.kanade.tachiyomi.source.SourceFactory
 | 
			
		||||
 | 
			
		||||
class XkcdFactory : SourceFactory {
 | 
			
		||||
    override fun createSources() = listOf(
 | 
			
		||||
        Xkcd("https://xkcd.com", "en"),
 | 
			
		||||
        XkcdES(),
 | 
			
		||||
        XkcdZH(),
 | 
			
		||||
        XkcdFR(),
 | 
			
		||||
        XkcdRU(),
 | 
			
		||||
        XkcdKO(),
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
package eu.kanade.tachiyomi.extension.all.xkcd.translations
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.extension.all.xkcd.Xkcd
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.SChapter
 | 
			
		||||
import eu.kanade.tachiyomi.util.asJsoup
 | 
			
		||||
import okhttp3.Response
 | 
			
		||||
 | 
			
		||||
class XkcdES : Xkcd("https://es.xkcd.com", "es") {
 | 
			
		||||
    override val synopsis =
 | 
			
		||||
        "Un webcómic sobre romance, sarcasmo, mates y lenguaje."
 | 
			
		||||
 | 
			
		||||
    // Google translated, sorry
 | 
			
		||||
    override val interactiveText =
 | 
			
		||||
        "Para experimentar la versión interactiva de este cómic," +
 | 
			
		||||
            "\nábralo en WebView/navegador."
 | 
			
		||||
 | 
			
		||||
    override val chapterListSelector = "#archive-ul > ul > li > a"
 | 
			
		||||
 | 
			
		||||
    override val imageSelector = "#middleContent .strip"
 | 
			
		||||
 | 
			
		||||
    override fun chapterListParse(response: Response) =
 | 
			
		||||
        response.asJsoup().select(chapterListSelector).mapIndexed { idx, el ->
 | 
			
		||||
            SChapter.create().apply {
 | 
			
		||||
                name = el.text()
 | 
			
		||||
                // convert relative path to absolute
 | 
			
		||||
                url = el.attr("href").substring(2)
 | 
			
		||||
                // not accurate to the original ¯\_(ツ)_/¯
 | 
			
		||||
                chapter_number = idx + 1f
 | 
			
		||||
                // no dates available
 | 
			
		||||
                date_upload = 0L
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override fun String.numbered(number: Any) =
 | 
			
		||||
        throw UnsupportedOperationException("Not used")
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,46 @@
 | 
			
		||||
package eu.kanade.tachiyomi.extension.all.xkcd.translations
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.extension.all.xkcd.Xkcd
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.Page
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.SChapter
 | 
			
		||||
import eu.kanade.tachiyomi.util.asJsoup
 | 
			
		||||
import okhttp3.Response
 | 
			
		||||
 | 
			
		||||
class XkcdFR : Xkcd("https://xkcd.lapin.org", "fr") {
 | 
			
		||||
    override val archive = "/tous-episodes.php"
 | 
			
		||||
 | 
			
		||||
    override val synopsis =
 | 
			
		||||
        "Un webcomic sarcastique qui parle de romance, de maths et de langage."
 | 
			
		||||
 | 
			
		||||
    override val chapterListSelector = "#content .s > a:not(:last-of-type)"
 | 
			
		||||
 | 
			
		||||
    override val imageSelector = "#content .s"
 | 
			
		||||
 | 
			
		||||
    override fun String.numbered(number: Any) = "$number. $this"
 | 
			
		||||
 | 
			
		||||
    override fun chapterListParse(response: Response) =
 | 
			
		||||
        response.asJsoup().select(chapterListSelector).map {
 | 
			
		||||
            SChapter.create().apply {
 | 
			
		||||
                url = "/" + it.attr("href")
 | 
			
		||||
                val number = url.substringAfter('=')
 | 
			
		||||
                name = it.text().numbered(number)
 | 
			
		||||
                chapter_number = number.toFloat()
 | 
			
		||||
                // no dates available
 | 
			
		||||
                date_upload = 0L
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override fun pageListParse(response: Response) =
 | 
			
		||||
        response.asJsoup().selectFirst(imageSelector).let {
 | 
			
		||||
            // no interactive comics here
 | 
			
		||||
            val img = it.child(2).child(0).child(0)
 | 
			
		||||
 | 
			
		||||
            // create a text image for the alt text
 | 
			
		||||
            val text = wordWrap(it.child(0).text(), img.attr("alt"))
 | 
			
		||||
 | 
			
		||||
            listOf(Page(0, "", img.attr("abs:src")), Page(1, "", text.image()))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override val interactiveText: String
 | 
			
		||||
        get() = throw UnsupportedOperationException("Not used")
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,50 @@
 | 
			
		||||
package eu.kanade.tachiyomi.extension.all.xkcd.translations
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.extension.all.xkcd.Xkcd
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.Page
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.SChapter
 | 
			
		||||
import eu.kanade.tachiyomi.util.asJsoup
 | 
			
		||||
import okhttp3.Response
 | 
			
		||||
 | 
			
		||||
class XkcdKO : Xkcd("https://xkcdko.com", "ko") {
 | 
			
		||||
    override val creator = "랜들 먼로"
 | 
			
		||||
 | 
			
		||||
    override val synopsis = "사랑, 풍자, 수학, 그리고 언어에 관한 웹 만화."
 | 
			
		||||
 | 
			
		||||
    // Google translated, sorry
 | 
			
		||||
    override val interactiveText =
 | 
			
		||||
        "이 만화의 대화형 버전을 경험하려면\nWebView/브라우저에서 엽니다."
 | 
			
		||||
 | 
			
		||||
    override val altTextUrl = CJK_ALT_TEXT_URL
 | 
			
		||||
 | 
			
		||||
    override val chapterListSelector = "#comicList > ol > li > a"
 | 
			
		||||
 | 
			
		||||
    override fun chapterListParse(response: Response) =
 | 
			
		||||
        response.asJsoup().select(chapterListSelector).map {
 | 
			
		||||
            SChapter.create().apply {
 | 
			
		||||
                url = it.attr("href")
 | 
			
		||||
                val number = it.attr("title")
 | 
			
		||||
                name = it.text().numbered(number)
 | 
			
		||||
                chapter_number = number.toFloat()
 | 
			
		||||
                // no dates available
 | 
			
		||||
                date_upload = 0L
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override fun pageListParse(response: Response): List<Page> {
 | 
			
		||||
        // if the img tag is empty then it is an interactive comic
 | 
			
		||||
        val img = response.asJsoup().selectFirst(imageSelector)
 | 
			
		||||
            ?: return listOf(Page(0, "", interactiveText.image()))
 | 
			
		||||
 | 
			
		||||
        // if an HD image is available it'll be the srcset attribute
 | 
			
		||||
        val image = when {
 | 
			
		||||
            !img.hasAttr("srcset") -> img.attr("abs:src")
 | 
			
		||||
            else -> img.attr("abs:srcset").substringBefore(' ')
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // create a text image for the alt text
 | 
			
		||||
        val text = img.attr("alt") + "\n\n" + img.attr("title")
 | 
			
		||||
 | 
			
		||||
        return listOf(Page(0, "", image), Page(1, "", text.image()))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,48 @@
 | 
			
		||||
package eu.kanade.tachiyomi.extension.all.xkcd.translations
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.extension.all.xkcd.Xkcd
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.Page
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.SChapter
 | 
			
		||||
import eu.kanade.tachiyomi.util.asJsoup
 | 
			
		||||
import okhttp3.Response
 | 
			
		||||
 | 
			
		||||
class XkcdRU : Xkcd("https://xkcd.ru", "ru") {
 | 
			
		||||
    override val archive = "/img"
 | 
			
		||||
 | 
			
		||||
    override val creator = "Рэндел Манро"
 | 
			
		||||
 | 
			
		||||
    override val synopsis = "о романтике, сарказме, математике и языке"
 | 
			
		||||
 | 
			
		||||
    override val altTextUrl = super.altTextUrl.replace("museo", "noto")
 | 
			
		||||
 | 
			
		||||
    override val chapterListSelector = ".main > a"
 | 
			
		||||
 | 
			
		||||
    override val imageSelector = ".main"
 | 
			
		||||
 | 
			
		||||
    override fun String.numbered(number: Any) = "$number: $this"
 | 
			
		||||
 | 
			
		||||
    override fun chapterListParse(response: Response) =
 | 
			
		||||
        response.asJsoup().select(chapterListSelector).map {
 | 
			
		||||
            SChapter.create().apply {
 | 
			
		||||
                url = it.attr("href")
 | 
			
		||||
                name = it.child(0).attr("title")
 | 
			
		||||
                chapter_number = url.removeSurrounding("/").toFloat()
 | 
			
		||||
                // no dates available
 | 
			
		||||
                date_upload = 0L
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override fun pageListParse(response: Response) =
 | 
			
		||||
        response.asJsoup().selectFirst(imageSelector).let {
 | 
			
		||||
            // no interactive comics here
 | 
			
		||||
            val img = it.child(5).child(0)
 | 
			
		||||
 | 
			
		||||
            // create a text image for the alt text
 | 
			
		||||
            val text = wordWrap(img.attr("alt"), it.child(7).text())
 | 
			
		||||
 | 
			
		||||
            listOf(Page(0, "", img.attr("abs:src")), Page(1, "", text.image()))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override val interactiveText: String
 | 
			
		||||
        get() = throw UnsupportedOperationException("Not used")
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user