Compare commits

...

14 Commits

Author SHA1 Message Date
tom5079
0eb6d40d7e fix tag 2025-11-14 19:09:46 -08:00
tom5079
f7b9260a2b Merge pull request #189 from contigo/patch-1
Update strings.xml (zh-rTW)
2025-11-14 19:07:16 -08:00
contigo
7df09aa74b Update strings.xml (zh-rTW)
</string> 가 없는 2개 문자열을 수정
2025-10-15 11:42:01 +09:00
tom5079
b3ce36f81c Merge pull request #160 from Regu-Miabyss/master
Add Chinese(Taiwan) translation
2025-10-09 10:49:25 -07:00
tom5079
27dded11c1 Merge pull request #188 from EmiyaSyahriel/apptl-id
add Indonesian App UI translation
2025-10-09 10:49:01 -07:00
Syahriel Ibnu Irfansyah
758210658e change: polish indonesian translation a bit 2025-10-08 16:17:55 +07:00
Syahriel Ibnu Irfansyah
830d490822 change: replace "atur" with "kelola" 2025-10-08 16:15:16 +07:00
Syahriel Ibnu Irfansyah
236ce2c189 add: indonesian translation 2025-10-08 15:58:40 +07:00
tom5079
7f3f17d08e image fix 2025-03-23 10:43:17 -07:00
tom5079
72937cdd42 thumbnail fix 2025-03-23 10:31:12 -07:00
tom5079
9c878f5e44 fix image loading 2025-03-23 10:13:41 -07:00
tom5079
db928a168f fix loading 2025-03-23 09:44:53 -07:00
tom5079
0eff941d48 update README.md 2025-02-26 23:42:41 -08:00
Regu-Miabyss
a6d5336608 Add Chinese(Taiwan) translation 2024-07-19 13:36:02 +08:00
10 changed files with 607 additions and 48 deletions

View File

