Merge branch 'master' of https://github.com/jpirnay/crosspoint-reader into feat-page-overlay

This commit is contained in:
jpirnay
2026-03-05 18:28:38 +01:00
33 changed files with 268 additions and 172 deletions
+6 -4
View File
@@ -274,11 +274,13 @@ bool BookMetadataCache::buildBookBin(const std::string& epubPath, const BookMeta
}
bool BookMetadataCache::cleanupTmpFiles() const {
if (Storage.exists((cachePath + tmpSpineBinFile).c_str())) {
Storage.remove((cachePath + tmpSpineBinFile).c_str());
const auto spineBinFile = cachePath + tmpSpineBinFile;
if (Storage.exists(spineBinFile.c_str())) {
Storage.remove(spineBinFile.c_str());
}
if (Storage.exists((cachePath + tmpTocBinFile).c_str())) {
Storage.remove((cachePath + tmpTocBinFile).c_str());
const auto tocBinFile = cachePath + tmpTocBinFile;
if (Storage.exists(tocBinFile.c_str())) {
Storage.remove(tocBinFile.c_str());
}
return true;
}
+19 -9
View File
@@ -144,9 +144,12 @@ std::vector<size_t> ParsedText::computeLineBreaks(const GfxRenderer& renderer, c
return {};
}
// Calculate first line indent (only for left/justified text without extra paragraph spacing)
// Calculate first line indent (only for left/justified text).
// Positive text-indent (paragraph indent) is suppressed when extraParagraphSpacing is on.
// Negative text-indent (hanging indent, e.g. margin-left:3em; text-indent:-1em) always applies —
// it is structural (positions the bullet/marker), not decorative.
const int firstLineIndent =
blockStyle.textIndent > 0 && !extraParagraphSpacing &&
blockStyle.textIndentDefined && (blockStyle.textIndent < 0 || !extraParagraphSpacing) &&
(blockStyle.alignment == CssTextAlign::Justify || blockStyle.alignment == CssTextAlign::Left)
? blockStyle.textIndent
: 0;
@@ -275,9 +278,12 @@ std::vector<size_t> ParsedText::computeHyphenatedLineBreaks(const GfxRenderer& r
const int pageWidth, const int spaceWidth,
std::vector<uint16_t>& wordWidths,
std::vector<bool>& continuesVec) {
// Calculate first line indent (only for left/justified text without extra paragraph spacing)
// Calculate first line indent (only for left/justified text).
// Positive text-indent (paragraph indent) is suppressed when extraParagraphSpacing is on.
// Negative text-indent (hanging indent, e.g. margin-left:3em; text-indent:-1em) always applies —
// it is structural (positions the bullet/marker), not decorative.
const int firstLineIndent =
blockStyle.textIndent > 0 && !extraParagraphSpacing &&
blockStyle.textIndentDefined && (blockStyle.textIndent < 0 || !extraParagraphSpacing) &&
(blockStyle.alignment == CssTextAlign::Justify || blockStyle.alignment == CssTextAlign::Left)
? blockStyle.textIndent
: 0;
@@ -443,10 +449,13 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const
const size_t lastBreakAt = breakIndex > 0 ? lineBreakIndices[breakIndex - 1] : 0;
const size_t lineWordCount = lineBreak - lastBreakAt;
// Calculate first line indent (only for left/justified text without extra paragraph spacing)
// Calculate first line indent (only for left/justified text).
// Positive text-indent (paragraph indent) is suppressed when extraParagraphSpacing is on.
// Negative text-indent (hanging indent, e.g. margin-left:3em; text-indent:-1em) always applies —
// it is structural (positions the bullet/marker), not decorative.
const bool isFirstLine = breakIndex == 0;
const int firstLineIndent =
isFirstLine && blockStyle.textIndent > 0 && !extraParagraphSpacing &&
isFirstLine && blockStyle.textIndentDefined && (blockStyle.textIndent < 0 || !extraParagraphSpacing) &&
(blockStyle.alignment == CssTextAlign::Justify || blockStyle.alignment == CssTextAlign::Left)
? blockStyle.textIndent
: 0;
@@ -485,8 +494,9 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const
? spareSpace / static_cast<int>(actualGapCount)
: 0;
// Calculate initial x position (first line starts at indent for left/justified text)
auto xpos = static_cast<uint16_t>(firstLineIndent);
// Calculate initial x position (first line starts at indent for left/justified text;
// may be negative for hanging indents, e.g. margin-left:3em; text-indent:-1em).
auto xpos = static_cast<int16_t>(firstLineIndent);
if (blockStyle.alignment == CssTextAlign::Right) {
xpos = effectivePageWidth - lineWordWidthSum - totalNaturalGaps;
} else if (blockStyle.alignment == CssTextAlign::Center) {
@@ -495,7 +505,7 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const
// Pre-calculate X positions for words
// Continuation words attach to the previous word with no space before them
std::vector<uint16_t> lineXPos;
std::vector<int16_t> lineXPos;
lineXPos.reserve(lineWordCount);
for (size_t wordIdx = 0; wordIdx < lineWordCount; wordIdx++) {
+14 -9
View File
@@ -10,10 +10,10 @@
#include "parsers/ChapterHtmlSlimParser.h"
namespace {
constexpr uint8_t SECTION_FILE_VERSION = 14;
constexpr uint8_t SECTION_FILE_VERSION = 17;
constexpr uint32_t HEADER_SIZE = sizeof(uint8_t) + sizeof(int) + sizeof(float) + sizeof(bool) + sizeof(uint8_t) +
sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(bool) + sizeof(bool) +
sizeof(uint32_t);
sizeof(uint8_t) + sizeof(uint32_t);
} // namespace
uint32_t Section::onPageComplete(std::unique_ptr<Page> page) {
@@ -36,7 +36,7 @@ uint32_t Section::onPageComplete(std::unique_ptr<Page> page) {
void Section::writeSectionFileHeader(const int fontId, const float lineCompression, const bool extraParagraphSpacing,
const uint8_t paragraphAlignment, const uint16_t viewportWidth,
const uint16_t viewportHeight, const bool hyphenationEnabled,
const bool embeddedStyle) {
const bool embeddedStyle, const uint8_t imageRendering) {
if (!file) {
LOG_DBG("SCT", "File not open for writing header");
return;
@@ -44,7 +44,7 @@ void Section::writeSectionFileHeader(const int fontId, const float lineCompressi
static_assert(HEADER_SIZE == sizeof(SECTION_FILE_VERSION) + sizeof(fontId) + sizeof(lineCompression) +
sizeof(extraParagraphSpacing) + sizeof(paragraphAlignment) + sizeof(viewportWidth) +
sizeof(viewportHeight) + sizeof(pageCount) + sizeof(hyphenationEnabled) +
sizeof(embeddedStyle) + sizeof(uint32_t),
sizeof(embeddedStyle) + sizeof(imageRendering) + sizeof(uint32_t),
"Header size mismatch");
serialization::writePod(file, SECTION_FILE_VERSION);
serialization::writePod(file, fontId);
@@ -55,13 +55,15 @@ void Section::writeSectionFileHeader(const int fontId, const float lineCompressi
serialization::writePod(file, viewportHeight);
serialization::writePod(file, hyphenationEnabled);
serialization::writePod(file, embeddedStyle);
serialization::writePod(file, imageRendering);
serialization::writePod(file, pageCount); // Placeholder for page count (will be initially 0 when written)
serialization::writePod(file, static_cast<uint32_t>(0)); // Placeholder for LUT offset
}
bool Section::loadSectionFile(const int fontId, const float lineCompression, const bool extraParagraphSpacing,
const uint8_t paragraphAlignment, const uint16_t viewportWidth,
const uint16_t viewportHeight, const bool hyphenationEnabled, const bool embeddedStyle) {
const uint16_t viewportHeight, const bool hyphenationEnabled, const bool embeddedStyle,
const uint8_t imageRendering) {
if (!Storage.openFileForRead("SCT", filePath, file)) {
return false;
}
@@ -84,6 +86,7 @@ bool Section::loadSectionFile(const int fontId, const float lineCompression, con
uint8_t fileParagraphAlignment;
bool fileHyphenationEnabled;
bool fileEmbeddedStyle;
uint8_t fileImageRendering;
serialization::readPod(file, fileFontId);
serialization::readPod(file, fileLineCompression);
serialization::readPod(file, fileExtraParagraphSpacing);
@@ -92,11 +95,13 @@ bool Section::loadSectionFile(const int fontId, const float lineCompression, con
serialization::readPod(file, fileViewportHeight);
serialization::readPod(file, fileHyphenationEnabled);
serialization::readPod(file, fileEmbeddedStyle);
serialization::readPod(file, fileImageRendering);
if (fontId != fileFontId || lineCompression != fileLineCompression ||
extraParagraphSpacing != fileExtraParagraphSpacing || paragraphAlignment != fileParagraphAlignment ||
viewportWidth != fileViewportWidth || viewportHeight != fileViewportHeight ||
hyphenationEnabled != fileHyphenationEnabled || embeddedStyle != fileEmbeddedStyle) {
hyphenationEnabled != fileHyphenationEnabled || embeddedStyle != fileEmbeddedStyle ||
imageRendering != fileImageRendering) {
file.close();
LOG_ERR("SCT", "Deserialization failed: Parameters do not match");
clearCache();
@@ -129,7 +134,7 @@ bool Section::clearCache() const {
bool Section::createSectionFile(const int fontId, const float lineCompression, const bool extraParagraphSpacing,
const uint8_t paragraphAlignment, const uint16_t viewportWidth,
const uint16_t viewportHeight, const bool hyphenationEnabled, const bool embeddedStyle,
const std::function<void()>& popupFn) {
const uint8_t imageRendering, const std::function<void()>& popupFn) {
const auto localPath = epub->getSpineItem(spineIndex).href;
const auto tmpHtmlPath = epub->getCachePath() + "/.tmp_" + std::to_string(spineIndex) + ".html";
@@ -179,7 +184,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
return false;
}
writeSectionFileHeader(fontId, lineCompression, extraParagraphSpacing, paragraphAlignment, viewportWidth,
viewportHeight, hyphenationEnabled, embeddedStyle);
viewportHeight, hyphenationEnabled, embeddedStyle, imageRendering);
std::vector<uint32_t> lut = {};
// Derive the content base directory and image cache path prefix for the parser
@@ -201,7 +206,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
epub, tmpHtmlPath, renderer, fontId, lineCompression, extraParagraphSpacing, paragraphAlignment, viewportWidth,
viewportHeight, hyphenationEnabled,
[this, &lut](std::unique_ptr<Page> page) { lut.emplace_back(this->onPageComplete(std::move(page))); },
embeddedStyle, contentBase, imageBasePath, popupFn, cssParser);
embeddedStyle, contentBase, imageBasePath, imageRendering, popupFn, cssParser);
Hyphenator::setPreferredLanguage(epub->getLanguage());
success = visitor.parseAndBuildPages();
+4 -3
View File
@@ -16,7 +16,7 @@ class Section {
void writeSectionFileHeader(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled,
bool embeddedStyle);
bool embeddedStyle, uint8_t imageRendering);
uint32_t onPageComplete(std::unique_ptr<Page> page);
public:
@@ -30,10 +30,11 @@ class Section {
filePath(epub->getCachePath() + "/sections/" + std::to_string(spineIndex) + ".bin") {}
~Section() = default;
bool loadSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle);
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle,
uint8_t imageRendering);
bool clearCache() const;
bool createSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle,
const std::function<void()>& popupFn = nullptr);
uint8_t imageRendering, const std::function<void()>& popupFn = nullptr);
std::unique_ptr<Page> loadPageFromSectionFile();
};
+1 -1
View File
@@ -74,7 +74,7 @@ bool TextBlock::serialize(FsFile& file) const {
std::unique_ptr<TextBlock> TextBlock::deserialize(FsFile& file) {
uint16_t wc;
std::vector<std::string> words;
std::vector<uint16_t> wordXpos;
std::vector<int16_t> wordXpos;
std::vector<EpdFontFamily::Style> wordStyles;
BlockStyle blockStyle;
+2 -2
View File
@@ -13,12 +13,12 @@
class TextBlock final : public Block {
private:
std::vector<std::string> words;
std::vector<uint16_t> wordXpos;
std::vector<int16_t> wordXpos;
std::vector<EpdFontFamily::Style> wordStyles;
BlockStyle blockStyle;
public:
explicit TextBlock(std::vector<std::string> words, std::vector<uint16_t> word_xpos,
explicit TextBlock(std::vector<std::string> words, std::vector<int16_t> word_xpos,
std::vector<EpdFontFamily::Style> word_styles, const BlockStyle& blockStyle = BlockStyle())
: words(std::move(words)),
wordXpos(std::move(word_xpos)),
@@ -243,7 +243,14 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
}
}
if (!src.empty()) {
// imageRendering: 0=display, 1=placeholder (alt text only), 2=suppress entirely
if (self->imageRendering == 2) {
self->skipUntilDepth = self->depth;
self->depth += 1;
return;
}
if (!src.empty() && self->imageRendering != 1) {
LOG_DBG("EHP", "Found image: src=%s", src.c_str());
{
@@ -278,8 +285,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
int displayWidth = 0;
int displayHeight = 0;
const float emSize =
static_cast<float>(self->renderer.getLineHeight(self->fontId)) * self->lineCompression;
const float emSize = static_cast<float>(self->renderer.getFontAscenderSize(self->fontId));
CssStyle imgStyle = self->cssParser ? self->cssParser->resolveStyle("img", classAttr) : CssStyle{};
// Merge inline style (e.g. style="height: 2em") so it overrides stylesheet rules
if (!styleAttr.empty()) {
@@ -505,7 +511,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
}
}
const float emSize = static_cast<float>(self->renderer.getLineHeight(self->fontId)) * self->lineCompression;
const float emSize = static_cast<float>(self->renderer.getFontAscenderSize(self->fontId));
const auto userAlignmentBlockStyle = BlockStyle::fromCssStyle(
cssStyle, emSize, static_cast<CssTextAlign>(self->paragraphAlignment), self->viewportWidth);
@@ -48,6 +48,7 @@ class ChapterHtmlSlimParser {
bool hyphenationEnabled;
const CssParser* cssParser;
bool embeddedStyle;
uint8_t imageRendering;
std::string contentBase;
std::string imageBasePath;
int imageCounter = 0;
@@ -94,8 +95,8 @@ class ChapterHtmlSlimParser {
const uint16_t viewportHeight, const bool hyphenationEnabled,
const std::function<void(std::unique_ptr<Page>)>& completePageFn,
const bool embeddedStyle, const std::string& contentBase,
const std::string& imageBasePath, const std::function<void()>& popupFn = nullptr,
const CssParser* cssParser = nullptr)
const std::string& imageBasePath, const uint8_t imageRendering = 0,
const std::function<void()>& popupFn = nullptr, const CssParser* cssParser = nullptr)
: epub(epub),
filepath(filepath),
@@ -111,6 +112,7 @@ class ChapterHtmlSlimParser {
popupFn(popupFn),
cssParser(cssParser),
embeddedStyle(embeddedStyle),
imageRendering(imageRendering),
contentBase(contentBase),
imageBasePath(imageBasePath) {}
+3 -5
View File
@@ -36,12 +36,10 @@ ContentOpfParser::~ContentOpfParser() {
if (tempItemStore) {
tempItemStore.close();
}
if (Storage.exists((cachePath + itemCacheFile).c_str())) {
Storage.remove((cachePath + itemCacheFile).c_str());
const auto itemCachePath = cachePath + itemCacheFile;
if (Storage.exists(itemCachePath.c_str())) {
Storage.remove(itemCachePath.c_str());
}
itemIndex.clear();
itemIndex.shrink_to_fit();
useItemIndex = false;
}
size_t ContentOpfParser::write(const uint8_t data) { return write(&data, 1); }
+4
View File
@@ -92,6 +92,10 @@ STR_STATUS_BAR: "Status Bar"
STR_HIDE_BATTERY: "Hide Battery %"
STR_EXTRA_SPACING: "Extra Paragraph Spacing"
STR_TEXT_AA: "Text Anti-Aliasing"
STR_IMAGES: "Images"
STR_IMAGES_DISPLAY: "Display"
STR_IMAGES_PLACEHOLDER: "Placeholder"
STR_IMAGES_SUPPRESS: "Suppress"
STR_SHORT_PWR_BTN: "Short Power Button Click"
STR_ORIENTATION: "Reading Orientation"
STR_FRONT_BTN_LAYOUT: "Front Button Layout"
+29 -6
View File
@@ -63,7 +63,7 @@ STR_MAC_ADDRESS: "MAC-Adresse:"
STR_CHECKING_WIFI: "WLAN prüfen…"
STR_ENTER_WIFI_PASSWORD: "WLAN-Passwort eingeben"
STR_ENTER_TEXT: "Text eingeben"
STR_TO_PREFIX: "bis"
STR_TO_PREFIX: "mit "
STR_CALIBRE_DISCOVERING: "Calibre finden..."
STR_CALIBRE_CONNECTING_TO: "Verbinden mit"
STR_CALIBRE_CONNECTED_TO: "Verbunden mit"
@@ -120,7 +120,7 @@ STR_SELECT_WALLPAPER: "Bildauswahl Standby"
STR_CLEAR_READING_CACHE: "Lese-Cache leeren"
STR_CALIBRE: "Calibre"
STR_USERNAME: "Benutzername"
STR_PASSWORD: "Passwort nötig"
STR_PASSWORD: "Passwort"
STR_SYNC_SERVER_URL: "Sync-Server-URL"
STR_DOCUMENT_MATCHING: "Dateizuordnung"
STR_AUTHENTICATE: "Authentifizieren"
@@ -169,7 +169,7 @@ STR_FRONT_LAYOUT_BCLR: "Zurück, Bst, L, R"
STR_FRONT_LAYOUT_LRBC: "L, R, Zurück, Bst"
STR_FRONT_LAYOUT_LBCR: "L, Zurück, Bst, R"
STR_PREV_NEXT: "Zurück/Weiter"
STR_NEXT_PREV: "Weiter/Zuürck"
STR_NEXT_PREV: "Weiter/Zurück"
STR_BOOKERLY: "Bookerly"
STR_NOTO_SANS: "Noto Sans"
STR_OPEN_DYSLEXIC: "Open Dyslexic"
@@ -236,6 +236,8 @@ STR_DOWNLOAD: "Herunterladen"
STR_RETRY: "Wiederh."
STR_YES: "Ja"
STR_NO: "Nein"
STR_SHOW: "Zeigen"
STR_HIDE: "Ausblenden"
STR_STATE_ON: "An"
STR_STATE_OFF: "Aus"
STR_NOT_SET: "Leer"
@@ -248,6 +250,21 @@ STR_CAPS_OFF: "umsch"
STR_OK_BUTTON: "OK"
STR_SLEEP_COVER_FILTER: "Standby-Coverfilter"
STR_FILTER_CONTRAST: "Kontrast"
STR_CUSTOMISE_STATUS_BAR: "Statusleiste anpassen"
STR_CHAPTER_PAGE_COUNT: "Kapitel-Seitenanzahl"
STR_BOOK_PROGRESS_PERCENTAGE: "Buchfortschritt in %"
STR_PROGRESS_BAR: "Fortschrittsbalken"
STR_PROGRESS_BAR_THICKNESS: "Balkenstärke"
STR_PROGRESS_BAR_THIN: "Dünn"
STR_PROGRESS_BAR_MEDIUM: "Mittel"
STR_PROGRESS_BAR_THICK: "Dick"
STR_BOOK: "Buch"
STR_CHAPTER: "Kapitel"
STR_EXAMPLE_CHAPTER: "Kapitel 21"
STR_EXAMPLE_BOOK: "Buchtitel"
STR_PREVIEW: "Vorschau"
STR_TITLE: "Titel"
STR_BATTERY: "Batterie"
STR_UI_THEME: "System-Design"
STR_THEME_CLASSIC: "Klassisch"
STR_THEME_LYRA: "Lyra"
@@ -280,6 +297,7 @@ STR_GO_TO_PERCENT: "Gehe zu %"
STR_GO_HOME_BUTTON: "Zum Anfang"
STR_SYNC_PROGRESS: "Fortschritt synchronisieren"
STR_DELETE_CACHE: "Buch-Cache leeren"
STR_DISPLAY_QR: "Seite als QR anzeigen"
STR_DELETE: "Löschen"
STR_CHAPTER_PREFIX: "Kapitel:"
STR_PAGES_SEPARATOR: " Seiten | "
@@ -289,7 +307,7 @@ STR_KBD_SHIFT_CAPS: "UMSCH"
STR_KBD_LOCK: "FESTST"
STR_CALIBRE_URL_HINT: "Calibre: URL um /opds ergänzen"
STR_PERCENT_STEP_HINT: "links/rechts: 1% hoch/runter: 10%"
STR_SYNCING_TIME: "Zeit synchonisieren…"
STR_SYNCING_TIME: "Zeit synchronisieren…"
STR_CALC_HASH: "Dokument-Hash berechnen…"
STR_HASH_FAILED: "Dokument-Hash fehlgeschlagen"
STR_FETCH_PROGRESS: "Externen Fortschritt abrufen..."
@@ -302,8 +320,8 @@ STR_LOCAL_LABEL: "Lokal:"
STR_PAGE_OVERALL_FORMAT: " Seite %d, %.2f%% insgesamt"
STR_PAGE_TOTAL_OVERALL_FORMAT: " Seite %d/%d, %.2f%% insgesamt"
STR_DEVICE_FROM_FORMAT: " Von: %s"
STR_APPLY_REMOTE: "Ext. Fortschritt übern."
STR_UPLOAD_LOCAL: "Lokalen Fortschritt hochl."
STR_APPLY_REMOTE: "Externen Fortschritt übernehmen"
STR_UPLOAD_LOCAL: "Lokalen Fortschritt hochladen"
STR_NO_REMOTE_MSG: "Kein externer Fortschritt"
STR_UPLOAD_PROMPT: "Aktuelle Position hochladen?"
STR_UPLOAD_SUCCESS: "Hochgeladen!"
@@ -314,3 +332,8 @@ STR_BOOK_S_STYLE: "Buch-Stil"
STR_EMBEDDED_STYLE: "Eingebetteter Stil"
STR_OPDS_SERVER_URL: "OPDS-Server-URL"
STR_SCREENSHOT_BUTTON: "Screenshot aufnehmen"
STR_FOOTNOTES: "Fußnoten"
STR_NO_FOOTNOTES: "Keine Fußnoten auf dieser Seite"
STR_LINK: "[Link]"
STR_AUTO_TURN_ENABLED: "Auto-Umblättern aktiv: "
STR_AUTO_TURN_PAGES_PER_MIN: "Auto-Umblättern (Seiten/Min.)"
+73 -49
View File
@@ -6,7 +6,7 @@ STR_CROSSPOINT: "CrossPoint"
STR_BOOTING: "Iniciando..."
STR_SLEEPING: "Suspendido"
STR_ENTERING_SLEEP: "Entrando en suspensión"
STR_BROWSE_FILES: "Explorador de Archivos"
STR_BROWSE_FILES: "Explorador de archivos"
STR_FILE_TRANSFER: "Transferir archivos"
STR_SETTINGS_TITLE: "Ajustes"
STR_CALIBRE_LIBRARY: "Biblioteca de Calibre"
@@ -46,11 +46,11 @@ STR_PRESS_ANY_CONTINUE: "Pulse cualquier botón para continuar"
STR_SELECT_HINT: "Izq./Der.: Seleccionar | OK: Confirmar"
STR_HOW_CONNECT: "¿Cómo desea conectarse?"
STR_JOIN_NETWORK: "Unirse a una red"
STR_CREATE_HOTSPOT: "Crear Punto de Acceso"
STR_CREATE_HOTSPOT: "Crear punto de acceso"
STR_JOIN_DESC: "Conectarse a una red Wi-Fi existente"
STR_HOTSPOT_DESC: "Conectarse a este dispositivo"
STR_STARTING_HOTSPOT: "Iniciando Punto de Acceso..."
STR_HOTSPOT_MODE: "Modo Punto de Acceso"
STR_STARTING_HOTSPOT: "Iniciando punto de acceso..."
STR_HOTSPOT_MODE: "Modo punto de acceso"
STR_CONNECT_WIFI_HINT: "Conecte su dispositivo a esta red Wi-Fi"
STR_OPEN_URL_HINT: "Abra esta dirección en su navegador"
STR_OR_HTTP_PREFIX: "o http://"
@@ -65,22 +65,22 @@ STR_ENTER_WIFI_PASSWORD: "Introduzca la contraseña del Wi-Fi"
STR_ENTER_TEXT: "Introduzca el texto"
STR_TO_PREFIX: "a "
STR_CALIBRE_DISCOVERING: "Buscando Calibre..."
STR_CALIBRE_CONNECTING_TO: "Conectándose a"
STR_CALIBRE_CONNECTING_TO: "Conectándose a "
STR_CALIBRE_CONNECTED_TO: "Conectado a "
STR_CALIBRE_WAITING_COMMANDS: "Esperando comandos..."
STR_CONNECTION_FAILED_RETRYING: "(Error de conexión, reintentando...)"
STR_CALIBRE_DISCONNECTED: "Calibre desconectado"
STR_CALIBRE_WAITING_TRANSFER: "Esperando transferencia..."
STR_CALIBRE_TRANSFER_HINT: "Si la transferencia falla, active \\n'Ignorar espacio libre' en la configuración del \\nPlugin Smart Device de Calibre."
STR_CALIBRE_TRANSFER_HINT: "Si la transferencia falla, active\\n\"Ignorar espacio libre\" en la configuración del\\ncomplemento SmartDevice de Calibre."
STR_CALIBRE_RECEIVING: "Recibiendo: "
STR_CALIBRE_RECEIVED: "Recibido: "
STR_CALIBRE_WAITING_MORE: "Esperando más..."
STR_CALIBRE_FAILED_CREATE_FILE: "Error al crear el archivo"
STR_CALIBRE_PASSWORD_REQUIRED: "Contraseña requerida"
STR_CALIBRE_TRANSFER_INTERRUPTED: "Transferencia interrumpida"
STR_CALIBRE_INSTRUCTION_1: "1) Instale el Plugin CrossPoint Reader"
STR_CALIBRE_INSTRUCTION_1: "1) Instale el complemento CrossPoint Reader"
STR_CALIBRE_INSTRUCTION_2: "2) Conéctese a la misma red Wi-Fi"
STR_CALIBRE_INSTRUCTION_3: "3) Desde Calibre seleccione: \"Enviar a dispositivo\""
STR_CALIBRE_INSTRUCTION_3: "3) Desde Calibre, seleccione \"Enviar a dispositivo\""
STR_CALIBRE_INSTRUCTION_4: "\"Permanezca en esta pantalla mientras se envía\""
STR_CAT_DISPLAY: "Pantalla"
STR_CAT_READER: "Lector"
@@ -92,15 +92,15 @@ STR_STATUS_BAR: "Barra de estado"
STR_HIDE_BATTERY: "Ocultar % de batería"
STR_EXTRA_SPACING: "Espaciado entre párrafos"
STR_TEXT_AA: "Suavizado de texto"
STR_SHORT_PWR_BTN: "Función especial botón Power"
STR_SHORT_PWR_BTN: "Toque corto botón encendido"
STR_ORIENTATION: "Orientación"
STR_FRONT_BTN_LAYOUT: "Diseño de los botones frontales"
STR_SIDE_BTN_LAYOUT: "Función botones laterales (Lector)"
STR_SIDE_BTN_LAYOUT: "Función botones laterales (lector)"
STR_LONG_PRESS_SKIP: "Saltar capítulo (pulsación larga)"
STR_FONT_FAMILY: "Tipografía"
STR_EXT_READER_FONT: "Tipografía externa"
STR_EXT_CHINESE_FONT: "Tipografía"
STR_EXT_UI_FONT: "Tipografía (Pantalla)"
STR_EXT_UI_FONT: "Tipografía (interfaz)"
STR_FONT_SIZE: "Tamaño"
STR_LINE_SPACING: "Interlineado"
STR_ASCII_LETTER_SPACING: "Espaciado entre letras ASCII"
@@ -126,7 +126,7 @@ STR_DOCUMENT_MATCHING: "Coincidencia de doc."
STR_AUTHENTICATE: "Autenticar"
STR_KOREADER_USERNAME: "Usuario de KOReader"
STR_KOREADER_PASSWORD: "Contraseña de KOReader"
STR_FILENAME: "Nombre del archivo"
STR_FILENAME: "Nombre de archivo"
STR_BINARY: "Binario"
STR_SET_CREDENTIALS_FIRST: "Configurar credenciales"
STR_WIFI_CONN_FAILED: "Fallo de conexión Wi-Fi"
@@ -142,8 +142,8 @@ STR_CLEAR_CACHE_WARNING_3: "Los libros deberán ser reindexados"
STR_CLEAR_CACHE_WARNING_4: "cuando se vuelvan a abrir."
STR_CLEARING_CACHE: "Borrando caché..."
STR_CACHE_CLEARED: "Caché borrada"
STR_ITEMS_REMOVED: "Elementos eliminados"
STR_FAILED_LOWER: "Error"
STR_ITEMS_REMOVED: "elementos eliminados"
STR_FAILED_LOWER: "falló"
STR_CLEAR_CACHE_FAILED: "No se pudo borrar la caché"
STR_CHECK_SERIAL_OUTPUT: "Consulte los registros del puerto serie"
STR_DARK: "Oscuro"
@@ -184,16 +184,16 @@ STR_JUSTIFY: "Justificado"
STR_ALIGN_LEFT: "Izquierda"
STR_CENTER: "Centro"
STR_ALIGN_RIGHT: "Derecha"
STR_MIN_1: "1 Minuto"
STR_MIN_5: "5 Minutos"
STR_MIN_10: "10 Minutos"
STR_MIN_15: "15 Minutos"
STR_MIN_30: "30 Minutos"
STR_PAGES_1: "1 Página"
STR_PAGES_5: "5 Páginas"
STR_PAGES_10: "10 Páginas"
STR_PAGES_15: "15 Páginas"
STR_PAGES_30: "30 Páginas"
STR_MIN_1: "1 min."
STR_MIN_5: "5 min."
STR_MIN_10: "10 min."
STR_MIN_15: "15 min."
STR_MIN_30: "30 min."
STR_PAGES_1: "1 pág."
STR_PAGES_5: "5 pág."
STR_PAGES_10: "10 pág."
STR_PAGES_15: "15 pág."
STR_PAGES_30: "30 pág."
STR_UPDATE: "Actualizar"
STR_CHECKING_UPDATE: "Verificando actualización..."
STR_NEW_UPDATE: "¡Nueva actualización disponible!"
@@ -203,20 +203,20 @@ STR_UPDATING: "Actualizando..."
STR_NO_UPDATE: "No hay actualizaciones disponibles"
STR_UPDATE_FAILED: "Fallo de actualización"
STR_UPDATE_COMPLETE: "Actualización completada"
STR_POWER_ON_HINT: "Pulse y mantenga presionado el botón de encendido para volver a encender"
STR_POWER_ON_HINT: "Reinicie manteniendo pulsado botón de encendido"
STR_EXTERNAL_FONT: "Fuente externa"
STR_BUILTIN_DISABLED: "Incorporado (Desactivado)"
STR_BUILTIN_DISABLED: "Incorporado (desactivado)"
STR_NO_ENTRIES: "No se encontraron elementos"
STR_DOWNLOADING: "Descargando..."
STR_DOWNLOAD_FAILED: "Fallo de descarga"
STR_ERROR_MSG: "Error"
STR_ERROR_MSG: "Error:"
STR_UNNAMED: "Sin nombre"
STR_NO_SERVER_URL: "No se ha configurado la URL del servidor"
STR_NO_SERVER_URL: "No se configuró URL de servidor"
STR_FETCH_FEED_FAILED: "Fallo al obtener el feed"
STR_PARSE_FEED_FAILED: "Fallo al procesar el feed"
STR_NETWORK_PREFIX: "Red: "
STR_IP_ADDRESS_PREFIX: "IP: "
STR_SCAN_QR_WIFI_HINT: "O escanee el código QR con su teléfono para conectarse a Wi-Fi."
STR_SCAN_QR_WIFI_HINT: "o lea el QR con su tfno. para conectarse al Wi-Fi."
STR_ERROR_GENERAL_FAILURE: "Error: Fallo general"
STR_ERROR_NETWORK_NOT_FOUND: "Error: Red no encontrada"
STR_ERROR_CONNECTION_TIMEOUT: "Error: Tiempo de conexión agotado"
@@ -225,7 +225,8 @@ STR_BACK: "« Atrás"
STR_EXIT: "« Salir"
STR_HOME: "« Inicio"
STR_SAVE: "« Guardar"
STR_SELECT: "Elegir"
STR_SELECT: "Selec."
STR_SELECTED: "Seleccionado"
STR_TOGGLE: "Cambiar"
STR_CONFIRM: "Confirmar"
STR_CANCEL: "Cancelar"
@@ -235,6 +236,8 @@ STR_DOWNLOAD: "Descargar"
STR_RETRY: "Reintentar"
STR_YES: "Sí"
STR_NO: "No"
STR_SHOW: "Mostrar"
STR_HIDE: "Ocultar"
STR_STATE_ON: "Activado"
STR_STATE_OFF: "Desactivado"
STR_NOT_SET: "No configurado"
@@ -247,6 +250,21 @@ STR_CAPS_OFF: "minúsculas"
STR_OK_BUTTON: "OK"
STR_SLEEP_COVER_FILTER: "Filtro de pantalla de suspensión"
STR_FILTER_CONTRAST: "Contraste"
STR_CUSTOMISE_STATUS_BAR: "Personalizar barra de estado"
STR_CHAPTER_PAGE_COUNT: "Contador pág. cap."
STR_BOOK_PROGRESS_PERCENTAGE: "Porcentaje progreso libro"
STR_PROGRESS_BAR: "Barra de progreso"
STR_PROGRESS_BAR_THICKNESS: "Grosor de barra de progreso"
STR_PROGRESS_BAR_THIN: "Fino"
STR_PROGRESS_BAR_MEDIUM: "Medio"
STR_PROGRESS_BAR_THICK: "Ancho"
STR_BOOK: "Libro"
STR_CHAPTER: "Capítulo"
STR_EXAMPLE_CHAPTER: "Capítulo 21"
STR_EXAMPLE_BOOK: "Título del libro"
STR_PREVIEW: "Previsualización"
STR_TITLE: "Título"
STR_BATTERY: "Batería"
STR_UI_THEME: "Interfaz"
STR_THEME_CLASSIC: "Clásico"
STR_THEME_LYRA: "Lyra"
@@ -269,37 +287,38 @@ STR_DEFAULT_VALUE: "Predeterminado"
STR_REMAP_PROMPT: "Pulse un botón frontal para cada función"
STR_UNASSIGNED: "Sin asignar"
STR_ALREADY_ASSIGNED: "Ya asignado"
STR_REMAP_RESET_HINT: "Botón lateral arriba: Restablecer configuración"
STR_REMAP_CANCEL_HINT: "Botón lateral abajo: Anular reconfiguración"
STR_HW_BACK_LABEL: "Atrás (Primer botón)"
STR_HW_CONFIRM_LABEL: "Confirmar (Segundo botón)"
STR_HW_LEFT_LABEL: "Izq. (Tercer botón)"
STR_HW_RIGHT_LABEL: "Der. (Cuarto botón)"
STR_REMAP_RESET_HINT: "Botón lateral arriba: restablecer configuración"
STR_REMAP_CANCEL_HINT: "Botón lateral abajo: anular reconfiguración"
STR_HW_BACK_LABEL: "Atrás (primer botón)"
STR_HW_CONFIRM_LABEL: "Confirmar (segundo botón)"
STR_HW_LEFT_LABEL: "Izq. (tercer botón)"
STR_HW_RIGHT_LABEL: "Der. (cuarto botón)"
STR_GO_TO_PERCENT: "Ir a %"
STR_GO_HOME_BUTTON: "Volver a inicio"
STR_DELETE: "Borrar"
STR_GO_HOME_BUTTON: "Volver al menú Inicio"
STR_SYNC_PROGRESS: "Sincronizar progreso de lectura"
STR_DELETE_CACHE: "Borrar caché del libro"
STR_CHAPTER_PREFIX: "Cap.:"
STR_PAGES_SEPARATOR: " Páginas |"
STR_BOOK_PREFIX: "Libro:"
STR_KBD_SHIFT: "shift"
STR_KBD_SHIFT_CAPS: "SHIFT"
STR_DELETE: "Borrar"
STR_DISPLAY_QR: "Mostrar página como QR"
STR_CHAPTER_PREFIX: "Cap.: "
STR_PAGES_SEPARATOR: " Págs. | "
STR_BOOK_PREFIX: "Libro: "
STR_KBD_SHIFT: "minús."
STR_KBD_SHIFT_CAPS: "MAYÚS."
STR_KBD_LOCK: "BLOQUEAR"
STR_CALIBRE_URL_HINT: "Para Calibre, agregue /opds a su URL"
STR_PERCENT_STEP_HINT: "Izq./Der.: 1% | Subir/Bajar: 10%"
STR_SYNCING_TIME: "Tiempo de sincronización..."
STR_CALC_HASH: "Calculando HASH del documento..."
STR_HASH_FAILED: "No se pudo calcular el HASH del documento"
STR_CALC_HASH: "Calculando hash del documento..."
STR_HASH_FAILED: "No se pudo calcular el hash del documento"
STR_FETCH_PROGRESS: "Recuperando progreso remoto..."
STR_UPLOAD_PROGRESS: "Subiendo progreso..."
STR_NO_CREDENTIALS_MSG: "No se han configurado credenciales"
STR_KOREADER_SETUP_HINT: "Configure una cuenta de KOReader en la configuración"
STR_PROGRESS_FOUND: "¡Progreso encontrado!"
STR_REMOTE_LABEL: "Remoto"
STR_LOCAL_LABEL: "Local"
STR_PAGE_OVERALL_FORMAT: "Página %d, %.2f%% Completada"
STR_PAGE_TOTAL_OVERALL_FORMAT: "Página %d / %d, %.2f%% Completada"
STR_REMOTE_LABEL: "Remoto:"
STR_LOCAL_LABEL: "Local:"
STR_PAGE_OVERALL_FORMAT: "Página %d, %.2f%% completado"
STR_PAGE_TOTAL_OVERALL_FORMAT: "Página %d / %d, %.2f%% completado"
STR_DEVICE_FROM_FORMAT: " De: %s"
STR_APPLY_REMOTE: "Aplicar progreso remoto"
STR_UPLOAD_LOCAL: "Subir progreso local"
@@ -312,4 +331,9 @@ STR_UPLOAD: "Subir"
STR_BOOK_S_STYLE: "Estilo del libro"
STR_EMBEDDED_STYLE: "Estilo integrado"
STR_OPDS_SERVER_URL: "URL del servidor OPDS"
STR_FOOTNOTES: "Pie de página"
STR_NO_FOOTNOTES: "No hay notas al pie de esta página"
STR_LINK: "[enlace]"
STR_SCREENSHOT_BUTTON: "Tomar captura de pantalla"
STR_AUTO_TURN_ENABLED: "Paso pág. automático: "
STR_AUTO_TURN_PAGES_PER_MIN: "Páginas por minuto"
+3
View File
@@ -297,6 +297,7 @@ STR_GO_TO_PERCENT: "Перейти до %"
STR_GO_HOME_BUTTON: "На головну"
STR_SYNC_PROGRESS: "Прогрес синхронізації"
STR_DELETE_CACHE: "Видалити кеш книги"
STR_DELETE: "Видалити"
STR_DISPLAY_QR: "Показати сторінку як QR-код"
STR_CHAPTER_PREFIX: "Розділ: "
STR_PAGES_SEPARATOR: " сторінок | "
@@ -334,3 +335,5 @@ STR_FOOTNOTES: "Зноски"
STR_NO_FOOTNOTES: "На цій сторінці немає зносок"
STR_LINK: "[посилання]"
STR_SCREENSHOT_BUTTON: "Знімок екрана"
STR_AUTO_TURN_ENABLED: "Автоперегортання увімк: "
STR_AUTO_TURN_PAGES_PER_MIN: "Автоперегортання (ст/хв)"