@@ -2,7 +2,7 @@
*Pupil, Hitomi.la viewer for Android* *Pupil, Hitomi.la viewer for Android*
![](https://img.shields.io/github/downloads/tom5079/Pupil/total) ![](https://img.shields.io/github/downloads/tom5079/Pupil/total)
[![](https://img.shields.io/github/downloads/tom5079/Pupil/5.3.17/Pupil-v5.3.17.apk?color=%234fc3f7&label=DOWNLOAD%20APP&style=for-the-badge)](https://github.com/tom5079/Pupil/releases/download/5.3.17/Pupil-v5.3.17.apk) [![](https://img.shields.io/github/downloads/tom5079/Pupil/5.3.18/Pupil-v5.3.18.apk?color=%234fc3f7&label=DOWNLOAD%20APP&style=for-the-badge)](https://github.com/tom5079/Pupil/releases/download/5.3.18/Pupil-v5.3.18.apk)
[![](https://discordapp.com/api/guilds/610452916612104194/embed.png?style=banner2)](https://discord.gg/Stj4b5v) [![](https://discordapp.com/api/guilds/610452916612104194/embed.png?style=banner2)](https://discord.gg/Stj4b5v)
# Features # Features

View File

@@ -19,7 +19,7 @@ android {
minSdk = 21 minSdk = 21
targetSdk = 35 targetSdk = 35
versionCode = 70 versionCode = 70
versionName = "5.3.18" versionName = "5.3.22"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
} }

View File

@@ -12,7 +12,7 @@
"filters": [], "filters": [],
"attributes": [], "attributes": [],
"versionCode": 70, "versionCode": 70,
"versionName": "5.3.18", "versionName": "5.3.22",
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }
], ],

View File

@@ -16,12 +16,14 @@
package xyz.quaver.pupil.hitomi package xyz.quaver.pupil.hitomi
import kotlinx.coroutines.* import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.datetime.Clock.System.now import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.Call import okhttp3.Call
import okhttp3.Callback import okhttp3.Callback
@@ -30,9 +32,7 @@ import okhttp3.Response
import xyz.quaver.pupil.client import xyz.quaver.pupil.client
import java.io.IOException import java.io.IOException
import java.net.URL import java.net.URL
import java.util.concurrent.Executors
import kotlin.coroutines.resumeWithException import kotlin.coroutines.resumeWithException
import kotlin.time.Duration.Companion.minutes
import kotlin.time.ExperimentalTime import kotlin.time.ExperimentalTime
const val protocol = "https:" const val protocol = "https:"
@@ -40,25 +40,25 @@ const val protocol = "https:"
@Serializable @Serializable
data class Artist( data class Artist(
val artist: String, val artist: String,
val url: String val url: String,
) )
@Serializable @Serializable
data class Group( data class Group(
val group: String, val group: String,
val url: String val url: String,
) )
@Serializable @Serializable
data class Parody( data class Parody(
val parody: String, val parody: String,
val url: String val url: String,
) )
@Serializable @Serializable
data class Character( data class Character(
val character: String, val character: String,
val url: String val url: String,
) )
@Serializable @Serializable
@@ -66,7 +66,7 @@ data class Tag(
val tag: String, val tag: String,
val url: String, val url: String,
val female: String? = null, val female: String? = null,
val male: String? = null val male: String? = null,
) )
@Serializable @Serializable
@@ -74,7 +74,7 @@ data class Language(
val galleryid: String, val galleryid: String,
val url: String, val url: String,
val language_localname: String, val language_localname: String,
val name: String val name: String,
) )
@Serializable @Serializable
@@ -93,7 +93,7 @@ data class GalleryInfo(
val languages: List<Language> = emptyList(), val languages: List<Language> = emptyList(),
val characters: List<Character>? = null, val characters: List<Character>? = null,
val scene_indexes: List<Int>? = emptyList(), val scene_indexes: List<Int>? = emptyList(),
val files: List<GalleryFiles> = emptyList() val files: List<GalleryFiles> = emptyList(),
) )
val json = Json { val json = Json {
@@ -104,13 +104,16 @@ val json = Json {
} }
typealias HeaderSetter = (Request.Builder) -> Request.Builder typealias HeaderSetter = (Request.Builder) -> Request.Builder
fun URL.readText(settings: HeaderSetter? = null): String { fun URL.readText(settings: HeaderSetter? = null): String {
val request = Request.Builder() val request = Request.Builder()
.url(this).let { .url(this).let {
settings?.invoke(it) ?: it settings?.invoke(it) ?: it
}.build() }.build()
return client.newCall(request).execute().also{ if (it.code() != 200) throw IOException("CODE ${it.code()}") }.body()?.use { it.string() } ?: throw IOException() return client.newCall(request).execute()
.also { if (it.code() != 200) throw IOException("CODE ${it.code()}") }.body()
?.use { it.string() } ?: throw IOException()
} }
fun URL.readBytes(settings: HeaderSetter? = null): ByteArray { fun URL.readBytes(settings: HeaderSetter? = null): ByteArray {
@@ -119,7 +122,9 @@ fun URL.readBytes(settings: HeaderSetter? = null): ByteArray {
settings?.invoke(it) ?: it settings?.invoke(it) ?: it
}.build() }.build()
return client.newCall(request).execute().also { if (it.code() != 200) throw IOException("CODE ${it.code()}") }.body()?.use { it.bytes() } ?: throw IOException() return client.newCall(request).execute()
.also { if (it.code() != 200) throw IOException("CODE ${it.code()}") }.body()
?.use { it.bytes() } ?: throw IOException()
} }
@Suppress("EXPERIMENTAL_API_USAGE") @Suppress("EXPERIMENTAL_API_USAGE")
@@ -130,7 +135,7 @@ fun getGalleryInfo(galleryID: Int) =
) )
//common.js //common.js
const val domain = "ltn.hitomi.la" const val domain = "ltn.gold-usergeneratedcontent.net"
const val galleryblockextension = ".html" const val galleryblockextension = ".html"
const val galleryblockdir = "galleryblock" const val galleryblockdir = "galleryblock"
const val nozomiextension = ".nozomi" const val nozomiextension = ".nozomi"
@@ -152,7 +157,11 @@ object gg {
mutex.withLock { mutex.withLock {
if (lastRetrieval == null || (lastRetrieval!! + 60000) < System.currentTimeMillis()) { if (lastRetrieval == null || (lastRetrieval!! + 60000) < System.currentTimeMillis()) {
val ggjs: String = suspendCancellableCoroutine { continuation -> val ggjs: String = suspendCancellableCoroutine { continuation ->
val call = client.newCall(Request.Builder().url("https://ltn.hitomi.la/gg.js").build()) val call =
client.newCall(
Request.Builder().url("https://ltn.gold-usergeneratedcontent.net/gg.js")
.build()
)
call.enqueue(object : Callback { call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) { override fun onFailure(call: Call, e: IOException) {
@@ -202,34 +211,46 @@ object gg {
refresh() refresh()
return b return b
} }
fun s(h: String): String { fun s(h: String): String {
val m = Regex("(..)(.)$").find(h) val m = Regex("(..)(.)$").find(h)
return m!!.groupValues.let { it[2] + it[1] }.toInt(16).toString(10) return m!!.groupValues.let { it[2] + it[1] }.toInt(16).toString(10)
} }
} }
suspend fun subdomainFromURL(url: String, base: String? = null) : String { suspend fun subdomainFromURL(url: String, base: String? = null, dir: String? = null): String {
var retval = "b" var retval = ""
if (!base.isNullOrBlank()) if (base.isNullOrBlank()) {
retval = base when {
dir == "webp" -> retval = "w"
dir == "avif" -> retval = "a"
}
}
val b = 16 val b = 16
val r = Regex("""/[0-9a-f]{61}([0-9a-f]{2})([0-9a-f])""") val r = Regex("""/[0-9a-f]{61}([0-9a-f]{2})([0-9a-f])""")
val m = r.find(url) ?: return "a" val m = r.find(url) ?: return ""
val g = m.groupValues.let { it[2] + it[1] }.toIntOrNull(b) val g = m.groupValues.let { it[2] + it[1] }.toIntOrNull(b)
if (g != null) { if (g != null) {
retval = (97+ gg.m(g)).toChar().toString() + retval retval = if (base.isNullOrEmpty()) {
retval + (1 + gg.m(g)).toString()
} else {
(97 + gg.m(g)).toChar().toString() + base
}
} }
return retval return retval
} }
suspend fun urlFromUrl(url: String, base: String? = null) : String { suspend fun urlFromUrl(url: String, base: String? = null, dir: String? = null): String {
return url.replace(Regex("""//..?\.hitomi\.la/"""), "//${subdomainFromURL(url, base)}.hitomi.la/") return url.replace(
Regex("""//..?\.(?:gold-usergeneratedcontent\.net|hitomi\.la)/"""),
"//${subdomainFromURL(url, base, dir)}.gold-usergeneratedcontent.net/"
)
} }
suspend fun fullPathFromHash(hash: String): String = suspend fun fullPathFromHash(hash: String): String =
@@ -238,28 +259,42 @@ suspend fun fullPathFromHash(hash: String) : String =
fun realFullPathFromHash(hash: String): String = fun realFullPathFromHash(hash: String): String =
hash.replace(Regex("""^.*(..)(.)$"""), "$2/$1/$hash") hash.replace(Regex("""^.*(..)(.)$"""), "$2/$1/$hash")
suspend fun urlFromHash(galleryID: Int, image: GalleryFiles, dir: String? = null, ext: String? = null) : String { suspend fun urlFromHash(
galleryID: Int,
image: GalleryFiles,
dir: String? = null,
ext: String? = null,
): String {
val ext = ext ?: dir ?: image.name.takeLastWhile { it != '.' } val ext = ext ?: dir ?: image.name.takeLastWhile { it != '.' }
val dir = dir ?: "images" return buildString {
return "https://a.hitomi.la/$dir/${fullPathFromHash(image.hash)}.$ext" append("https://a.gold-usergeneratedcontent.net/")
if (dir != "webp" && dir != "avif") {
append(dir)
append("/")
}
append(fullPathFromHash(image.hash))
append(".")
append(ext)
}
} }
suspend fun urlFromUrlFromHash(galleryID: Int, image: GalleryFiles, dir: String? = null, ext: String? = null, base: String? = null) = suspend fun urlFromUrlFromHash(
galleryID: Int,
image: GalleryFiles,
dir: String? = null,
ext: String? = null,
base: String? = null,
) =
if (base == "tn") if (base == "tn")
urlFromUrl("https://a.hitomi.la/$dir/${realFullPathFromHash(image.hash)}.$ext", base) urlFromUrl(
"https://a.gold-usergeneratedcontent.net/$dir/${realFullPathFromHash(image.hash)}.$ext",
base,
)
else else
urlFromUrl(urlFromHash(galleryID, image, dir, ext), base) urlFromUrl(urlFromHash(galleryID, image, dir, ext), base, dir)
suspend fun rewriteTnPaths(html: String) {
html.replace(Regex("""//tn\.hitomi\.la/[^/]+/[0-9a-f]/[0-9a-f]{2}/[0-9a-f]{64}""")) { url ->
runBlocking {
urlFromUrl(url.value, "tn")
}
}
}
suspend fun imageUrlFromImage(galleryID: Int, image: GalleryFiles, noWebp: Boolean): String { suspend fun imageUrlFromImage(galleryID: Int, image: GalleryFiles, noWebp: Boolean): String {
return urlFromUrlFromHash(galleryID, image, "webp", null, "a") return urlFromUrlFromHash(galleryID, image, "webp")
// return when { // return when {
// noWebp -> // noWebp ->
// urlFromUrlFromHash(galleryID, image) // urlFromUrlFromHash(galleryID, image)

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
~ Pupil, Hitomi.la viewer for Android
~ Copyright (C) 2020 tom5079
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<string-array name="proxy_type">
<item>Tanpa Proxy</item>
<item>HTTP</item>
<item>SOCKS</item>
</string-array>
</resources>

View File

@@ -0,0 +1,236 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="warning">Peringatan</string>
<string name="error">Kesalahan</string>
<string name="ignore">Abaikan</string>
<string name="unlimited">Tidak Terbatas</string>
<string name="copied_to_clipboard">Disalin ke papan klip</string>
<string name="channel_download">Unduh</string>
<string name="channel_download_description">Tampilkan status unduhan</string>
<string name="channel_downloader">Pengunduh</string>
<string name="channel_downloader_description">Tampilkan status pengunduh</string>
<string name="channel_update">Perbarui</string>
<string name="channel_update_description">Tampilkan kemajuan pembaruan</string>
<string name="channel_transfer">Transfer</string>
<string name="channel_transfer_description">Tampilkan kemajuan transfer data ke perangkat lain</string>
<string name="unable_to_connect">Gagal tersambung ke hitomi.la</string>
<string name="lock_corrupted">Berkas kunci rusak! Dimohon untuk menginstal ulang Pupil</string>
<string name="main_no_result">Hasil kosong</string>
<string name="unaccessible_download_folder">Dari Android 11 dan yang lebih baru, folder Unduhan yang sekarang tidak akan bisa diakses dari aplikasi luar. Pindahkan folder Unduhan?</string>
<string name="notification_denied">Izin memunculkan notifikasi dibutuhkan untuk melakukan unduhan latar belakang. Jika anda menolak notifikasi dari aplikasi ini, pembaruan dari dalam aplikasi dan unduhan latar belakang akan dinonaktifkan.</string>
<string name="main_drawer_home">Beranda</string>
<string name="main_drawer_history">Riwayat</string>
<string name="main_drawer_downloads">Diunduh</string>
<string name="main_drawer_favorite">Favorit</string>
<string name="main_drawer_group_contact_title">Kontak</string>
<string name="main_drawer_group_contact_help">Bantuan</string>
<string name="main_drawer_group_contact_homepage">Kunjungi situs apl.</string>
<string name="main_drawer_group_contact_github">Kunjungi github</string>
<string name="main_drawer_group_contact_email">Email saya!</string>
<string name="main_drawer_grouop_contact_discord">Discord</string>
<string name="main_menu_thin">Mode Tipis</string>
<string name="main_menu_sort">Urutan</string>
<string name="main_menu_sort_date_added">Tanggal Ditambahkan</string>
<string name="main_menu_sort_date_published">Tanggal Publikasi</string>
<string name="main_menu_sort_popular_today">Populer: Hari Ini</string>
<string name="main_menu_sort_popular_week">Populer: Minggu Ini</string>
<string name="main_menu_sort_popular_month">Populer: Bulan Ini</string>
<string name="main_menu_sort_popular_year">Populer: Tahun ini</string>
<string name="main_menu_sort_random">Acak</string>
<string name="main_jump_title">Lompat ke Halaman</string>
<string name="main_jump_message">Sekarang halaman: %1$d\nHalaman paling belakang: %2$d</string>
<string name="main_open_gallery_by_id">Buka Galeri dari ID</string>
<string name="reader_failed_to_find_gallery">Gagal membuka galeri</string>
<string name="main_fab_random">Buka galeri acak</string>
<string name="main_fab_cancel">Batalkan semua unduhan</string>
<string name="main_move_to_page">Pergi ke halaman %1$d</string>
<string name="main_download">UNDUH</string>
<string name="main_delete">HAPUS</string>
<string name="update_title">Pembaruan tersedia</string>
<string name="update_download_completed">Unduhan Pembaruan Selesai</string>
<string name="update_download_completed_description">Tap disini untuh memperbarui</string>
<string name="update_notification_description">Mengunduh pembaruan&#8230;</string>
<string name="update_release_note"># Catatan rilis (v%1$s)\n%2$s</string>
<string name="search_hint">Pencarian galeri</string>
<string name="search_all">Mencari seluruh galeri</string>
<string name="search_show_histories">Tampilkan riwayat</string>
<string name="search_show_tags">Tampilkan tag favorit</string>
<string name="gallery_details">Rincian</string>
<string name="gallery_thumbnails">Thumbnail</string>
<string name="gallery_related">Galeri Terkait</string>
<string name="gallery_artists">Seniman</string>
<string name="gallery_groups">Grup</string>
<string name="gallery_language">Bahasa</string>
<string name="gallery_series">Seri</string>
<string name="gallery_characters">Karakter</string>
<string name="gallery_tags">Tag</string>
<string name="galleryblock_series">Seri: %1$s</string>
<string name="galleryblock_type">Jenis: %1$s</string>
<string name="galleryblock_language">Bahasa: %1$s</string>
<!-- READER -->
<string name="reader_loading">Memuat</string>
<string name="reader_go_to_page">Ke halaman</string>
<string name="reader_fab_fullscreen">Layar penuh</string>>
<string name="reader_fab_retry">Coba lagi</string>
<string name="reader_fab_auto">Gulir dengan kedipan mata</string>
<string name="reader_fab_auto_cancel">Berhenti gulir dengan kedipan mata</string>
<string name="reader_fab_download">Unduhan latar belakang</string>
<string name="reader_fab_download_cancel">Batalkan unduhan latar belakang</string>
<string name="reader_notification_text">Mengunduh&#8230;</string>
<string name="reader_notification_complete">Unduhan selesai</string>
<string name="camera_denied">Deteksi kedipan mata tidak bisa berfungsi tanpa izin kamera</string>
<string name="no_camera">Tidak terdeteksi kamera depan di perangkat ini</string>
<!-- DOWNLOADER -->
<string name="downloader_running">Pengunduh dimulai…</string>
<!-- SETTINGS -->
<string name="settings_title">Pengaturan</string>
<string name="settings_app_version_title">Versi aplikasi (Tap untuk memeriksa pembaruan)</string>
<string name="settings_app_version_description">v%s</string>
<string name="settings_beta">Perbarui dari kanal beta</string>
<!-- SEARCH -->
<string name="settings_search_title">Pengaturan pencarian</string>
<string name="settings_galleries_per_page">Galeri per halaman</string>
<string name="settings_default_query">Kueri pencarian default</string>
<!-- SETTINGS/STORAGE -->
<string name="settings_storage">Penyimpanan</string>
<!-- SETTINGS/STORAGE / MANAGE STORAGE -->
<string name="settings_manage_storage">Kelola Penyimpanan</string>
<string name="settings_storage_usage">Sedang menggunakan %s</string>
<string name="settings_storage_usage_loading">Menghitung penggunaan penyimpanan…</string>
<string name="settings_clear_cache">Bersihkan cache</string>
<string name="settings_clear_cache_alert_message">Menghapus cache bisa mempengaruhi kecepatan memuat gambar, lanjutkan?</string>
<string name="settings_recover_downloads">Buat ulang daftar terunduh</string>
<string name="settings_clear_downloads">Bersihkan daftar unduhan</string>
<string name="settings_clear_downloads_alert_message">Ini akan menghapus semua hasil unduhan.\nLanjutkan?</string>
<string name="settings_clear_history">Hapus riwayat</string>
<string name="settings_clear_history_alert_message">Ini akan menghapus seluruh isi riwayat, lanjutkan?</string>
<string name="settings_clear_history_summary">%1$d entri riwayat disimpan</string>
<!-- SETTINGS/STORAGE / MISCELLANEOUS -->
<string name="settings_download_folder_name">Pola nama folder</string>
<string name="settings_invalid_download_folder_name">Pola nama folder mengandung karakter yang tidak sah.</string>
<string name="settings_download_folder_name_message">%s akan digantikan dengan nilai yang disesuaikan\n\n%s</string>
<string name="settings_download_folder">Folder unduhan</string>
<string name="settings_download_folder_removable">Penyimpanan Lepasan</string>
<string name="settings_download_folder_internal">Penyimpanan Internal</string>
<string name="settings_download_folder_available">%s tersedia</string>
<string name="settings_download_folder_custom">Lokasi Kustom</string>
<string name="settings_download_folder_not_writable">Folder tidak dapat ditulisi. Silahkan pilih yang lain.</string>
<string name="settings_cache_limit">Batas Besar Cache</string>
<string name="settings_nomedia_title">Sembunyikan gambar dari galeri</string>
<string name="settings_low_quality">Gambar kualitas rendah</string>
<string name="settings_low_quality_summary">Muat versi gambar kualitas rendah untuk menghemat waktu muat dan penggunaan data</string>
<string name="settings_transfer_data">Transfer data ke perangkat lain</string>
<!-- SETTINGS/APP LOCK -->
<string name="settings_app_lock">Kunci Aplikasi</string>
<string name="settings_app_lock_type">Jenis kunci aplikasi</string>
<!-- SETTINGS/NETWORKING -->
<string name="settings_networking">Jaringan</string>
<string name="settings_mirror_summary">Muat gambar dari jaringan mirror</string>
<string name="settings_proxy_title">Proxy</string>
<string name="settings_max_concurrent_download">Jumlah Unduhan Bersamaan</string>
<!-- SETTINGS/MISCELLANEOUS -->
<string name="settings_miscellaneous_title">Lain-Lain</string>
<string name="settings_tag_translation">Bahasa Tag</string>
<string name="settings_tag_translation_message">Berpartisipasi dalam terjemahan di GitHub</string>
<string name="settings_rtl">Membalik halaman dari kanan-ke-kiri</string>
<string name="settings_security_mode_title">Nyalakan mode kemananan</string>
<string name="settings_security_mode_summary">Buat tampilan tidak bisa dilihat dari aplikasi baru-baru ini dan tangkapan layar.</string>
<string name="settings_dark_mode_title">Tema gelap</string>
<string name="settings_dark_mode_summary">Jaga matamu dari sinar terang layar.</string>
<string name="settings_import_old_galleries">Impor galeri lama</string>
<string name="settings_user_id">ID Pengguna</string>
<string name="settings_oss">Info Sumber Terbuka</string>
<!-- MANAGE FAVORITES -->
<string name="settings_manage_favorites">Kelola favorit</string>
<string name="settings_backup_title">Cadangkan favorit</string>
<string name="settings_backup_failed">Gagal Mengunggah</string>
<string name="settings_backup_share">Bagikan Cadangan</string>
<string name="settings_backup_file_created">Berkas cadangan dibuat</string>
<string name="settings_restore_title">Kembalikan favorit</string>
<string name="settings_restore_failed">Gagal mengembalikan</string>
<string name="settings_restore_success">%1$d entri dikembalikan</string>
<!-- SETTINGS/APP LOCK ACTIVITY -->
<string name="settings_lock_none">Tidak ada</string>
<string name="settings_lock_pattern">Pola</string>
<string name="settings_lock_password">Kata Sandi</string>
<string name="settings_lock_biometrics">Biometrik</string>
<string name="settings_lock_fingerprint">Sidik Jari</string>
<string name="settings_lock_fingerprint_without_lock">Sidik Jari hanya bisa dipakai jika jenis kunci lain juga aktif</string>
<string name="settings_lock_enabled">Aktif</string>
<string name="settings_lock_confirm">Masukkan kunci yang sama sekali lagi untuk mengkonfirmasi</string>
<string name="settings_lock_remove_message">Hilangkan kunci?</string>
<string name="settings_lock_wrong_confirm">Kunci berbeda dari sebelumnya, silahkan coba lagi.</string>
<string name="settings_lock_fingerprint_prompt">Kunci Sidik Jari Pupil™</string>
<string name="settings_lock_fingerprint_prompt_subtitle">Kami perlu bukti bahwa anda memang ras terkuat dibumi.</string>
<!-- SETTINGS/DEFAULT QUERY DIALOG -->
<string name="default_query_dialog_title">Kelola kueri pencarian default</string>
<string name="default_query_dialog_language">Bahasa: </string>
<string name="default_query_dialog_filter_BL">Jangan tampilkan BL</string>
<string name="default_query_dialog_filter_guro">Jangan tampilkan Guro</string>
<string name="default_query_dialog_filter_loli">Saya bukan pedo</string>
<string name="default_query_dialog_language_selector_none">Apapun</string>
<string name="settings_mirror_title">Mirror</string>
<!-- PROXY DIALOG -->
<string name="proxy_dialog_type">Jenis</string>
<string name="proxy_dialog_addr_hint">Alamat</string>
<string name="proxy_dialog_username_hint">Nama Pengguna</string>
<string name="proxy_dialog_password_hint">Kata Sandi</string>
<string name="proxy_dialog_error">Nilai salah</string>
<string name="proxy_dialog_server">Server</string>
<!-- IMPORT OLD GALLERIES -->
<string name="import_old_galleries_folder_not_readable">Folder ini tidak bisa dibaca</string>
<string name="import_old_galleries_notification">Mengimpor galeri lama…</string>
<string name="import_old_galleries_notification_done">Impor selesai</string>
</resources>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Pupil, Hitomi.la viewer for Android
~ Copyright (C) 2020 tom5079
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<resources>
<string-array name="proxy_type">
<item>直接連線</item>
<item>HTTP</item>
<item>SOCKS</item>
</string-array>
</resources>

View File

@@ -0,0 +1,236 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Translate needed down here -->
<string name="warning">警告</string>
<string name="error">錯誤</string>
<string name="ignore">忽略</string>
<string name="unlimited">無限制</string>
<string name="copied_to_clipboard">已複製到剪貼簿</string>
<string name="channel_download">下載</string>
<string name="channel_download_description">展示下載狀態</string>
<string name="channel_downloader">下載器</string>
<string name="channel_downloader_description">顯示下載器狀態</string>
<string name="channel_update">更新</string>
<string name="channel_update_description">顯示更新狀態</string>
<string name="channel_transfer">轉送</string>
<string name="channel_transfer_description">顯示轉送數據到其他裝置的進度</string>
<string name="unable_to_connect">沒法與hitomi.la建立連線</string>
<string name="lock_corrupted">檔案鎖發生錯誤請重裝Pupil</string>
<string name="main_no_result">空無一物</string>
<string name="unaccessible_download_folder">從Android11及以後默認的下載資料夾沒法被外界的應用訪問。是否要改變下載目的地</string>
<string name="notification_denied">在背景下載需要通知權限。如果拒絕此權限則應用內更新和背景下載功能都會被停用。</string>
<string name="main_drawer_home">首頁</string>
<string name="main_drawer_history">歷史記錄</string>
<string name="main_drawer_downloads">下載</string>
<string name="main_drawer_favorite">收藏</string>
<string name="main_drawer_group_contact_title">聯絡</string>
<string name="main_drawer_group_contact_help">幫助</string>
<string name="main_drawer_group_contact_homepage">造訪主頁</string>
<string name="main_drawer_group_contact_github">造訪GitHub</string>
<string name="main_drawer_group_contact_email">給我傳電郵!</string>
<string name="main_drawer_grouop_contact_discord">Discord</string>
<string name="main_menu_thin">緊緻模式</string>
<string name="main_menu_sort">排序</string>
<string name="main_menu_sort_newest">最近新增</string>
<string name="main_menu_sort_popular">最有人氣</string>
<string name="main_jump_title">跳到頁面</string>
<string name="main_jump_message">現在頁面: %1$d\n最大頁面: %2$d</string>
<string name="main_open_gallery_by_id">以ID開啟相簿</string>
<string name="reader_failed_to_find_gallery">無法開啟相簿</string>
<string name="main_fab_random">隨機相簿</string>
<string name="main_fab_cancel">取消所有下載作業</string>
<string name="main_move_to_page">移動到第 %1$d 頁</string>
<string name="main_download">下載</string>
<string name="main_delete">刪除</string>
<string name="update_title">有可用更新</string>
<string name="update_download_completed">下載已完成</string>
<string name="update_download_completed_description">按此更新</string>
<string name="update_notification_description">正下載更新&#8230;</string>
<string name="update_release_note"># Release附註(v%1$s)\n%2$s</string>
<string name="search_hint">搜尋相簿</string>
<string name="search_all">搜尋所有相簿</string>
<string name="search_show_histories">顯示歷史</string>
<string name="search_show_tags">顯示收藏的標籤</string>
<string name="gallery_details">詳情</string>
<string name="gallery_thumbnails">縮圖</string>
<string name="gallery_related">有關聯的相簿</string>
<string name="gallery_artists">藝術家</string>
<string name="gallery_groups">團體</string>
<string name="gallery_language">語言</string>
<string name="gallery_series">系列</string>
<string name="gallery_characters">角色</string>
<string name="gallery_tags">標籤</string>
<string name="galleryblock_series">系列: %1$s</string>
<string name="galleryblock_type">類別: %1$s</string>
<string name="galleryblock_language">語言: %1$s</string>
<string name="galleryblock_pagecount" translatable="false">%dP</string>
<!-- READER -->
<string name="reader_loading">加載中</string>
<string name="reader_go_to_page">轉到頁面</string>
<string name="reader_fab_fullscreen">全螢幕</string>>
<string name="reader_fab_retry">重試</string>
<string name="reader_fab_auto">眨眼捲動</string>
<string name="reader_fab_auto_cancel">眨眼停止捲動</string>
<string name="reader_fab_download">背景下載</string>
<string name="reader_fab_download_cancel">取消背景下載</string>
<string name="reader_notification_text">正下載&#8230;</string>
<string name="reader_notification_complete">下載完成</string>
<string name="camera_denied">權限遭到拒絕,眨眼捲動無法運作。</string>
<string name="no_camera">這臺裝置沒有前置攝像頭。</string>
<!-- DOWNLOADER -->
<string name="downloader_running">下載器運行中…</string>
<!-- SETTINGS -->
<string name="settings_title">設定</string>
<string name="settings_app_version_title">應用版本(點選以更新)</string>
<string name="settings_app_version_description">v%s</string>
<string name="settings_beta">從Beta頻道更新</string>
<!-- SEARCH -->
<string name="settings_search_title">搜尋設定</string>
<string name="settings_galleries_per_page">每頁展示相簿數量</string>
<string name="settings_default_query">預設查詢</string>
<!-- SETTINGS/STORAGE -->
<string name="settings_storage">存儲位置</string>
<!-- SETTINGS/STORAGE / MANAGE STORAGE -->
<string name="settings_manage_storage">管理存儲位置</string>
<string name="settings_storage_usage">現正使用 %s</string>
<string name="settings_storage_usage_loading">計算存儲用量…</string>
<string name="settings_clear_cache">清除快取</string>
<string name="settings_clear_cache_alert_message">快取清除後會影響影像載入速度,確定嗎?</string>
<string name="settings_recover_downloads">重建下載資料庫</string>
<string name="settings_clear_downloads">清除下載</string>
<string name="settings_clear_downloads_alert_message">這會刪掉所有下載相簿。\n你要繼續嗎</string>
<string name="settings_clear_history">清除歷史記錄</string>
<string name="settings_clear_history_alert_message">你想清除歷史記錄嗎?</string>
<string name="settings_clear_history_summary">有 %1$d 條歷史記錄</string>
<!-- SETTINGS/STORAGE / MISCELLANEOUS -->
<string name="settings_download_folder_name">資料夾命名模式</string>
<string name="settings_invalid_download_folder_name">有無效的字元!</string>
<string name="settings_download_folder_name_message">%s 會被替換成對應的字元\n\n%s</string>
<string name="settings_download_folder">下載資料夾</string>
<string name="settings_download_folder_removable">行動儲存</string>
<string name="settings_download_folder_internal">內置儲存</string>
<string name="settings_download_folder_available">%s 可用</string>
<string name="settings_download_folder_custom">自訂位置</string>
<string name="settings_download_folder_not_writable">此資料夾為只讀。請重新選擇另一個。</string>
<string name="settings_cache_limit">快取上限</string>
<string name="settings_nomedia_title">在相簿中隱藏影像</string>
<string name="settings_low_quality">低質影像</string>
<string name="settings_low_quality_summary">載入低質影像以改善載入速度和流量用量。</string>
<string name="settings_transfer_data">轉移數據到其他裝置</string>
<!-- SETTINGS/APP LOCK -->
<string name="settings_app_lock">應用鎖</string>
<string name="settings_app_lock_type">鎖定方式</string>
<!-- SETTINGS/NETWORKING -->
<string name="settings_networking">網路</string>
<string name="settings_mirror_summary">從映像站載入影像</string>
<string name="settings_proxy_title">代理</string>
<string name="settings_max_concurrent_download">並發下載數</string>
<!-- SETTINGS/MISCELLANEOUS -->
<string name="settings_miscellaneous_title">雜項</string>
<string name="settings_tag_translation">標籤語言</string>
<string name="settings_tag_translation_message">在GitHub上貢獻翻譯</string>
<string name="settings_rtl">從右至左翻頁</string>
<string name="settings_security_mode_title">啟用安全模式</string>
<string name="settings_security_mode_summary">啟用安全模式以在最近應用程式列表中隱藏螢幕內容</string>
<string name="settings_dark_mode_title">暗黑模式</string>
<string name="settings_dark_mode_summary">不要讓光亮瞎了你的眼!</string>
<string name="settings_import_old_galleries">匯入以前的相簿</string>
<string name="settings_user_id">用戶ID</string>
<string name="settings_oss">開放原始碼提示</string>
<!-- MANAGE FAVORITES -->
<string name="settings_manage_favorites">管理收藏夾</string>
<string name="settings_backup_title">備份收藏夾</string>
<string name="settings_backup_failed">上載失敗</string>
<string name="settings_backup_share">分享備份</string>
<string name="settings_backup_file_created">備份檔已創建</string>
<string name="settings_restore_title">還原收藏夾</string>
<string name="settings_restore_failed">還原失敗</string>
<string name="settings_restore_success">%1$d 個條目已恢復</string>
<!-- SETTINGS/APP LOCK ACTIVITY -->
<string name="settings_lock_none"></string>
<string name="settings_lock_pattern">圖形</string>
<string name="settings_lock_pin" translatable="false">PIN</string>
<string name="settings_lock_password">密碼</string>
<string name="settings_lock_biometrics">生物辨識</string>
<string name="settings_lock_fingerprint">指紋辨識</string>
<string name="settings_lock_fingerprint_without_lock">只有在啟用其他鎖定方式後才能啟用指紋。</string>
<string name="settings_lock_fingerprint_prompt">Pupil Fingerprint Lock™</string>
<string name="settings_lock_enabled">已啟用</string>
<string name="settings_lock_confirm">重複一次以確認</string>
<string name="settings_lock_remove_message">你想要移除鎖定嗎?</string>
<string name="settings_lock_wrong_confirm">兩次不匹配,請重試。</string>
<!-- SETTINGS/DEFAULT QUERY DIALOG -->
<string name="default_query_dialog_title">設定預設查詢</string>
<string name="default_query_dialog_language">語言: </string>
<string name="default_query_dialog_filter_BL">過濾 BL</string>
<string name="default_query_dialog_filter_guro">過濾 Guro</string>
<string name="default_query_dialog_filter_loli">合法18+模式</string>
<string name="default_query_dialog_language_selector_none">任何的</string>
<string name="settings_mirror_title">映像站</string>
<!-- PROXY DIALOG -->
<string name="proxy_dialog_type">類型</string>
<string name="proxy_dialog_addr_hint">位址</string>
<string name="proxy_dialog_port_hint"></string>
<string name="proxy_dialog_username_hint">使用者名稱</string>
<string name="proxy_dialog_password_hint">密碼</string>
<string name="proxy_dialog_error">錯誤的值</string>
<string name="proxy_dialog_server">伺服器</string>
<!-- IMPORT OLD GALLERIES -->
<string name="import_old_galleries_folder_not_readable">無法讀取該資料夾</string>
<string name="import_old_galleries_notification">匯入舊的相簿…</string>
<string name="import_old_galleries_notification_text" translatable="false">%1$d/%2$d</string>
<string name="import_old_galleries_notification_done">匯入完畢</string>
<string name="settings_lock_fingerprint_prompt_subtitle">喔靠,重試一次吧</string>
</resources>