mirror of
https://github.com/crosspoint-reader/crosspoint-reader.git
synced 2026-08-13 14:21:57 -07:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27c4be8a34 |
No files matched your search
+2
-1
@@ -29,5 +29,6 @@ lib/EpdFont/scripts/output/
|
||||
/.dummy
|
||||
/CMakeLists.txt
|
||||
/dependencies.lock
|
||||
/sdkconfig.*
|
||||
/sdkconfig.default
|
||||
/sdkconfig.defaults
|
||||
sdkconfig.sticky
|
||||
@@ -153,7 +153,6 @@ To convert your own TrueType/OpenType fonts:
|
||||
| `armenian` | Armenian |
|
||||
| `ethiopic` | Ethiopic + Extended |
|
||||
| `vietnamese` | Vietnamese subset (ơ/ư and combining marks) |
|
||||
| `ipa-chars` | IPA Extensions + Spacing Modifier Letters (phonetic transcription) |
|
||||
| `punctuation` | General punctuation (U+2000–U+206F) |
|
||||
| `cjk` | CJK Unified Ideographs + Hiragana + Katakana + Fullwidth |
|
||||
| `hangul` | Korean Hangul syllables + Jamo + Compatibility Jamo |
|
||||
|
||||
+74
-19
@@ -99,8 +99,11 @@ void SdCardFont::freeStyleMiniData(PerStyle& s) {
|
||||
s.miniIntervals = nullptr;
|
||||
delete[] s.miniGlyphs;
|
||||
s.miniGlyphs = nullptr;
|
||||
delete[] s.miniBitmap;
|
||||
s.miniBitmap = nullptr;
|
||||
for (auto& chunk : s.miniBitmapChunks) {
|
||||
delete[] chunk;
|
||||
chunk = nullptr;
|
||||
}
|
||||
s.miniBitmapChunkCount = 0;
|
||||
s.miniIntervalCount = 0;
|
||||
s.miniGlyphCount = 0;
|
||||
s.miniIntervalCapacity = 0;
|
||||
@@ -1010,30 +1013,66 @@ int SdCardFont::prewarmStyle(uint8_t styleIdx, const uint32_t* codepoints, uint3
|
||||
totalBitmapSize += s.miniGlyphs[i].dataLength;
|
||||
}
|
||||
|
||||
if (!ensureArrayCapacity(s.miniBitmap, s.miniBitmapCapacity, totalBitmapSize)) {
|
||||
LOG_ERR("SDCF", "Failed to allocate mini bitmap (%u bytes) for style %u", totalBitmapSize, styleIdx);
|
||||
delete[] readOrder;
|
||||
delete[] mappings;
|
||||
freeStyleMiniData(s);
|
||||
return static_cast<int>(cpCount);
|
||||
}
|
||||
s.miniBitmapUsed = totalBitmapSize; // underuse-hysteresis signal for resetStyleMiniData
|
||||
|
||||
// Read bitmap data sorted by file offset
|
||||
std::sort(readOrder, readOrder + validCount,
|
||||
[&](uint32_t a, uint32_t b) { return s.miniGlyphs[a].dataOffset < s.miniGlyphs[b].dataOffset; });
|
||||
|
||||
uint32_t miniBitmapOffset = 0;
|
||||
// Assemble the bitmap arena from on-demand 4 KB chunks (see MINI_BM_CHUNK_*).
|
||||
// `span` is the running virtual offset into the arena; each glyph is placed
|
||||
// wholly within one chunk, skipping past a boundary rather than straddling it.
|
||||
// glyph.dataOffset becomes the virtual offset, decoded at render time by
|
||||
// miniGlyphBitmap(). Chunks are allocated only as span reaches them, so a
|
||||
// sparse page never allocates the full ceiling.
|
||||
uint32_t span = 0;
|
||||
uint32_t lastBitmapEnd = UINT32_MAX;
|
||||
for (uint32_t i = 0; i < validCount; i++) {
|
||||
uint32_t mapIdx = readOrder[i];
|
||||
EpdGlyph& glyph = s.miniGlyphs[mapIdx];
|
||||
const uint32_t len = glyph.dataLength;
|
||||
|
||||
if (glyph.dataLength == 0) {
|
||||
glyph.dataOffset = miniBitmapOffset;
|
||||
if (len == 0) {
|
||||
glyph.dataOffset = span;
|
||||
continue;
|
||||
}
|
||||
if (len > MINI_BM_CHUNK_SIZE) {
|
||||
// A single glyph larger than one chunk cannot be placed. Real fonts never
|
||||
// hit this (a 4 KB 2bpp glyph would be enormous); bail rather than corrupt.
|
||||
LOG_ERR("SDCF", "Prewarm: glyph %u B exceeds chunk %u B (style %u)", len, MINI_BM_CHUNK_SIZE, styleIdx);
|
||||
file.close();
|
||||
delete[] readOrder;
|
||||
delete[] mappings;
|
||||
freeStyleMiniData(s);
|
||||
return static_cast<int>(cpCount);
|
||||
}
|
||||
|
||||
// Skip to the next chunk boundary if this glyph would straddle one.
|
||||
const uint32_t within = span & (MINI_BM_CHUNK_SIZE - 1);
|
||||
if (within != 0 && within + len > MINI_BM_CHUNK_SIZE) {
|
||||
span += MINI_BM_CHUNK_SIZE - within;
|
||||
}
|
||||
const uint32_t chunkIdx = span >> MINI_BM_CHUNK_SHIFT;
|
||||
if (chunkIdx >= MINI_BM_MAX_CHUNKS) {
|
||||
LOG_ERR("SDCF", "Prewarm: mini bitmap needs > %u chunks (style %u)", MINI_BM_MAX_CHUNKS, styleIdx);
|
||||
file.close();
|
||||
delete[] readOrder;
|
||||
delete[] mappings;
|
||||
freeStyleMiniData(s);
|
||||
return static_cast<int>(cpCount);
|
||||
}
|
||||
if (!s.miniBitmapChunks[chunkIdx]) {
|
||||
s.miniBitmapChunks[chunkIdx] = new (std::nothrow) uint8_t[MINI_BM_CHUNK_SIZE];
|
||||
if (!s.miniBitmapChunks[chunkIdx]) {
|
||||
LOG_ERR("SDCF", "Failed to allocate mini bitmap chunk %u (style %u)", chunkIdx, styleIdx);
|
||||
file.close();
|
||||
delete[] readOrder;
|
||||
delete[] mappings;
|
||||
freeStyleMiniData(s);
|
||||
return static_cast<int>(cpCount);
|
||||
}
|
||||
if (chunkIdx + 1 > s.miniBitmapChunkCount) s.miniBitmapChunkCount = chunkIdx + 1;
|
||||
}
|
||||
|
||||
const uint32_t off = span & (MINI_BM_CHUNK_SIZE - 1);
|
||||
uint32_t fileOff = s.bitmapFileOffset + glyph.dataOffset;
|
||||
if (fileOff != lastBitmapEnd) {
|
||||
if (!file.seekSet(fileOff)) {
|
||||
@@ -1046,18 +1085,21 @@ int SdCardFont::prewarmStyle(uint8_t styleIdx, const uint32_t* codepoints, uint3
|
||||
}
|
||||
seekCount++;
|
||||
}
|
||||
if (file.read(s.miniBitmap + miniBitmapOffset, glyph.dataLength) != static_cast<int>(glyph.dataLength)) {
|
||||
if (file.read(s.miniBitmapChunks[chunkIdx] + off, len) != static_cast<int>(len)) {
|
||||
LOG_ERR("SDCF", "Prewarm: short bitmap read (style %u)", styleIdx);
|
||||
delete[] readOrder;
|
||||
delete[] mappings;
|
||||
freeStyleMiniData(s);
|
||||
return static_cast<int>(cpCount);
|
||||
}
|
||||
lastBitmapEnd = fileOff + glyph.dataLength;
|
||||
lastBitmapEnd = fileOff + len;
|
||||
|
||||
glyph.dataOffset = miniBitmapOffset;
|
||||
miniBitmapOffset += glyph.dataLength;
|
||||
glyph.dataOffset = span;
|
||||
span += len;
|
||||
}
|
||||
// Footprint including inter-chunk padding: the underuse-hysteresis signal.
|
||||
s.miniBitmapUsed = span;
|
||||
s.miniBitmapCapacity = s.miniBitmapChunkCount * MINI_BM_CHUNK_SIZE;
|
||||
}
|
||||
|
||||
uint32_t sdTime = millis() - sdStart;
|
||||
@@ -1080,7 +1122,10 @@ int SdCardFont::prewarmStyle(uint8_t styleIdx, const uint32_t* codepoints, uint3
|
||||
s.miniMetadataOnly = metadataOnly;
|
||||
s.miniHysteresisPending = !metadataOnly; // one hysteresis evaluation per rebuild
|
||||
memset(&s.miniData, 0, sizeof(s.miniData));
|
||||
s.miniData.bitmap = s.miniBitmap;
|
||||
// The mini bitmap is chunked (non-contiguous), so there is no single base
|
||||
// pointer. Prewarmed SD glyphs are resolved via SdCardFont::miniGlyphBitmap()
|
||||
// in the renderer; leave bitmap null so any stray &bitmap[dataOffset] faults.
|
||||
s.miniData.bitmap = nullptr;
|
||||
s.miniData.glyph = s.miniGlyphs;
|
||||
s.miniData.intervals = s.miniIntervals;
|
||||
s.miniData.intervalCount = s.miniIntervalCount;
|
||||
@@ -1517,4 +1562,14 @@ const uint8_t* SdCardFont::getOverflowBitmap(const EpdGlyph* glyph) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint8_t* SdCardFont::miniGlyphBitmap(const void* ctx, uint32_t dataOffset) const {
|
||||
const auto* octx = static_cast<const OverflowContext*>(ctx);
|
||||
const PerStyle& s = styles_[octx->styleIdx];
|
||||
const uint32_t chunkIdx = dataOffset >> MINI_BM_CHUNK_SHIFT;
|
||||
if (chunkIdx >= s.miniBitmapChunkCount) return nullptr;
|
||||
const uint8_t* chunk = s.miniBitmapChunks[chunkIdx];
|
||||
if (!chunk) return nullptr;
|
||||
return chunk + (dataOffset & (MINI_BM_CHUNK_SIZE - 1));
|
||||
}
|
||||
|
||||
SdCardFont* SdCardFont::fromMissCtx(void* ctx) { return static_cast<OverflowContext*>(ctx)->self; }
|
||||
@@ -94,6 +94,12 @@ class SdCardFont {
|
||||
// Returns the bitmap for an on-demand-loaded (overflow) glyph.
|
||||
const uint8_t* getOverflowBitmap(const EpdGlyph* glyph) const;
|
||||
|
||||
// Resolves a prewarmed mini glyph's chunked bitmap. `ctx` is the glyphMissCtx
|
||||
// (an OverflowContext identifying the style); `dataOffset` is the glyph's
|
||||
// virtual offset into the style's chunked arena. Returns nullptr if the chunk
|
||||
// is absent or out of range. Called by GfxRenderer::getGlyphBitmap().
|
||||
const uint8_t* miniGlyphBitmap(const void* ctx, uint32_t dataOffset) const;
|
||||
|
||||
// Extract SdCardFont* from an opaque glyphMissCtx pointer.
|
||||
// Used by GfxRenderer::getGlyphBitmap() to recover the SdCardFont from EpdFontData::glyphMissCtx.
|
||||
static SdCardFont* fromMissCtx(void* ctx);
|
||||
@@ -129,6 +135,18 @@ class SdCardFont {
|
||||
uint8_t ligaturePairCount = 0;
|
||||
};
|
||||
|
||||
// The per-style mini bitmap arena is stored as a list of fixed-size chunks
|
||||
// rather than one contiguous block. A whole page's 2bpp glyph bitmaps can run
|
||||
// tens of KB; on a fragmented heap a single contiguous allocation of that size
|
||||
// fails even when the same bytes are available as several smaller free blocks.
|
||||
// Chunking lets the arena be assembled from blocks the allocator can actually
|
||||
// provide. Each glyph's bitmap is placed wholly within one chunk (never
|
||||
// straddling a boundary), so a glyph is addressed by a virtual offset that
|
||||
// maps to (chunk index, offset-in-chunk) via miniGlyphBitmap().
|
||||
static constexpr uint32_t MINI_BM_CHUNK_SHIFT = 12; // 4 KB chunks
|
||||
static constexpr uint32_t MINI_BM_CHUNK_SIZE = 1u << MINI_BM_CHUNK_SHIFT;
|
||||
static constexpr uint32_t MINI_BM_MAX_CHUNKS = 24; // 96 KB ceiling per style/page
|
||||
|
||||
// All per-style data: file offsets, intervals, kern/lig, prewarm cache, EpdFont
|
||||
struct PerStyle {
|
||||
CpFontHeader header{};
|
||||
@@ -188,7 +206,10 @@ class SdCardFont {
|
||||
EpdFontData miniData{};
|
||||
EpdUnicodeInterval* miniIntervals = nullptr;
|
||||
EpdGlyph* miniGlyphs = nullptr;
|
||||
uint8_t* miniBitmap = nullptr;
|
||||
// Chunked mini bitmap arena (see MINI_BM_CHUNK_* above). Chunks are allocated
|
||||
// on demand during prewarm; miniBitmapChunkCount is how many are live.
|
||||
uint8_t* miniBitmapChunks[MINI_BM_MAX_CHUNKS] = {};
|
||||
uint32_t miniBitmapChunkCount = 0;
|
||||
uint32_t miniIntervalCount = 0;
|
||||
uint32_t miniGlyphCount = 0;
|
||||
uint32_t miniIntervalCapacity = 0;
|
||||
|
||||
@@ -49,7 +49,6 @@ INTERVAL_PRESETS = {
|
||||
"armenian": [(0x0530, 0x058F)],
|
||||
"ethiopic": [(0x1200, 0x137F), (0x1380, 0x139F), (0x2D80, 0x2DDF)],
|
||||
"vietnamese": [(0x01A0, 0x01B0), (0x1EA0, 0x1EF9)],
|
||||
"ipa-chars": [(0x0250, 0x02AF), (0x02B0, 0x02FF)],
|
||||
"punctuation": [(0x2000, 0x206F)],
|
||||
"cjk": [(0x3000, 0x303F), (0x3040, 0x309F), (0x30A0, 0x30FF),
|
||||
(0x4E00, 0x9FFF), (0xF900, 0xFAFF), (0xFF00, 0xFFEF)],
|
||||
|
||||
@@ -35,7 +35,7 @@ families:
|
||||
|
||||
- name: Literata
|
||||
description: "Screen-optimized serif (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/googlefonts/literata/main/fonts/ttf/Literata-Regular.ttf"}
|
||||
@@ -45,7 +45,7 @@ families:
|
||||
|
||||
- name: SourceSerif4
|
||||
description: "Adobe transitional serif (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/adobe-fonts/source-serif/release/TTF/SourceSerif4-Regular.ttf"}
|
||||
@@ -55,7 +55,7 @@ families:
|
||||
|
||||
- name: NotoSerifExtended
|
||||
description: "Serif (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/notofonts/NotoSerif/main/fonts/ttf/unhinted/instance_ttf/NotoSerif-Regular.ttf"}
|
||||
@@ -65,7 +65,7 @@ families:
|
||||
|
||||
- name: Merriweather
|
||||
description: "Warm serif for long-form reading (Latin, Cyrillic)"
|
||||
intervals: latin-ext,cyrillic,ipa-chars
|
||||
intervals: latin-ext,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/SorkinType/Merriweather/master/fonts/ttf/Merriweather-Regular.ttf"}
|
||||
@@ -75,7 +75,7 @@ families:
|
||||
|
||||
- name: Lora
|
||||
description: "Calligraphic serif for literary reading (Latin, Cyrillic)"
|
||||
intervals: latin-ext,cyrillic,ipa-chars
|
||||
intervals: latin-ext,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/cyrealtype/Lora-Cyrillic/main/fonts/ttf/Lora-Regular.ttf"}
|
||||
@@ -85,7 +85,7 @@ families:
|
||||
|
||||
- name: GentiumBookPlus
|
||||
description: "Scholarly serif with wide Unicode coverage (Latin, Greek, Cyrillic, IPA)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/google/fonts/main/ofl/gentiumbookplus/GentiumBookPlus-Regular.ttf"}
|
||||
@@ -95,7 +95,7 @@ families:
|
||||
|
||||
- name: IBMPlexSerif
|
||||
description: "Professional serif (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/google/fonts/main/ofl/ibmplexserif/IBMPlexSerif-Regular.ttf"}
|
||||
@@ -105,7 +105,7 @@ families:
|
||||
|
||||
- name: Bitter
|
||||
description: "Slab serif designed for e-ink (Latin, Cyrillic)"
|
||||
intervals: latin-ext,cyrillic,ipa-chars
|
||||
intervals: latin-ext,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/google/fonts/main/ofl/bitter/Bitter%5Bwght%5D.ttf", variable: {wght: 500}}
|
||||
@@ -115,7 +115,7 @@ families:
|
||||
|
||||
- name: Domitian
|
||||
description: "A humanist serif for literary reading (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://mirrors.ctan.org/fonts/domitian/opentype/Domitian-Roman.otf"}
|
||||
@@ -125,7 +125,7 @@ families:
|
||||
|
||||
- name: LibreBaskerville
|
||||
description: "A serif reimplementing the classic Baskerville (Latin)"
|
||||
intervals: latin-ext,ipa-chars
|
||||
intervals: latin-ext
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/impallari/Libre-Baskerville/master/fonts/ttf/LibreBaskerville-Regular.ttf"}
|
||||
@@ -135,7 +135,7 @@ families:
|
||||
|
||||
- name: Vollkorn
|
||||
description: "A serif for bread and butter use by Friedrich Althausen (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/google/fonts/main/ofl/vollkorn/Vollkorn%5Bwght%5D.ttf", variable: {wght: 400}}
|
||||
@@ -147,7 +147,7 @@ families:
|
||||
|
||||
- name: NotoSansExtended
|
||||
description: "Sans-serif (Latin, Greek, Cyrillic, Georgian, Armenian, Ethiopic)"
|
||||
intervals: latin-ext,greek,cyrillic,georgian,armenian,ethiopic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic,georgian,armenian,ethiopic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {path: "builtinFonts/source/NotoSans/NotoSans-Regular.ttf"}
|
||||
@@ -157,7 +157,7 @@ families:
|
||||
|
||||
- name: Inter
|
||||
description: "Modern sans-serif (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/google/fonts/main/ofl/inter/Inter%5Bopsz%2Cwght%5D.ttf", variable: {wght: 400, opsz: 14}}
|
||||
@@ -167,7 +167,7 @@ families:
|
||||
|
||||
- name: SourceSans3
|
||||
description: "Adobe humanist sans-serif (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/adobe-fonts/source-sans/release/TTF/SourceSans3-Regular.ttf"}
|
||||
@@ -177,7 +177,7 @@ families:
|
||||
|
||||
- name: IBMPlexSans
|
||||
description: "IBM corporate sans-serif (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/IBM/plex/master/packages/plex-sans/fonts/complete/ttf/IBMPlexSans-Regular.ttf"}
|
||||
@@ -187,7 +187,7 @@ families:
|
||||
|
||||
- name: Alegreya
|
||||
description: "Calligraphic serif/display (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/google/fonts/main/ofl/alegreya/Alegreya%5Bwght%5D.ttf", variable: {wght: 400}}
|
||||
@@ -199,7 +199,7 @@ families:
|
||||
|
||||
- name: IBMPlexMono
|
||||
description: "Monospace for code and technical reading (Latin, Greek, Cyrillic)"
|
||||
intervals: latin-ext,greek,cyrillic,ipa-chars
|
||||
intervals: latin-ext,greek,cyrillic
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/google/fonts/main/ofl/ibmplexmono/IBMPlexMono-Regular.ttf"}
|
||||
@@ -209,7 +209,7 @@ families:
|
||||
|
||||
- name: SourceCodePro
|
||||
description: "Adobe monospace with excellent hinting (Latin)"
|
||||
intervals: latin-ext,ipa-chars
|
||||
intervals: latin-ext
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/adobe-fonts/source-code-pro/release/TTF/SourceCodePro-Regular.ttf"}
|
||||
@@ -221,7 +221,7 @@ families:
|
||||
|
||||
- name: OpenDyslexic
|
||||
description: "Dyslexia-friendly font (Latin)"
|
||||
intervals: latin-ext,ipa-chars
|
||||
intervals: latin-ext
|
||||
sizes: [8, 10, 12, 14]
|
||||
styles:
|
||||
regular: {path: "builtinFonts/source/OpenDyslexic/OpenDyslexic-Regular.otf"}
|
||||
@@ -233,7 +233,7 @@ families:
|
||||
|
||||
- name: AtkinsonHyperlegibleNext
|
||||
description: "Accessibility font for low vision (Latin)"
|
||||
intervals: latin-ext,ipa-chars
|
||||
intervals: latin-ext
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/googlefonts/atkinson-hyperlegible-next/main/fonts/ttf/AtkinsonHyperlegibleNext-Regular.ttf"}
|
||||
@@ -243,7 +243,7 @@ families:
|
||||
|
||||
- name: LexicaUltralegible
|
||||
description: "Accessibility font for low vision / dyslexia (Latin)"
|
||||
intervals: latin-ext,ipa-chars
|
||||
intervals: latin-ext
|
||||
sizes: [12, 14, 16, 18]
|
||||
styles:
|
||||
regular: {url: "https://raw.githubusercontent.com/jacobxperez/lexica-ultralegible/main/fonts/ttf/LexicaUltralegible-Regular.ttf"}
|
||||
|
||||
@@ -681,76 +681,6 @@ static inline bool isCjkIdeograph(uint32_t cp) {
|
||||
(cp >= 0x20000 && cp <= 0x3FFFF);
|
||||
}
|
||||
|
||||
// The first word of a line may have its ruby characters wider than the word (the base text). In that case, we need to
|
||||
// move the base text to the right a bit so that ruby text doesn't overflow the left border, and it is still centered
|
||||
// over the base text. This function calculates how much we need to move the base text to the right.
|
||||
int ParsedText::calculateRubyExtraStartOffset(const size_t wordIdx, const size_t maxWordIdx,
|
||||
const GfxRenderer& renderer, const int fontId) const {
|
||||
if (rubyTexts.empty() || wordIdx >= rubyTexts.size() || rubyTexts[wordIdx].empty() ||
|
||||
(wordStyles[wordIdx] & EpdFontFamily::RUBY_CONTINUE) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t groupWordCount = 1;
|
||||
while (wordIdx + groupWordCount < maxWordIdx &&
|
||||
(wordStyles[wordIdx + groupWordCount] & EpdFontFamily::RUBY_CONTINUE) != 0) {
|
||||
groupWordCount++;
|
||||
}
|
||||
int groupActualWidth = 0;
|
||||
for (size_t k = 0; k < groupWordCount; ++k) {
|
||||
groupActualWidth += measureWordWidth(renderer, fontId, words[wordIdx + k], wordStyles[wordIdx + k]);
|
||||
}
|
||||
const int rubyWidth = renderer.getTextAdvanceX(fontId, rubyTexts[wordIdx].c_str(), EpdFontFamily::SUP);
|
||||
if (rubyWidth <= groupActualWidth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int leftOverlap = (rubyWidth - groupActualWidth) / 2;
|
||||
|
||||
// This function is only ever called for the first word of a line.
|
||||
// words[wordIdx - 1], if it exists, is always the last word of the *prior* line
|
||||
// and cannot absorb any left overhang on the current line.
|
||||
// The full leftOverlap must therefore be reserved as a visual indent so the
|
||||
// ruby text does not overflow the left margin.
|
||||
return leftOverlap;
|
||||
}
|
||||
|
||||
// The last ruby group on a line may have its ruby characters wider than the group's base text.
|
||||
// The right half of that overhang protrudes past the last base character. This function returns
|
||||
// the amount of right-margin space that must be reserved so the ruby does not overflow the right
|
||||
// border. It mirrors calculateRubyExtraStartOffset: words[lineBreak] is on the *next* line and
|
||||
// cannot absorb any of the right overhang on the current line, so the full rightOverlap is returned.
|
||||
int ParsedText::calculateRubyExtraEndOffset(const size_t lineStartIdx, const size_t lineBreakIdx,
|
||||
const GfxRenderer& renderer, const int fontId) const {
|
||||
if (rubyTexts.empty() || lineBreakIdx == 0 || lineStartIdx >= lineBreakIdx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Walk backwards from the last word to find the leader of the last ruby group on the line.
|
||||
size_t leaderIdx = lineBreakIdx - 1;
|
||||
while (leaderIdx > lineStartIdx && (wordStyles[leaderIdx] & EpdFontFamily::RUBY_CONTINUE) != 0) {
|
||||
leaderIdx--;
|
||||
}
|
||||
|
||||
// leaderIdx must be a ruby group leader (non-empty ruby, no RUBY_CONTINUE flag).
|
||||
if (leaderIdx >= rubyTexts.size() || rubyTexts[leaderIdx].empty() ||
|
||||
(wordStyles[leaderIdx] & EpdFontFamily::RUBY_CONTINUE) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Measure the group.
|
||||
int groupActualWidth = 0;
|
||||
for (size_t k = leaderIdx; k < lineBreakIdx; ++k) {
|
||||
groupActualWidth += measureWordWidth(renderer, fontId, words[k], wordStyles[k]);
|
||||
}
|
||||
const int rubyWidth = renderer.getTextAdvanceX(fontId, rubyTexts[leaderIdx].c_str(), EpdFontFamily::SUP);
|
||||
if (rubyWidth <= groupActualWidth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (rubyWidth - groupActualWidth) / 2;
|
||||
}
|
||||
|
||||
std::vector<uint16_t> ParsedText::calculateWordWidths(const GfxRenderer& renderer, const int fontId) {
|
||||
std::vector<uint16_t> wordWidths;
|
||||
wordWidths.reserve(words.size());
|
||||
@@ -761,6 +691,9 @@ std::vector<uint16_t> ParsedText::calculateWordWidths(const GfxRenderer& rendere
|
||||
|
||||
// Adjust widths for ruby groups to comply with JLReq standards
|
||||
if (!rubyTexts.empty()) {
|
||||
const int ascender = renderer.getFontAscenderSize(fontId);
|
||||
const int maxOverhang = ascender / 2; // Maximum overhang over non-ideographic characters (Kana, punctuation, etc.)
|
||||
|
||||
struct RubyGroupInfo {
|
||||
size_t start;
|
||||
size_t count;
|
||||
@@ -797,10 +730,9 @@ std::vector<uint16_t> ParsedText::calculateWordWidths(const GfxRenderer& rendere
|
||||
if (g.start > 0) {
|
||||
const uint32_t cpPrev = lastCodepoint(words[g.start - 1]);
|
||||
if (isCjkIdeograph(cpPrev)) {
|
||||
wordWidths[g.start - 1] += g.leftOverlap;
|
||||
wordWidths[g.start] += g.leftOverlap;
|
||||
} else {
|
||||
const int maxLeftOverhang = wordWidths[g.start - 1] / 2;
|
||||
wordWidths[g.start - 1] += std::max(0, g.leftOverlap - maxLeftOverhang);
|
||||
wordWidths[g.start] += std::max(0, g.leftOverlap - maxOverhang);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -820,8 +752,7 @@ std::vector<uint16_t> ParsedText::calculateWordWidths(const GfxRenderer& rendere
|
||||
if (isCjkIdeograph(cpNext)) {
|
||||
wordWidths[g.start + g.count - 1] += g.rightOverlap;
|
||||
} else {
|
||||
const int maxRightOverhang = wordWidths[nextIdx] / 2;
|
||||
wordWidths[g.start + g.count - 1] += std::max(0, g.rightOverlap - maxRightOverhang);
|
||||
wordWidths[g.start + g.count - 1] += std::max(0, g.rightOverlap - maxOverhang);
|
||||
}
|
||||
|
||||
// Check if there is another ruby group further ahead separated only by non-ideographs
|
||||
@@ -838,10 +769,8 @@ std::vector<uint16_t> ParsedText::calculateWordWidths(const GfxRenderer& rendere
|
||||
gapWidth += wordWidths[k];
|
||||
}
|
||||
if (onlyNonIdeographsInBetween) {
|
||||
const int maxRightOverhang = wordWidths[g.start + g.count - 1] / 2;
|
||||
const int maxLeftOverhang = wordWidths[nextG.start - 1] / 2;
|
||||
const int allowedRight = std::min(g.rightOverlap, maxRightOverhang);
|
||||
const int allowedLeft = std::min(nextG.leftOverlap, maxLeftOverhang);
|
||||
const int allowedRight = std::min(g.rightOverlap, maxOverhang);
|
||||
const int allowedLeft = std::min(nextG.leftOverlap, maxOverhang);
|
||||
const int touchOverlap = allowedRight + allowedLeft - gapWidth;
|
||||
if (touchOverlap > 0) {
|
||||
wordWidths[g.start + g.count - 1] += touchOverlap;
|
||||
@@ -908,7 +837,36 @@ std::vector<size_t> ParsedText::computeLineBreaks(const GfxRenderer& renderer, c
|
||||
}
|
||||
|
||||
// Calculate extraStartOffset for the first word on the line (i) (protect left margin)
|
||||
const int extraStartOffset = (j == i) ? calculateRubyExtraStartOffset(i, totalWordCount, renderer, fontId) : 0;
|
||||
int extraStartOffset = 0;
|
||||
if (j == i && !rubyTexts.empty() && i < rubyTexts.size() && !rubyTexts[i].empty() &&
|
||||
(wordStyles[i] & EpdFontFamily::RUBY_CONTINUE) == 0) {
|
||||
int groupWordCount = 1;
|
||||
while (i + groupWordCount < totalWordCount &&
|
||||
(wordStyles[i + groupWordCount] & EpdFontFamily::RUBY_CONTINUE) != 0) {
|
||||
groupWordCount++;
|
||||
}
|
||||
int groupActualWidth = 0;
|
||||
for (int k = 0; k < groupWordCount; ++k) {
|
||||
groupActualWidth += measureWordWidth(renderer, fontId, words[i + k], wordStyles[i + k]);
|
||||
}
|
||||
const int rubyWidth = renderer.getTextAdvanceX(fontId, rubyTexts[i].c_str(), EpdFontFamily::SUP);
|
||||
if (rubyWidth > groupActualWidth) {
|
||||
const int leftOverlap = (rubyWidth - groupActualWidth) / 2;
|
||||
const int ascender = renderer.getFontAscenderSize(fontId);
|
||||
const int maxOverhang = ascender / 2;
|
||||
|
||||
int expansion_added = 0;
|
||||
if (i > 0) {
|
||||
const uint32_t cpPrev = lastCodepoint(words[i - 1]);
|
||||
if (isCjkIdeograph(cpPrev)) {
|
||||
expansion_added = leftOverlap;
|
||||
} else {
|
||||
expansion_added = std::max(0, leftOverlap - maxOverhang);
|
||||
}
|
||||
}
|
||||
extraStartOffset = leftOverlap - expansion_added;
|
||||
}
|
||||
}
|
||||
|
||||
currlen += wordWidths[j] + gap + (j == i ? extraStartOffset : 0);
|
||||
|
||||
@@ -921,7 +879,46 @@ std::vector<size_t> ParsedText::computeLineBreaks(const GfxRenderer& renderer, c
|
||||
continue;
|
||||
}
|
||||
|
||||
const int extraEndOffset = calculateRubyExtraEndOffset(i, j + 1, renderer, fontId);
|
||||
// Calculate extraEndOffset if we break after word j (protect right margin)
|
||||
int extraEndOffset = 0;
|
||||
if (!rubyTexts.empty() && j < rubyTexts.size()) {
|
||||
bool isLastOfGroup = false;
|
||||
size_t leaderIdx = j;
|
||||
while (true) {
|
||||
if (!rubyTexts[leaderIdx].empty() && (wordStyles[leaderIdx] & EpdFontFamily::RUBY_CONTINUE) == 0) {
|
||||
isLastOfGroup = true;
|
||||
break;
|
||||
}
|
||||
if (leaderIdx == 0 || (wordStyles[leaderIdx] & EpdFontFamily::RUBY_CONTINUE) == 0) {
|
||||
break;
|
||||
}
|
||||
leaderIdx--;
|
||||
}
|
||||
|
||||
if (isLastOfGroup && (j + 1 == totalWordCount || (wordStyles[j + 1] & EpdFontFamily::RUBY_CONTINUE) == 0)) {
|
||||
int groupActualWidth = 0;
|
||||
for (size_t k = leaderIdx; k <= j; ++k) {
|
||||
groupActualWidth += measureWordWidth(renderer, fontId, words[k], wordStyles[k]);
|
||||
}
|
||||
const int rubyWidth = renderer.getTextAdvanceX(fontId, rubyTexts[leaderIdx].c_str(), EpdFontFamily::SUP);
|
||||
if (rubyWidth > groupActualWidth) {
|
||||
const int rightOverlap = (rubyWidth - groupActualWidth) / 2;
|
||||
const int ascender = renderer.getFontAscenderSize(fontId);
|
||||
const int maxOverhang = ascender / 2;
|
||||
|
||||
int expansion_added = 0;
|
||||
if (j + 1 < totalWordCount) {
|
||||
const uint32_t cpNext = firstCodepoint(words[j + 1]);
|
||||
if (isCjkIdeograph(cpNext)) {
|
||||
expansion_added = rightOverlap;
|
||||
} else {
|
||||
expansion_added = std::max(0, rightOverlap - maxOverhang);
|
||||
}
|
||||
}
|
||||
extraEndOffset = rightOverlap - expansion_added;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currlen + extraEndOffset > effectivePageWidth) {
|
||||
continue; // Cannot split here as it would overflow the right margin
|
||||
@@ -942,9 +939,7 @@ std::vector<size_t> ParsedText::computeLineBreaks(const GfxRenderer& renderer, c
|
||||
}
|
||||
}
|
||||
|
||||
// Favor longer lines when line-breaking costs are equal, to avoid unnecessary short lines in Chinese and Japanese
|
||||
// text.
|
||||
if (cost <= dp[i]) {
|
||||
if (cost < dp[i]) {
|
||||
dp[i] = cost;
|
||||
ans[i] = j; // j is the index of the last word in this optimal line
|
||||
}
|
||||
@@ -1176,9 +1171,6 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const
|
||||
std::copy(rubyTexts.begin() + lastBreakAt, rubyTexts.begin() + lastBreakAt + copyCount, lineRubyTexts.begin());
|
||||
}
|
||||
|
||||
const int extraStartOffset = calculateRubyExtraStartOffset(lastBreakAt, lineBreak, renderer, fontId);
|
||||
const int extraEndOffset = calculateRubyExtraEndOffset(lastBreakAt, lineBreak, renderer, fontId);
|
||||
|
||||
std::vector<std::string> lineWords;
|
||||
lineWords.reserve(lineWordCount);
|
||||
std::vector<EpdFontFamily::Style> lineWordStyles;
|
||||
@@ -1233,9 +1225,8 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const
|
||||
? CssTextAlign::Right
|
||||
: blockStyle.alignment;
|
||||
|
||||
// For justified text, compute per-gap extra to distribute remaining space evenly.
|
||||
// extraEndOffset reserves space for any ruby group at the right edge of the line.
|
||||
const int spareSpace = effectivePageWidth - extraStartOffset - extraEndOffset - lineWordWidthSum - totalNaturalGaps;
|
||||
// For justified text, compute per-gap extra to distribute remaining space evenly
|
||||
const int spareSpace = effectivePageWidth - lineWordWidthSum - totalNaturalGaps;
|
||||
const int justifyExtra = (effectiveAlignment == CssTextAlign::Justify && !isLastLine)
|
||||
? computeJustifyExtra(spareSpace, actualGapCount)
|
||||
: 0;
|
||||
@@ -1316,8 +1307,7 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const
|
||||
}
|
||||
}
|
||||
|
||||
const int reorderedSpare =
|
||||
effectivePageWidth - extraStartOffset - extraEndOffset - reorderedWordWidthSum - reorderedNaturalGaps;
|
||||
const int reorderedSpare = effectivePageWidth - reorderedWordWidthSum - reorderedNaturalGaps;
|
||||
const int reorderedJustifyExtra = (effectiveAlignment == CssTextAlign::Justify && !isLastLine)
|
||||
? computeJustifyExtra(reorderedSpare, reorderedGapCount)
|
||||
: 0;
|
||||
@@ -1422,7 +1412,7 @@ void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const
|
||||
}
|
||||
} else {
|
||||
// LTR: position words from left to right
|
||||
int xpos = firstLineIndent + extraStartOffset;
|
||||
int xpos = firstLineIndent;
|
||||
if (effectiveAlignment == CssTextAlign::Right) {
|
||||
xpos = effectivePageWidth - lineWordWidthSum - totalNaturalGaps;
|
||||
} else if (effectiveAlignment == CssTextAlign::Center) {
|
||||
|
||||
@@ -59,9 +59,6 @@ class ParsedText {
|
||||
void pushVisibleOffset(uint32_t offset);
|
||||
void insertVisibleOffset(size_t wordIndex, uint32_t offset);
|
||||
void eraseVisibleOffsetPrefix(size_t count);
|
||||
int calculateRubyExtraStartOffset(size_t wordIdx, size_t maxWordIdx, const GfxRenderer& renderer, int fontId) const;
|
||||
int calculateRubyExtraEndOffset(size_t lineStartIdx, size_t lineBreakIdx, const GfxRenderer& renderer,
|
||||
int fontId) const;
|
||||
int resolveFirstLineIndent(bool isFirstLine, const GfxRenderer& renderer, int fontId) const;
|
||||
std::vector<size_t> computeLineBreaks(const GfxRenderer& renderer, int fontId, int pageWidth,
|
||||
std::vector<uint16_t>& wordWidths, std::vector<bool>& continuesVec,
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace {
|
||||
// match. Keeps <br>-per-paragraph books (common CJK formatting) from
|
||||
// re-adding container spacing at every paragraph.
|
||||
// v35: Persist a uint32_t visible-text start offset for every page.
|
||||
constexpr uint8_t SECTION_FILE_VERSION = 36;
|
||||
constexpr uint8_t SECTION_FILE_VERSION = 35;
|
||||
// Written into the version field while a build is in progress; patched to
|
||||
// SECTION_FILE_VERSION only when the build is finalized. An abandoned /
|
||||
// crash-interrupted .bin therefore carries version 0, which loadSectionFile rejects
|
||||
|
||||
@@ -135,32 +135,86 @@ void TextBlock::render(const GfxRenderer& renderer, const int fontId, const int
|
||||
const bool scanning = renderer.isFontCacheScanning();
|
||||
const int ascender = renderer.getFontAscenderSize(fontId);
|
||||
|
||||
// Resolve ruby positions. Layout (extractLine) has already reserved extraStartOffset on the
|
||||
// left and extraEndOffset on the right, so the centered rubyX is always within the page margins.
|
||||
// Resolve ruby collisions left-to-right to prevent adjacent ruby texts from overlapping
|
||||
struct RubyDrawInfo {
|
||||
int x;
|
||||
int width;
|
||||
std::string text;
|
||||
BidiUtils::BidiBaseDir baseDir;
|
||||
};
|
||||
// hasRuby() is an O(numWords) scan, so resolve it once here rather than per word.
|
||||
// Both arrays below are only ever read when the line carries ruby, so they stay
|
||||
// empty (zero allocations) for the ruby-less case, which is every line of a
|
||||
// non-CJK book. Sized lazily inside the branch.
|
||||
const bool blockHasRuby = hasRuby();
|
||||
std::vector<int> wordShiftArr;
|
||||
std::vector<RubyDrawInfo> rubies;
|
||||
if (blockHasRuby) {
|
||||
wordShiftArr.assign(numWords, 0);
|
||||
rubies.resize(numWords);
|
||||
int accumulatedShift = 0;
|
||||
int lastEnd = -9999;
|
||||
for (uint16_t i = 0; i < numWords; i++) {
|
||||
wordShiftArr[i] = accumulatedShift;
|
||||
if (i < rubyTexts.size() && !rubyTexts[i].empty() && (wordStyle(i) & EpdFontFamily::RUBY_CONTINUE) == 0) {
|
||||
// Find the group size (how many words are part of this ruby annotation)
|
||||
int groupWordCount = 1;
|
||||
while (i + groupWordCount < numWords && (wordStyle(i + groupWordCount) & EpdFontFamily::RUBY_CONTINUE) != 0) {
|
||||
groupWordCount++;
|
||||
}
|
||||
|
||||
// Compute actual width for the group
|
||||
int groupActualWidth = 0;
|
||||
for (int k = 0; k < groupWordCount; ++k) {
|
||||
groupActualWidth += renderer.getTextAdvanceX(fontId, wordText(i + k), wordStyle(i + k));
|
||||
}
|
||||
const int rubyWidth = renderer.getTextAdvanceX(fontId, rubyTexts[i].c_str(), EpdFontFamily::SUP);
|
||||
|
||||
const char* word = wordText(i);
|
||||
const int leaderWordX = xposArr[i] + x;
|
||||
const int leaderWordX_shifted = leaderWordX + accumulatedShift;
|
||||
const auto baseDir =
|
||||
static_cast<BidiUtils::BidiBaseDir>(BidiUtils::detectParagraphLevel(wordText(i), blockStyle.isRtl ? 1 : 0));
|
||||
rubies[i] = {leaderWordX - (rubyWidth - groupActualWidth) / 2, rubyTexts[i], baseDir};
|
||||
static_cast<BidiUtils::BidiBaseDir>(BidiUtils::detectParagraphLevel(word, blockStyle.isRtl ? 1 : 0));
|
||||
const int rubyWidth = renderer.getTextAdvanceX(fontId, rubyTexts[i].c_str(), EpdFontFamily::SUP);
|
||||
const int screenWidth = renderer.getScreenWidth();
|
||||
|
||||
int rubyX = 0;
|
||||
int groupDrawX = 0;
|
||||
if (rubyWidth > groupActualWidth) {
|
||||
rubyX = leaderWordX_shifted - (rubyWidth - groupActualWidth) / 2;
|
||||
if (i == 0) {
|
||||
rubyX = std::max(leaderWordX_shifted, rubyX);
|
||||
}
|
||||
if (rubyX < lastEnd) {
|
||||
rubyX = lastEnd;
|
||||
}
|
||||
groupDrawX = rubyX + (rubyWidth - groupActualWidth) / 2;
|
||||
} else {
|
||||
groupDrawX = leaderWordX_shifted;
|
||||
rubyX = groupDrawX + (groupActualWidth - rubyWidth) / 2;
|
||||
if (i == 0) {
|
||||
rubyX = std::max(leaderWordX_shifted, rubyX);
|
||||
}
|
||||
if (rubyX < lastEnd) {
|
||||
const int push = lastEnd - rubyX;
|
||||
rubyX = lastEnd;
|
||||
groupDrawX += push;
|
||||
}
|
||||
}
|
||||
rubyX = std::max(0, std::min(rubyX, screenWidth - rubyWidth));
|
||||
// Keep groupDrawX aligned if rubyX was clamped by screen edges
|
||||
if (rubyWidth > groupActualWidth) {
|
||||
groupDrawX = rubyX + (rubyWidth - groupActualWidth) / 2;
|
||||
}
|
||||
|
||||
rubies[i] = {rubyX, rubyWidth, rubyTexts[i], baseDir};
|
||||
lastEnd = rubyX + rubyWidth;
|
||||
|
||||
// Propagate shift to all words in the group and subsequent words
|
||||
const int groupShift = groupDrawX - leaderWordX;
|
||||
accumulatedShift = groupShift;
|
||||
for (int k = 0; k < groupWordCount; ++k) {
|
||||
wordShiftArr[i + k] = accumulatedShift;
|
||||
}
|
||||
i += groupWordCount - 1;
|
||||
}
|
||||
}
|
||||
@@ -221,7 +275,7 @@ void TextBlock::render(const GfxRenderer& renderer, const int fontId, const int
|
||||
wordY += ascender / 4;
|
||||
}
|
||||
|
||||
const int drawX = wordX;
|
||||
const int drawX = wordX + (blockHasRuby ? wordShiftArr[i] : 0);
|
||||
|
||||
if (boundary > 0) {
|
||||
// Focus split: draw bold prefix, then the regular suffix at a pre-computed x offset.
|
||||
|
||||
@@ -81,6 +81,9 @@ const uint8_t* GfxRenderer::getGlyphBitmap(const EpdFontData* fontData, const Ep
|
||||
if (sdFont->isOverflowGlyph(glyph)) {
|
||||
return sdFont->getOverflowBitmap(glyph); // may be nullptr for zero-width glyphs
|
||||
}
|
||||
// Prewarmed SD glyph: the mini bitmap is chunked (non-contiguous), so there is
|
||||
// no fontData->bitmap base to index. Resolve via the per-style chunk table.
|
||||
return sdFont->miniGlyphBitmap(fontData->glyphMissCtx, glyph->dataOffset);
|
||||
}
|
||||
return &fontData->bitmap[glyph->dataOffset];
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ STR_BROWSE_FILES: "تصفح الملفات"
|
||||
STR_FILE_TRANSFER: "نقل الملفات"
|
||||
STR_SETTINGS_TITLE: "الإعدادات"
|
||||
STR_CONTINUE_READING: "متابعة القراءة"
|
||||
STR_RESUME: "استئناف"
|
||||
STR_NO_OPEN_BOOK: "لا يوجد كتاب مفتوح"
|
||||
STR_START_READING: "ابدأ القراءة أدناه"
|
||||
STR_NO_FILES_FOUND: "لم يتم العثور على ملفات"
|
||||
@@ -23,20 +22,9 @@ STR_INDEX_FAILED: "فشلت الفهرسة - كتاب غير صالح"
|
||||
STR_MEMORY_ERROR: "خطأ في الذاكرة"
|
||||
STR_PAGE_LOAD_ERROR: "خطأ في تحميل الصفحة"
|
||||
STR_EMPTY_FILE: "ملف فارغ"
|
||||
STR_INVALID_BMP_FILE: "ملف BMP غير صالح"
|
||||
STR_FILE_OPEN_FAILED: "تعذر فتح الملف"
|
||||
STR_OUT_OF_BOUNDS: "خارج النطاق"
|
||||
STR_LOADING: "جاري التحميل..."
|
||||
STR_LOADING_POPUP: "جاري التحميل"
|
||||
STR_LOOKUP: "بحث"
|
||||
STR_DICT_LOOKING_UP: "جاري البحث..."
|
||||
STR_DICT_INDEXING: "جاري فهرسة القاموس..."
|
||||
STR_DICT_NOT_FOUND: "غير موجود"
|
||||
STR_DICT_NO_DICT_SET: "لم يتم تحديد قاموس"
|
||||
STR_DICT_ERROR: "خطأ في القاموس"
|
||||
STR_DICT_READ_FAILED: "تعذر قراءة التعريف"
|
||||
STR_DICT_DECOMPRESS_ERROR: "تعذر فك ضغط التعريف"
|
||||
STR_DICT_LOW_MEMORY: "الذاكرة غير كافية"
|
||||
STR_WIFI_NETWORKS: "شبكات Wi-Fi"
|
||||
STR_NO_NETWORKS: "لم يتم العثور على شبكات"
|
||||
STR_NETWORKS_FOUND: "تم العثور على %zu شبكة"
|
||||
@@ -93,7 +81,6 @@ STR_EOB_CONTINUE_WITH: "المتابعة إلى"
|
||||
STR_SHORT_PWR_BTN: "ضغطة قصيرة على زر التشغيل"
|
||||
STR_ORIENTATION: "اتجاه القراءة"
|
||||
STR_SIDE_BTN_LAYOUT: "تخطيط الأزرار الجانبية (أثناء القراءة)"
|
||||
STR_TOUCH_READER_CONTROLS: "التحكم باللمس (أثناء القراءة)"
|
||||
STR_FRONT_BTN_FOLLOW_ORIENTATION: "تدوير الأزرار الأمامية مع الشاشة"
|
||||
STR_LONG_PRESS_BEHAVIOR: "سلوك الضغطة الطويلة"
|
||||
STR_LONG_PRESS_BEHAVIOR_OFF: "إيقاف"
|
||||
@@ -103,13 +90,6 @@ STR_LONG_PRESS_MENU: "قائمة الضغطة الطويلة"
|
||||
STR_FONT_PREVIEW_TEXT: "نص حكيم له سر قاطع وذو شأن عظيم مكتوب على ثوب أخضر ومغلف بجلد أزرق"
|
||||
STR_FONT_FAMILY: "خط القراءة"
|
||||
STR_FONT_SIZE: "حجم الخط"
|
||||
STR_TEXT_SETTINGS: "إعدادات النص"
|
||||
STR_FONT: "الخط"
|
||||
STR_SIZE: "الحجم"
|
||||
STR_LAYOUT: "التخطيط"
|
||||
STR_ALIGNMENT: "المحاذاة"
|
||||
STR_STYLE: "النمط"
|
||||
STR_NOT_IN_PREVIEW: "غير معروض في المعاينة"
|
||||
STR_LINE_SPACING: "تباعد الأسطر"
|
||||
STR_SCREEN_MARGIN: "هوامش شاشة القراءة"
|
||||
STR_PARA_ALIGNMENT: "محاذاة الفقرات"
|
||||
@@ -128,15 +108,7 @@ STR_PASSWORD: "كلمة المرور"
|
||||
STR_SYNC_SERVER_URL: "عنوان خادم المزامنة"
|
||||
STR_DOCUMENT_MATCHING: "مطابقة المستندات"
|
||||
STR_SEND_METADATA: "إرسال البيانات الوصفية للمستند"
|
||||
STR_SYNC_BEHAVIOR: "سلوك المزامنة"
|
||||
STR_ASK_EVERY_TIME: "اسأل في كل مرة"
|
||||
STR_SMART_SYNC: "مزامنة ذكية"
|
||||
STR_AUTHENTICATE: "تسجيل الدخول"
|
||||
STR_SIGN_UP: "إنشاء حساب"
|
||||
STR_CREATING_ACCOUNT: "جاري إنشاء الحساب..."
|
||||
STR_ACCOUNT_CREATED: "تم إنشاء الحساب"
|
||||
STR_SIGNUP_FAILED: "فشل إنشاء الحساب"
|
||||
STR_USERNAME_TAKEN: "اسم المستخدم مسجل مسبقا"
|
||||
STR_KOREADER_USERNAME: "اسم مستخدم KOReader"
|
||||
STR_KOREADER_PASSWORD: "كلمة مرور KOReader"
|
||||
STR_FILENAME: "اسم الملف"
|
||||
@@ -182,7 +154,6 @@ STR_PREV_NEXT: "السابق/التالي"
|
||||
STR_NEXT_PREV: "التالي/السابق"
|
||||
STR_KOSYNC: "KOSync"
|
||||
STR_BOOKMARK_OPTION: "إشارة مرجعية"
|
||||
STR_DICTIONARY: "القاموس"
|
||||
STR_DISABLED: "معطل"
|
||||
STR_NOTO_SERIF: "Noto Serif"
|
||||
STR_NOTO_SANS: "Noto Sans"
|
||||
@@ -239,7 +210,6 @@ STR_CONNECT: "اتصال"
|
||||
STR_OPEN: "فتح"
|
||||
STR_DOWNLOAD: "تنزيل"
|
||||
STR_RETRY: "إعادة المحاولة"
|
||||
STR_TAP_TO_RETRY: "اضغط لإعادة المحاولة"
|
||||
STR_YES: "نعم"
|
||||
STR_NO: "لا"
|
||||
STR_SHOW: "عرض"
|
||||
@@ -252,9 +222,6 @@ STR_DIR_RIGHT: "يمين"
|
||||
STR_DIR_UP: "أعلى"
|
||||
STR_DIR_DOWN: "أسفل"
|
||||
STR_OK_BUTTON: "موافق"
|
||||
STR_KEY_SHIFT: "Shift"
|
||||
STR_KEY_MODE_SYMBOLS: "?123"
|
||||
STR_KEY_MODE_ABC: "abc"
|
||||
STR_SLEEP_COVER_FILTER: "مرشح غلاف شاشة السكون"
|
||||
STR_FILTER_CONTRAST: "التباين"
|
||||
STR_CUSTOMISE_STATUS_BAR: "تخصيص شريط الحالة"
|
||||
@@ -353,7 +320,6 @@ STR_UPLOAD_LOCAL: "رفع التقدم المحلي"
|
||||
STR_NO_REMOTE_MSG: "لا يوجد تقدم على الخادم"
|
||||
STR_UPLOAD_PROMPT: "رفع الموضع الحالي؟"
|
||||
STR_UPLOAD_SUCCESS: "تم رفع التقدم!"
|
||||
STR_ALREADY_SYNCED: "متزامن مسبقا"
|
||||
STR_SYNC_FAILED_MSG: "فشلت المزامنة"
|
||||
STR_SAVE_PROGRESS_FAILED: "تعذر حفظ التقدم"
|
||||
STR_SECTION_PREFIX: "القسم "
|
||||
@@ -363,7 +329,6 @@ STR_EMBEDDED_STYLE: "التنسيق المضمن"
|
||||
STR_FOCUS_READING: "قراءة مركزة"
|
||||
STR_OPDS_SERVER_URL: "عنوان خادم OPDS"
|
||||
STR_PWR_BTN_FOOTNOTE_BACK: "عودة سريعة من الحواشي"
|
||||
STR_BACK_SHORT_TO_FILE_BROWSER: "عودة سريعة إلى متصفح الملفات"
|
||||
STR_SET_SLEEP_COVER: "تعيين الغلاف"
|
||||
STR_FOOTNOTES: "الحواشي"
|
||||
STR_NO_FOOTNOTES: "لا توجد حواش في هذه الصفحة"
|
||||
@@ -378,12 +343,6 @@ STR_SERVER_NAME: "اسم الخادم"
|
||||
STR_NO_SERVERS: "لم يتم إعداد خوادم OPDS"
|
||||
STR_DELETE_SERVER: "حذف الخادم"
|
||||
STR_OPDS_SERVERS: "خوادم OPDS"
|
||||
STR_OPDS_DOWNLOAD_FOLDER: "مجلد التنزيل"
|
||||
STR_OPDS_FILENAME_FORMAT: "تنسيق اسم الملف"
|
||||
STR_FMT_AUTHOR_TITLE: "المؤلف - العنوان"
|
||||
STR_FMT_TITLE_AUTHOR: "العنوان - المؤلف"
|
||||
STR_FMT_TITLE: "العنوان"
|
||||
STR_OPDS_SD_ROOT: "جذر بطاقة SD"
|
||||
STR_AUTO_TURN_ENABLED: "التقليب التلقائي مفعل: "
|
||||
STR_AUTO_TURN_PAGES_PER_MIN: "التقليب التلقائي (صفحات في الدقيقة)"
|
||||
STR_MANAGE_FONTS: "إدارة الخطوط"
|
||||
|
||||
@@ -10,7 +10,6 @@ STR_BROWSE_FILES: "Прагляд файлаў"
|
||||
STR_FILE_TRANSFER: "Перадача файлаў"
|
||||
STR_SETTINGS_TITLE: "Налады"
|
||||
STR_CONTINUE_READING: "Працягнуць чытанне"
|
||||
STR_RESUME: "Працягнуць"
|
||||
STR_NO_OPEN_BOOK: "Няма адкрытай кнігі"
|
||||
STR_START_READING: "Пачніце чытанне ніжэй"
|
||||
STR_NO_FILES_FOUND: "Файлы не знойдзены"
|
||||
@@ -19,32 +18,17 @@ STR_NO_CHAPTERS: "Раздзелаў няма"
|
||||
STR_END_OF_BOOK: "Канец кнігі"
|
||||
STR_EMPTY_CHAPTER: "Пусты раздзел"
|
||||
STR_INDEXING: "Індэксацыя"
|
||||
STR_INDEX_FAILED: "Памылка індэксацыі — няправільная кніга"
|
||||
STR_MEMORY_ERROR: "Памылка памяці"
|
||||
STR_PAGE_LOAD_ERROR: "Памылка загрузкі старонкі"
|
||||
STR_EMPTY_FILE: "Пусты файл"
|
||||
STR_INVALID_BMP_FILE: "Няправільны файл BMP"
|
||||
STR_FILE_OPEN_FAILED: "Не ўдалося адкрыць файл"
|
||||
STR_OUT_OF_BOUNDS: "Выхад за межы"
|
||||
STR_LOADING: "Загрузка..."
|
||||
STR_LOADING_POPUP: "Загрузка"
|
||||
STR_LOOKUP: "Шукаць"
|
||||
STR_DICT_LOOKING_UP: "Пошук..."
|
||||
STR_DICT_INDEXING: "Індэксацыя слоўніка..."
|
||||
STR_DICT_NOT_FOUND: "Не знойдзена"
|
||||
STR_DICT_NO_DICT_SET: "Слоўнік не выбраны"
|
||||
STR_DICT_ERROR: "Памылка слоўніка"
|
||||
STR_DICT_READ_FAILED: "Не ўдалося прачытаць азначэнне"
|
||||
STR_DICT_DECOMPRESS_ERROR: "Не ўдалося распакаваць азначэнне"
|
||||
STR_DICT_LOW_MEMORY: "Не хапае памяці"
|
||||
STR_WIFI_NETWORKS: "Сеткі Wi-Fi"
|
||||
STR_NO_NETWORKS: "Сеткі не знойдзены"
|
||||
STR_NETWORKS_FOUND: "Знойдзена сетак: %zu"
|
||||
STR_SCANNING: "Сканаванне..."
|
||||
STR_FINDING_SAVED_WIFI: "Пошук захаванай сеткі Wi-Fi..."
|
||||
STR_CONNECTING: "Падключэнне..."
|
||||
STR_CONNECTING_SAVED_WIFI: "Падключэнне да захаванай сеткі Wi-Fi..."
|
||||
STR_SHOW_NETWORKS: "Паказаць"
|
||||
STR_CONNECTED: "Падключана!"
|
||||
STR_CONNECTION_FAILED: "Памылка падключэння"
|
||||
STR_FORGET_NETWORK: "Забыць сетку?"
|
||||
@@ -86,11 +70,7 @@ STR_ORIENTATION: "Арыентацыя чытання"
|
||||
STR_SIDE_BTN_LAYOUT: "Бакавыя кнопкі"
|
||||
STR_TOUCH_READER_CONTROLS: "Сэнсарнае кіраванне чытаннем"
|
||||
STR_FRONT_BTN_FOLLOW_ORIENTATION: "Арыентаваць пярэднія кнопкі"
|
||||
STR_LONG_PRESS_BEHAVIOR: "Дзеянне доўгага націскання"
|
||||
STR_LONG_PRESS_BEHAVIOR_OFF: "ВЫКЛ"
|
||||
STR_LONG_PRESS_BEHAVIOR_SKIP: "Змена раздзела"
|
||||
STR_LONG_PRESS_BEHAVIOR_ORIENTATION: "Змена арыентацыі"
|
||||
STR_LONG_PRESS_MENU: "Меню доўгім націсканнем"
|
||||
STR_LONG_PRESS_SKIP: "Доўгае націсканне - змена раздзела"
|
||||
STR_FONT_PREVIEW_TEXT: "У Іўі худы жвавы чорт у зялёнай камізэльцы пабег пад'есці фаршу з юшкай"
|
||||
STR_FONT_FAMILY: "Шрыфт чытання"
|
||||
STR_FONT_SIZE: "Памер шрыфту інтэрфейсу"
|
||||
@@ -116,15 +96,7 @@ STR_PASSWORD: "Пароль"
|
||||
STR_SYNC_SERVER_URL: "URL сервера сінхранізацыі"
|
||||
STR_DOCUMENT_MATCHING: "Супастаўленне дакументаў"
|
||||
STR_SEND_METADATA: "Адпраўляць метаданыя дакумента"
|
||||
STR_SYNC_BEHAVIOR: "Рэжым сінхранізацыі"
|
||||
STR_ASK_EVERY_TIME: "Пытацца кожны раз"
|
||||
STR_SMART_SYNC: "Разумная сінхранізацыя"
|
||||
STR_AUTHENTICATE: "Аўтарызацыя"
|
||||
STR_SIGN_UP: "Рэгістрацыя"
|
||||
STR_CREATING_ACCOUNT: "Стварэнне ўліковага запісу..."
|
||||
STR_ACCOUNT_CREATED: "Уліковы запіс створаны"
|
||||
STR_SIGNUP_FAILED: "Памылка рэгістрацыі"
|
||||
STR_USERNAME_TAKEN: "Такое імя карыстальніка ўжо занята"
|
||||
STR_KOREADER_USERNAME: "Імя карыстальніка KOReader"
|
||||
STR_KOREADER_PASSWORD: "Пароль KOReader"
|
||||
STR_FILENAME: "Імя файла"
|
||||
@@ -160,7 +132,6 @@ STR_ALWAYS: "Заўсёды"
|
||||
STR_IGNORE: "Ігнараваць"
|
||||
STR_SLEEP: "Сон"
|
||||
STR_PAGE_TURN: "Перагортванне"
|
||||
STR_FORCE_REFRESH: "Абнавіць экран"
|
||||
STR_PORTRAIT: "Партрэт"
|
||||
STR_LANDSCAPE_CW: "Ландшафт (CW)"
|
||||
STR_INVERTED: "Інверсія"
|
||||
@@ -168,10 +139,6 @@ STR_ORIENTATION_INVERTED: "Партрэт 180°"
|
||||
STR_LANDSCAPE_CCW: "Ландшафт (CCW)"
|
||||
STR_PREV_NEXT: "Назад/Наперад"
|
||||
STR_NEXT_PREV: "Наперад/Назад"
|
||||
STR_KOSYNC: "KOSync"
|
||||
STR_BOOKMARK_OPTION: "Закладка"
|
||||
STR_DICTIONARY: "Слоўнік"
|
||||
STR_DISABLED: "Адключана"
|
||||
STR_NOTO_SERIF: "Noto Serif"
|
||||
STR_NOTO_SANS: "Noto Sans"
|
||||
STR_TIGHT: "Вузкі"
|
||||
@@ -196,7 +163,6 @@ STR_NO_UPDATE: "Абнаўленняў няма"
|
||||
STR_UPDATE_FAILED: "Памылка абнаўлення"
|
||||
STR_UPDATE_COMPLETE: "Абнаўленне завершана"
|
||||
STR_POWER_ON_HINT: "Утрымлівайце кнопку сілкавання для ўключэння"
|
||||
STR_RESTARTING_HINT: "Перазапуск... Калі прылада не перазапусцілася, утрымлівайце кнопку сілкавання некалькі секунд."
|
||||
STR_NO_ENTRIES: "Запісы не знойдзены"
|
||||
STR_DOWNLOADING: "Спампоўка..."
|
||||
STR_DOWNLOAD_FAILED: "Памылка спампоўкі"
|
||||
@@ -205,8 +171,6 @@ STR_UNNAMED: "Без імя"
|
||||
STR_NO_SERVER_URL: "URL сервера не наладжаны"
|
||||
STR_FETCH_FEED_FAILED: "Не ўдалося атрымаць стужку"
|
||||
STR_PARSE_FEED_FAILED: "Не ўдалося апрацаваць стужку"
|
||||
STR_NEXT_PAGE: "Наступная старонка »"
|
||||
STR_PREV_PAGE: "« Папярэдняя старонка"
|
||||
STR_NETWORK_PREFIX: "Сетка:"
|
||||
STR_IP_ADDRESS_PREFIX: "IP-адрас:"
|
||||
STR_ERROR_GENERAL_FAILURE: "Памылка: Агульная памылка"
|
||||
@@ -227,7 +191,6 @@ STR_CONNECT: "Падкл."
|
||||
STR_OPEN: "Адкрыць"
|
||||
STR_DOWNLOAD: "Спампаваць"
|
||||
STR_RETRY: "Паўтарыць"
|
||||
STR_TAP_TO_RETRY: "Націсніце, каб паўтарыць"
|
||||
STR_YES: "Так"
|
||||
STR_NO: "Не"
|
||||
STR_STATE_ON: "УКЛ"
|
||||
@@ -238,23 +201,16 @@ STR_DIR_RIGHT: "Управа"
|
||||
STR_DIR_UP: "Уверх"
|
||||
STR_DIR_DOWN: "Уніз"
|
||||
STR_OK_BUTTON: "OK"
|
||||
STR_KEY_SHIFT: "Shift"
|
||||
STR_KEY_MODE_SYMBOLS: "?123"
|
||||
STR_KEY_MODE_ABC: "abc"
|
||||
STR_SLEEP_COVER_FILTER: "Фільтр экрана сну"
|
||||
STR_FILTER_CONTRAST: "Кантраст"
|
||||
STR_UI_THEME: "Тэма інтэрфейсу"
|
||||
STR_THEME_CLASSIC: "Класічная"
|
||||
STR_THEME_LYRA: "Lyra"
|
||||
STR_THEME_ROUNDEDRAFF: "RoundedRaff"
|
||||
STR_THEME_LYRA_EXTENDED: "Lyra Extended"
|
||||
STR_SUNLIGHT_FADING_FIX: "Кампенсацыя выцвітання"
|
||||
STR_QUICK_RESUME_TIMEOUT: "Хуткае узнаўленне пасля таймаўту"
|
||||
STR_REMAP_FRONT_BUTTONS: "Пераназначыць пярэднія кнопкі"
|
||||
STR_BOOKMARKS: "Закладкі"
|
||||
STR_BOOKMARK_ADDED: "Закладка дададзена."
|
||||
STR_OPDS_BROWSER: "OPDS браўзер"
|
||||
STR_SEARCH: "Пошук"
|
||||
STR_COVER_CUSTOM: "Вокладка + Свой"
|
||||
STR_QUICK_RESUME: "Хуткае узнаўленне"
|
||||
STR_MENU_RECENT_BOOKS: "Нядаўнія кнігі"
|
||||
@@ -303,7 +259,6 @@ STR_UPLOAD_LOCAL: "Адправіць лакальны прагрэс"
|
||||
STR_NO_REMOTE_MSG: "Аддалены прагрэс не знойдзены"
|
||||
STR_UPLOAD_PROMPT: "Адправіць бягучую пазіцыю?"
|
||||
STR_UPLOAD_SUCCESS: "Прагрэс адпраўлены!"
|
||||
STR_ALREADY_SYNCED: "Ужо сінхранізавана"
|
||||
STR_SYNC_FAILED_MSG: "Памылка сінхранізацыі"
|
||||
STR_SAVE_PROGRESS_FAILED: "Не ўдалося захаваць прагрэс"
|
||||
STR_SECTION_PREFIX: "Раздзел"
|
||||
@@ -312,16 +267,11 @@ STR_BOOK_S_STYLE: "Стыль кнігі"
|
||||
STR_EMBEDDED_STYLE: "Убудаваны стыль"
|
||||
STR_FOCUS_READING: "Фокуснае чытанне"
|
||||
STR_OPDS_SERVER_URL: "URL OPDS сервера"
|
||||
STR_PWR_BTN_FOOTNOTE_BACK: "Хуткае вяртанне з зносак"
|
||||
STR_BACK_SHORT_TO_FILE_BROWSER: "Кароткае «Назад» да файлаў"
|
||||
STR_SET_SLEEP_COVER: "Задаць вокладку"
|
||||
STR_SCREENSHOT_BUTTON: "Зрабіць здымак экрана"
|
||||
STR_IMAGES: "Выявы"
|
||||
STR_IMAGES_DISPLAY: "Паказваць"
|
||||
STR_IMAGES_PLACEHOLDER: "Запаўняльнік"
|
||||
STR_IMAGES_SUPPRESS: "Хаваць"
|
||||
STR_EOB_HOME: "Галоўная"
|
||||
STR_EOB_CONTINUE_WITH: "Працягнуць з"
|
||||
STR_SHOW_HIDDEN_FILES: "Паказваць схаваныя файлы"
|
||||
STR_REMOVE_READ_FROM_RECENTS: "Ачышчаць прачытаныя кнігі са спісу нядаўніх"
|
||||
STR_MOVE_FINISHED_TO_READ: "Перамяшчаць прачытаныя кнігі ў тэчку Read"
|
||||
@@ -343,26 +293,7 @@ STR_EXAMPLE_BOOK: "Назва кнігі"
|
||||
STR_PREVIEW: "Перадпрагляд"
|
||||
STR_TITLE: "Назва"
|
||||
STR_BATTERY: "Батарэя"
|
||||
STR_XTC_STATUS_BAR: "Радок стану XTC"
|
||||
STR_BOTTOM: "Унізе"
|
||||
STR_TOP: "Уверсе"
|
||||
STR_CLOCK: "Гадзіннік"
|
||||
STR_CLOCK_UTC_OFFSET: "Зрух гадзінніка ад UTC"
|
||||
STR_CLOCK_FORMAT: "Фармат часу"
|
||||
STR_CLOCK_FORMAT_24H: "24-гадзінны"
|
||||
STR_CLOCK_FORMAT_12H: "12-гадзінны"
|
||||
STR_CURRENT_TIME: "Бягучы час:"
|
||||
STR_NEXT_FIELD: "Далей"
|
||||
STR_CLOCK_SYNC: "Сінхранізаваць гадзіннік"
|
||||
STR_CLOCK_SYNC_NOW: "Сінхранізаваць зараз"
|
||||
STR_CLOCK_SYNCING: "Сінхранізацыя праз NTP..."
|
||||
STR_CLOCK_SYNC_OK: "Гадзіннік сінхранізаваны"
|
||||
STR_CLOCK_SYNC_FAIL: "Памылка сінхранізацыі"
|
||||
STR_CLOCK_SYNC_NO_WIFI: "Wi-Fi не падключаны"
|
||||
STR_CLOCK_SYNC_NO_WIFI_HINT: "Спачатку падключыцеся да Wi-Fi, потым паўтарыце."
|
||||
STR_CLOCK_SYNCED: "Гадзіннік сінхранізаваны"
|
||||
STR_DELETE: "Выдаліць"
|
||||
STR_CONFIRM_DELETE_BOOKMARK: "Выдаліць гэтую закладку?"
|
||||
STR_DISPLAY_QR: "Паказаць старонку як QR"
|
||||
STR_FOOTNOTES: "Зноскі"
|
||||
STR_NO_FOOTNOTES: "На гэтай старонцы няма зносак"
|
||||
@@ -371,61 +302,13 @@ STR_SLEEP_TIMER_VALUE_FORMAT: "%u хв"
|
||||
STR_SLEEP_NEVER: "Ніколі"
|
||||
STR_STEP_HINT_FRONT: "Пярэднія кнопкі:"
|
||||
STR_STEP_HINT_SIDE: "Бакавыя кнопкі:"
|
||||
STR_ADD_SERVER: "Дадаць сервер"
|
||||
STR_SERVER_NAME: "Назва сервера"
|
||||
STR_NO_SERVERS: "Серверы OPDS не наладжаны"
|
||||
STR_DELETE_SERVER: "Выдаліць сервер"
|
||||
STR_OPDS_SERVERS: "Серверы OPDS"
|
||||
STR_OPDS_DOWNLOAD_FOLDER: "Папка для спампоўкі"
|
||||
STR_OPDS_FILENAME_FORMAT: "Фармат назвы файла"
|
||||
STR_FMT_AUTHOR_TITLE: "Аўтар - Назва"
|
||||
STR_FMT_TITLE_AUTHOR: "Назва - Аўтар"
|
||||
STR_FMT_TITLE: "Назва"
|
||||
STR_OPDS_SD_ROOT: "Корань SD"
|
||||
STR_AUTO_TURN_ENABLED: "Аўтаперагортванне: "
|
||||
STR_AUTO_TURN_PAGES_PER_MIN: "Аўтаперагортванне (старонак за хвіліну)"
|
||||
STR_MANAGE_FONTS: "Кіраванне шрыфтамі"
|
||||
STR_FONT_BROWSER: "Агляд шрыфтоў"
|
||||
STR_LOADING_FONT_LIST: "Загрузка спісу шрыфтоў..."
|
||||
STR_NO_FONTS_AVAILABLE: "Няма даступных шрыфтоў"
|
||||
STR_FONT_INSTALLED: "Шрыфт усталяваны!"
|
||||
STR_FONT_INSTALL_FAILED: "Не ўдалося ўсталяваць шрыфт"
|
||||
STR_INSTALLED: "Усталявана"
|
||||
STR_DOWNLOAD_ALL: "Спампаваць усе"
|
||||
STR_UPDATE_ALL: "Абнавіць усе"
|
||||
STR_UPDATE_AVAILABLE: "Абнавіць"
|
||||
STR_CRASH_TITLE: "Збой сістэмы"
|
||||
STR_CRASH_DESCRIPTION: "Падрабязная справаздача захавана ў crash_report.txt. Калі ласка, далучыце гэты файл да паведамлення пра памылку."
|
||||
STR_CRASH_REASON: "Прычына збою:"
|
||||
STR_CRASH_NO_REASON: "(Прычына не зафіксавана)"
|
||||
STR_TILT_PAGE_TURN: "Перагортванне нахілам"
|
||||
STR_KB_HINT_MOVE_CURSOR: "Націсніце ЎЛЕВА ці ЎПРАВА, каб перамясціць курсор"
|
||||
STR_KB_HINT_RETURN_CURSOR: "Націсніце ЎЛЕВА, каб вярнуцца да курсора"
|
||||
STR_KB_HINT_HIDE_PASSWORD: "Утрымлівайце ЎПРАВА, потым [***], каб схаваць пароль"
|
||||
STR_KB_HINT_SHOW_PASSWORD: "Утрымлівайце ЎПРАВА, потым [abc], каб паказаць пароль"
|
||||
STR_KB_HINT_TOGGLE_HIDE_PASSWORD: "Націсніце [***], каб схаваць пароль"
|
||||
STR_KB_HINT_TOGGLE_SHOW_PASSWORD: "Націсніце [abc], каб паказаць пароль"
|
||||
STR_KB_HINT_EDIT_ENTRY: "Утрымлівайце ЎВЕРХ, каб рэдагаваць запіс"
|
||||
STR_KB_TIPS: "Падказкі:"
|
||||
STR_KB_HINT_RETURN_KEYBOARD: "Націсніце ЎНІЗ, каб вярнуцца да клавіятуры"
|
||||
STR_KB_HINT_EXIT_URL_MODE: "Націсніце ABC, каб выйсці з рэжыму URL"
|
||||
STR_KB_HINT_CLEAR_TEXT: "Утрымлівайце DEL, каб сцерці ўвесь тэкст"
|
||||
STR_KB_HINT_SECONDARY_CHAR: "Утрымлівайце SELECT для дадатковага сімвала"
|
||||
STR_KB_HINT_UPPER_SECONDARY: "Утрымлівайце SELECT для ВЯЛІКАЙ ЛІТАРЫ ці дадатковага сімвала"
|
||||
STR_KB_HINT_LOWER_SECONDARY: "Утрымлівайце SELECT для малой літары ці дадатковага сімвала"
|
||||
STR_KB_HINT_URL_SNIPPETS: "Націсніце URL для шаблонаў"
|
||||
STR_SD_FIRMWARE_UPDATE: "Абнаўленне прашыўкі з SD-карты"
|
||||
STR_SELECT_FIRMWARE_FILE: "Абярыце файл прашыўкі (.bin)"
|
||||
STR_NO_BIN_FILES: "Файлы .bin не знойдзены"
|
||||
STR_VALIDATING_FIRMWARE: "Праверка прашыўкі..."
|
||||
STR_INVALID_FIRMWARE: "Няправільны файл прашыўкі"
|
||||
STR_FIRMWARE_TOO_LARGE: "Прашыўка завялікая для раздзела"
|
||||
STR_FIRMWARE_TOO_SMALL: "Файл прашыўкі занадта малы"
|
||||
STR_FIRMWARE_UPDATE_PROMPT: "Абнавіць прашыўку?"
|
||||
STR_FIRMWARE_FILE_OPEN_FAILED: "Не ўдалося адкрыць файл"
|
||||
STR_FIRMWARE_WRITE_FAILED: "Не ўдалося запісаць прашыўку"
|
||||
STR_FIRMWARE_UPDATE_DO_NOT_POWER_OFF: "Не выключайце прыладу!"
|
||||
STR_RECOVERY_MODE: "Рэжым аднаўлення"
|
||||
STR_RECOVERY_MODE_HINT: "Змясціце firmware.bin у корань SD-карты і абярыце яго"
|
||||
STR_ADD_HIDDEN_NETWORK: "Дадаць схаваную сетку..."
|
||||
STR_ENTER_WIFI_SSID: "Увядзіце назву сеткі (SSID)"
|
||||
@@ -9,7 +9,6 @@ STR_BROWSE_FILES: "Pregled datoteka"
|
||||
STR_FILE_TRANSFER: "Prijenos datoteka"
|
||||
STR_SETTINGS_TITLE: "Postavke"
|
||||
STR_CONTINUE_READING: "Nastavi čitanje"
|
||||
STR_RESUME: "Nastavi"
|
||||
STR_NO_OPEN_BOOK: "Nema otvorene knjige"
|
||||
STR_START_READING: "Počni čitati ispod"
|
||||
STR_NO_FILES_FOUND: "Nema pronađenih datoteka"
|
||||
@@ -22,20 +21,9 @@ STR_INDEX_FAILED: "Indeksiranje nije uspjelo - nevažeća knjiga"
|
||||
STR_MEMORY_ERROR: "Greška memorije"
|
||||
STR_PAGE_LOAD_ERROR: "Greška pri učitavanju stranice"
|
||||
STR_EMPTY_FILE: "Prazna datoteka"
|
||||
STR_INVALID_BMP_FILE: "Nevažeća BMP datoteka"
|
||||
STR_FILE_OPEN_FAILED: "Datoteka se ne može otvoriti"
|
||||
STR_OUT_OF_BOUNDS: "Izvan granica"
|
||||
STR_LOADING: "Učitavanje..."
|
||||
STR_LOADING_POPUP: "Učitavanje"
|
||||
STR_LOOKUP: "Potraži"
|
||||
STR_DICT_LOOKING_UP: "Traženje..."
|
||||
STR_DICT_INDEXING: "Indeksiranje rječnika..."
|
||||
STR_DICT_NOT_FOUND: "Nije pronađeno"
|
||||
STR_DICT_NO_DICT_SET: "Nije postavljen rječnik"
|
||||
STR_DICT_ERROR: "Greška rječnika"
|
||||
STR_DICT_READ_FAILED: "Čitanje definicije nije uspjelo"
|
||||
STR_DICT_DECOMPRESS_ERROR: "Dekompresija definicije nije uspjela"
|
||||
STR_DICT_LOW_MEMORY: "Nedovoljno memorije"
|
||||
STR_WIFI_NETWORKS: "Wi-Fi mreže"
|
||||
STR_NO_NETWORKS: "Nema pronađenih mreža"
|
||||
STR_NETWORKS_FOUND: "%zu pronađenih mreža"
|
||||
@@ -92,7 +80,6 @@ STR_EOB_CONTINUE_WITH: "Nastavi sa"
|
||||
STR_SHORT_PWR_BTN: "Kratak klik dugmeta napajanja"
|
||||
STR_ORIENTATION: "Orijentacija čitanja"
|
||||
STR_SIDE_BTN_LAYOUT: "Raspored bočnih dugmadi (čitač)"
|
||||
STR_TOUCH_READER_CONTROLS: "Dodirne kontrole čitača"
|
||||
STR_FRONT_BTN_FOLLOW_ORIENTATION: "Orijentiši prednja dugmad"
|
||||
STR_LONG_PRESS_BEHAVIOR: "Ponašanje dugog pritiska dugmeta"
|
||||
STR_LONG_PRESS_BEHAVIOR_OFF: "ISKLJUČENO"
|
||||
@@ -100,15 +87,8 @@ STR_LONG_PRESS_BEHAVIOR_SKIP: "Preskakanje poglavlja"
|
||||
STR_LONG_PRESS_BEHAVIOR_ORIENTATION: "Promjena orijentacije"
|
||||
STR_LONG_PRESS_MENU: "Meni dugog pritiska"
|
||||
STR_FONT_PREVIEW_TEXT: "Brza smeđa lisica preskače lijenog psa"
|
||||
STR_FONT_FAMILY: "Porodica pisma čitača"
|
||||
STR_FONT_SIZE: "Veličina pisma čitača"
|
||||
STR_TEXT_SETTINGS: "Postavke teksta"
|
||||
STR_FONT: "Pismo"
|
||||
STR_SIZE: "Veličina"
|
||||
STR_LAYOUT: "Izgled"
|
||||
STR_ALIGNMENT: "Poravnanje"
|
||||
STR_STYLE: "Stil"
|
||||
STR_NOT_IN_PREVIEW: "Nije prikazano u pregledu"
|
||||
STR_FONT_FAMILY: "Porodica fonta čitača"
|
||||
STR_FONT_SIZE: "Veličina fonta čitača"
|
||||
STR_LINE_SPACING: "Razmak između redova čitača"
|
||||
STR_SCREEN_MARGIN: "Margina ekrana čitača"
|
||||
STR_PARA_ALIGNMENT: "Poravnanje paragrafa čitača"
|
||||
@@ -127,15 +107,7 @@ STR_PASSWORD: "Lozinka"
|
||||
STR_SYNC_SERVER_URL: "URL servera za sinhronizaciju"
|
||||
STR_DOCUMENT_MATCHING: "Podudaranje dokumenata"
|
||||
STR_SEND_METADATA: "Pošalji metapodatke dokumenta"
|
||||
STR_SYNC_BEHAVIOR: "Ponašanje sinhronizacije"
|
||||
STR_ASK_EVERY_TIME: "Pitaj svaki put"
|
||||
STR_SMART_SYNC: "Pametna sinhronizacija"
|
||||
STR_AUTHENTICATE: "Autentifikuj"
|
||||
STR_SIGN_UP: "Registruj se"
|
||||
STR_CREATING_ACCOUNT: "Kreiranje računa..."
|
||||
STR_ACCOUNT_CREATED: "Račun je kreiran"
|
||||
STR_SIGNUP_FAILED: "Registracija nije uspjela"
|
||||
STR_USERNAME_TAKEN: "Korisničko ime je već registrovano"
|
||||
STR_KOREADER_USERNAME: "KOReader korisničko ime"
|
||||
STR_KOREADER_PASSWORD: "KOReader lozinka"
|
||||
STR_FILENAME: "Naziv datoteke"
|
||||
@@ -181,7 +153,6 @@ STR_PREV_NEXT: "Prethodno/Sljedeće"
|
||||
STR_NEXT_PREV: "Sljedeće/Prethodno"
|
||||
STR_KOSYNC: "KOSync"
|
||||
STR_BOOKMARK_OPTION: "Obilježivač"
|
||||
STR_DICTIONARY: "Rječnik"
|
||||
STR_DISABLED: "Onemogućeno"
|
||||
STR_NOTO_SERIF: "Noto Serif"
|
||||
STR_NOTO_SANS: "Noto Sans"
|
||||
@@ -238,7 +209,6 @@ STR_CONNECT: "Poveži"
|
||||
STR_OPEN: "Otvori"
|
||||
STR_DOWNLOAD: "Preuzmi"
|
||||
STR_RETRY: "Pokušaj ponovo"
|
||||
STR_TAP_TO_RETRY: "Dodirni za ponovni pokušaj"
|
||||
STR_YES: "Da"
|
||||
STR_NO: "Ne"
|
||||
STR_SHOW: "Prikaži"
|
||||
@@ -251,9 +221,6 @@ STR_DIR_RIGHT: "Desno"
|
||||
STR_DIR_UP: "Gore"
|
||||
STR_DIR_DOWN: "Dolje"
|
||||
STR_OK_BUTTON: "OK"
|
||||
STR_KEY_SHIFT: "Shift"
|
||||
STR_KEY_MODE_SYMBOLS: "?123"
|
||||
STR_KEY_MODE_ABC: "abc"
|
||||
STR_SLEEP_COVER_FILTER: "Filter korica ekrana mirovanja"
|
||||
STR_FILTER_CONTRAST: "Kontrast"
|
||||
STR_CUSTOMISE_STATUS_BAR: "Prilagodi statusnu traku"
|
||||
@@ -352,7 +319,6 @@ STR_UPLOAD_LOCAL: "Pošalji lokalni napredak"
|
||||
STR_NO_REMOTE_MSG: "Nije pronađen udaljeni napredak"
|
||||
STR_UPLOAD_PROMPT: "Poslati trenutnu poziciju?"
|
||||
STR_UPLOAD_SUCCESS: "Napredak poslan!"
|
||||
STR_ALREADY_SYNCED: "Već sinhronizovano"
|
||||
STR_SYNC_FAILED_MSG: "Sinhronizacija nije uspjela"
|
||||
STR_SAVE_PROGRESS_FAILED: "Napredak nije mogao biti sačuvan"
|
||||
STR_SECTION_PREFIX: "Sekcija "
|
||||
@@ -362,7 +328,6 @@ STR_EMBEDDED_STYLE: "Ugrađeni stil"
|
||||
STR_FOCUS_READING: "Fokusirano čitanje"
|
||||
STR_OPDS_SERVER_URL: "URL OPDS servera"
|
||||
STR_PWR_BTN_FOOTNOTE_BACK: "Brzi povratak iz fusnota"
|
||||
STR_BACK_SHORT_TO_FILE_BROWSER: "Brzi povratak na pregled datoteka"
|
||||
STR_SET_SLEEP_COVER: "Postavi korice"
|
||||
STR_FOOTNOTES: "Fusnote"
|
||||
STR_NO_FOOTNOTES: "Nema fusnota na ovoj stranici"
|
||||
@@ -377,20 +342,14 @@ STR_SERVER_NAME: "Naziv servera"
|
||||
STR_NO_SERVERS: "Nema podešenih OPDS servera"
|
||||
STR_DELETE_SERVER: "Obriši server"
|
||||
STR_OPDS_SERVERS: "OPDS serveri"
|
||||
STR_OPDS_DOWNLOAD_FOLDER: "Folder za preuzimanje"
|
||||
STR_OPDS_FILENAME_FORMAT: "Format naziva datoteke"
|
||||
STR_FMT_AUTHOR_TITLE: "Autor - Naslov"
|
||||
STR_FMT_TITLE_AUTHOR: "Naslov - Autor"
|
||||
STR_FMT_TITLE: "Naslov"
|
||||
STR_OPDS_SD_ROOT: "SD korijen"
|
||||
STR_AUTO_TURN_ENABLED: "Automatsko okretanje omogućeno: "
|
||||
STR_AUTO_TURN_PAGES_PER_MIN: "Automatsko okretanje (stranica po minuti)"
|
||||
STR_MANAGE_FONTS: "Upravljaj pismima"
|
||||
STR_FONT_BROWSER: "Pregledač pisama"
|
||||
STR_LOADING_FONT_LIST: "Učitavanje liste pisama..."
|
||||
STR_NO_FONTS_AVAILABLE: "Nema dostupnih pisama"
|
||||
STR_FONT_INSTALLED: "Pismo instalirano!"
|
||||
STR_FONT_INSTALL_FAILED: "Instalacija pisma nije uspjela"
|
||||
STR_MANAGE_FONTS: "Upravljaj fontovima"
|
||||
STR_FONT_BROWSER: "Pregledač fontova"
|
||||
STR_LOADING_FONT_LIST: "Učitavanje liste fontova..."
|
||||
STR_NO_FONTS_AVAILABLE: "Nema dostupnih fontova"
|
||||
STR_FONT_INSTALLED: "Font instaliran!"
|
||||
STR_FONT_INSTALL_FAILED: "Instalacija fonta nije uspjela"
|
||||
STR_INSTALLED: "Instalirano"
|
||||
STR_DOWNLOAD_ALL: "Preuzmi sve"
|
||||
STR_UPDATE_ALL: "Ažuriraj sve"
|
||||
|
||||
@@ -34,9 +34,6 @@ STR_DICT_INDEXING: "S'està indexant el diccionari..."
|
||||
STR_DICT_NOT_FOUND: "No s'ha trobat"
|
||||
STR_DICT_NO_DICT_SET: "No hi ha cap diccionari configurat"
|
||||
STR_DICT_ERROR: "Error del diccionari"
|
||||
STR_DICT_READ_FAILED: "No s'ha pogut llegir la definició"
|
||||
STR_DICT_DECOMPRESS_ERROR: "No s'ha pogut descomprimir la definició"
|
||||
STR_DICT_LOW_MEMORY: "No hi ha prou memòria"
|
||||
STR_WIFI_NETWORKS: "Xarxes Wi-Fi"
|
||||
STR_NO_NETWORKS: "No s'han trobat xarxes"
|
||||
STR_NETWORKS_FOUND: "%zu xarxes trobades"
|
||||
|
||||
@@ -21,8 +21,6 @@ STR_INDEXING: "Indexování"
|
||||
STR_MEMORY_ERROR: "Chyba paměti"
|
||||
STR_PAGE_LOAD_ERROR: "Chyba načítání stránky"
|
||||
STR_EMPTY_FILE: "Prázdný soubor"
|
||||
STR_INVALID_BMP_FILE: "Neplatný soubor BMP"
|
||||
STR_FILE_OPEN_FAILED: "Nelze otevřít soubor"
|
||||
STR_OUT_OF_BOUNDS: "Mimo hranice"
|
||||
STR_LOADING: "Načítání..."
|
||||
STR_LOADING_POPUP: "Načítání"
|
||||
@@ -334,9 +332,6 @@ STR_DICT_INDEXING: "Indexování slovníku..."
|
||||
STR_DICT_LOOKING_UP: "Vyhledávání..."
|
||||
STR_DICT_NOT_FOUND: "Nenalezeno"
|
||||
STR_DICT_NO_DICT_SET: "Není nastaven žádný slovník"
|
||||
STR_DICT_READ_FAILED: "Nelze přečíst definici"
|
||||
STR_DICT_DECOMPRESS_ERROR: "Nelze dekomprimovat definici"
|
||||
STR_DICT_LOW_MEMORY: "Nedostatek paměti"
|
||||
STR_DISABLED: "Zakázáno"
|
||||
STR_DISPLAY_QR: "Zobrazit stránku jako QR"
|
||||
STR_DOWNLOAD_ALL: "Stáhnout vše"
|
||||
|
||||
@@ -423,7 +423,6 @@ STR_VALIDATING_FIRMWARE: "Validating firmware..."
|
||||
STR_INVALID_FIRMWARE: "Invalid firmware file"
|
||||
STR_FIRMWARE_TOO_LARGE: "Firmware too large for partition"
|
||||
STR_FIRMWARE_TOO_SMALL: "Firmware file is too small"
|
||||
STR_FIRMWARE_WRONG_DEVICE: "Firmware is for a different device"
|
||||
STR_FIRMWARE_UPDATE_PROMPT: "Update firmware?"
|
||||
STR_FIRMWARE_FILE_OPEN_FAILED: "Cannot open file"
|
||||
STR_FIRMWARE_WRITE_FAILED: "Firmware write failed"
|
||||
|
||||
@@ -10,7 +10,6 @@ STR_BROWSE_FILES: "Parcourir les fichiers"
|
||||
STR_FILE_TRANSFER: "Transfert de fichiers"
|
||||
STR_SETTINGS_TITLE: "Réglages"
|
||||
STR_CONTINUE_READING: "Reprendre la lecture"
|
||||
STR_RESUME: "Reprendre"
|
||||
STR_NO_OPEN_BOOK: "Aucun livre ouvert"
|
||||
STR_START_READING: "Commencer la lecture"
|
||||
STR_NO_FILES_FOUND: "Aucun fichier trouvé"
|
||||
@@ -19,32 +18,17 @@ STR_NO_CHAPTERS: "Aucun chapitre"
|
||||
STR_END_OF_BOOK: "Fin du livre"
|
||||
STR_EMPTY_CHAPTER: "Chapitre vide"
|
||||
STR_INDEXING: "Indexation en cours"
|
||||
STR_INDEX_FAILED: "Échec de l'indexation - livre invalide"
|
||||
STR_MEMORY_ERROR: "Erreur de mémoire"
|
||||
STR_PAGE_LOAD_ERROR: "Erreur de chargement"
|
||||
STR_EMPTY_FILE: "Fichier vide"
|
||||
STR_INVALID_BMP_FILE: "Fichier BMP invalide"
|
||||
STR_FILE_OPEN_FAILED: "Impossible d'ouvrir le fichier"
|
||||
STR_OUT_OF_BOUNDS: "Dépassement de mémoire"
|
||||
STR_LOADING: "Chargement…"
|
||||
STR_LOADING_POPUP: "Chargement"
|
||||
STR_LOOKUP: "Rechercher"
|
||||
STR_DICT_LOOKING_UP: "Recherche dans le dictionnaire…"
|
||||
STR_DICT_INDEXING: "Indexation du dictionnaire…"
|
||||
STR_DICT_NOT_FOUND: "Non trouvé"
|
||||
STR_DICT_NO_DICT_SET: "Aucun dictionnaire défini"
|
||||
STR_DICT_ERROR: "Erreur de dictionnaire"
|
||||
STR_DICT_READ_FAILED: "Impossible de lire la définition"
|
||||
STR_DICT_DECOMPRESS_ERROR: "Échec décompression définition"
|
||||
STR_DICT_LOW_MEMORY: "Mémoire insuffisante"
|
||||
STR_WIFI_NETWORKS: "Réseaux Wi-Fi"
|
||||
STR_NO_NETWORKS: "Aucun réseau"
|
||||
STR_NETWORKS_FOUND: "%zu réseaux"
|
||||
STR_SCANNING: "Recherche en cours…"
|
||||
STR_FINDING_SAVED_WIFI: "Recherche Wi-Fi connu…"
|
||||
STR_CONNECTING: "Connexion en cours…"
|
||||
STR_CONNECTING_SAVED_WIFI: "Connexion au Wi-Fi connu…"
|
||||
STR_SHOW_NETWORKS: "Afficher"
|
||||
STR_CONNECTED: "Connecté !"
|
||||
STR_CONNECTION_FAILED: "Échec de la connexion"
|
||||
STR_FORGET_NETWORK: "Oublier ce réseau ?"
|
||||
@@ -65,8 +49,6 @@ STR_NETWORK_LEGEND: "* = Sécurisé | + = Sauvegardé"
|
||||
STR_MAC_ADDRESS: "Adresse MAC :"
|
||||
STR_CHECKING_WIFI: "Vérification du Wi-Fi…"
|
||||
STR_ENTER_WIFI_PASSWORD: "Entrez le mot de passe Wi-Fi"
|
||||
STR_ADD_HIDDEN_NETWORK: "Ajouter un réseau masqué..."
|
||||
STR_ENTER_WIFI_SSID: "Saisir le nom du réseau (SSID)"
|
||||
STR_TO_PREFIX: "vers "
|
||||
STR_CALIBRE_RECEIVING: "Réception : "
|
||||
STR_CALIBRE_RECEIVED: "Reçu : "
|
||||
@@ -79,27 +61,23 @@ STR_CAT_READER: "Lecteur"
|
||||
STR_CAT_CONTROLS: "Commandes"
|
||||
STR_CAT_SYSTEM: "Système"
|
||||
STR_SLEEP_SCREEN: "Écran de veille"
|
||||
STR_QUICK_RESUME_TIMEOUT: "Reprise rapide après délai"
|
||||
STR_SLEEP_COVER_MODE: "Mode écran de veille"
|
||||
STR_HIDE_BATTERY: "Masquer % batterie"
|
||||
STR_EXTRA_SPACING: "Espacement paragraphes supp."
|
||||
STR_EXTRA_SPACING: "Espacement paragraphes"
|
||||
STR_TEXT_AA: "Lissage du texte"
|
||||
STR_IMAGES: "Images"
|
||||
STR_IMAGES_DISPLAY: "Affichage"
|
||||
STR_IMAGES_PLACEHOLDER: "Espace réservé"
|
||||
STR_IMAGES_SUPPRESS: "Masquer"
|
||||
STR_EOB_HOME: "Accueil"
|
||||
STR_EOB_CONTINUE_WITH: "Poursuivre avec"
|
||||
STR_SHORT_PWR_BTN: "Appui court bouton alim."
|
||||
STR_SHORT_PWR_BTN: "Appui court alim."
|
||||
STR_ORIENTATION: "Orientation de lecture"
|
||||
STR_SIDE_BTN_LAYOUT: "Boutons latéraux (lecteur)"
|
||||
STR_SIDE_BTN_LAYOUT: "Boutons latéraux"
|
||||
STR_TOUCH_READER_CONTROLS: "Commandes tactiles lecteur"
|
||||
STR_FRONT_BTN_FOLLOW_ORIENTATION: "Orienter boutons avant"
|
||||
STR_LONG_PRESS_BEHAVIOR: "Comportement lors d'un appui long"
|
||||
STR_LONG_PRESS_BEHAVIOR_OFF: "Désactivé"
|
||||
STR_LONG_PRESS_BEHAVIOR_SKIP: "Saut de chapitre"
|
||||
STR_LONG_PRESS_BEHAVIOR_ORIENTATION: "Changement d'orientation"
|
||||
STR_LONG_PRESS_MENU: "Menu appui long"
|
||||
STR_FONT_PREVIEW_TEXT: "Portez ce vieux whisky au juge blond qui fume"
|
||||
STR_FONT_FAMILY: "Police de caractères du lecteur"
|
||||
STR_FONT_SIZE: "Taille police lecteur"
|
||||
@@ -107,9 +85,9 @@ STR_TEXT_SETTINGS: "Réglages du texte"
|
||||
STR_FONT: "Police"
|
||||
STR_SIZE: "Taille"
|
||||
STR_LAYOUT: "Disposition"
|
||||
STR_ALIGNMENT: "Alignement"
|
||||
STR_STYLE: "Style"
|
||||
STR_NOT_IN_PREVIEW: "Absent de l'aperçu"
|
||||
STR_ALIGNMENT: "Alignement"
|
||||
STR_LINE_SPACING: "Interligne"
|
||||
STR_SCREEN_MARGIN: "Marges"
|
||||
STR_PARA_ALIGNMENT: "Alignement du paragraphe"
|
||||
@@ -128,17 +106,9 @@ STR_PASSWORD: "Mot de passe"
|
||||
STR_SYNC_SERVER_URL: "URL du serveur"
|
||||
STR_DOCUMENT_MATCHING: "Correspondance"
|
||||
STR_SEND_METADATA: "Envoyer métadonnées"
|
||||
STR_SYNC_BEHAVIOR: "Comportement de synchro"
|
||||
STR_ASK_EVERY_TIME: "Toujours demander"
|
||||
STR_SMART_SYNC: "Synchro intelligente"
|
||||
STR_AUTHENTICATE: "Connexion"
|
||||
STR_SIGN_UP: "Créer un compte"
|
||||
STR_CREATING_ACCOUNT: "Création du compte…"
|
||||
STR_ACCOUNT_CREATED: "Compte créé"
|
||||
STR_SIGNUP_FAILED: "Échec de la création"
|
||||
STR_USERNAME_TAKEN: "Nom d'utilisateur déjà pris"
|
||||
STR_KOREADER_USERNAME: "Utilisateur KOReader"
|
||||
STR_KOREADER_PASSWORD: "Mot de passe KOReader"
|
||||
STR_KOREADER_USERNAME: "Utilisateur"
|
||||
STR_KOREADER_PASSWORD: "Mot de passe"
|
||||
STR_FILENAME: "Nom de fichier"
|
||||
STR_BINARY: "Binaire"
|
||||
STR_SET_CREDENTIALS_FIRST: "Identifiants manquants"
|
||||
@@ -156,7 +126,7 @@ STR_CLEAR_CACHE_WARNING_4: "à la prochaine ouverture."
|
||||
STR_CLEARING_CACHE: "Nettoyage du cache…"
|
||||
STR_CACHE_CLEARED: "Cache vidé"
|
||||
STR_ITEMS_REMOVED: "éléments supprimés"
|
||||
STR_FAILED_LOWER: "Echec"
|
||||
STR_FAILED_LOWER: "ont échoué"
|
||||
STR_CLEAR_CACHE_FAILED: "Échec nettoyage cache"
|
||||
STR_CHECK_SERIAL_OUTPUT: "Voir console pour détails"
|
||||
STR_DARK: "Sombre"
|
||||
@@ -172,7 +142,6 @@ STR_ALWAYS: "Toujours"
|
||||
STR_IGNORE: "Ignorer"
|
||||
STR_SLEEP: "Mise en veille"
|
||||
STR_PAGE_TURN: "Page suivante"
|
||||
STR_FORCE_REFRESH: "Rafraîchir l'écran"
|
||||
STR_PORTRAIT: "Portrait"
|
||||
STR_LANDSCAPE_CW: "Paysage"
|
||||
STR_INVERTED: "Inversé"
|
||||
@@ -180,10 +149,6 @@ STR_ORIENTATION_INVERTED: "Portrait 180°"
|
||||
STR_LANDSCAPE_CCW: "Paysage inversé"
|
||||
STR_PREV_NEXT: "Préc/Suiv"
|
||||
STR_NEXT_PREV: "Suiv/Préc"
|
||||
STR_KOSYNC: "KOSync"
|
||||
STR_BOOKMARK_OPTION: "Marque-page"
|
||||
STR_DICTIONARY: "Dictionnaire"
|
||||
STR_DISABLED: "Désactivé"
|
||||
STR_NOTO_SERIF: "Noto Serif"
|
||||
STR_NOTO_SANS: "Noto Sans"
|
||||
STR_TIGHT: "Serré"
|
||||
@@ -208,18 +173,14 @@ STR_NO_UPDATE: "Aucune mise à jour"
|
||||
STR_UPDATE_FAILED: "Échec de la mise à jour"
|
||||
STR_UPDATE_COMPLETE: "Mise à jour effectuée"
|
||||
STR_POWER_ON_HINT: "Maintenir Power pour redémarrer"
|
||||
STR_RESTARTING_HINT: "Redémarrage… Si l'appareil ne redémarre pas, maintenez le bouton Power enfoncé quelques secondes."
|
||||
STR_NO_ENTRIES: "Aucune entrée"
|
||||
STR_DOWNLOADING: "Téléchargement…"
|
||||
STR_DOWNLOAD_FAILED: "Échec du téléchargement"
|
||||
STR_ERROR_MSG: "Erreur : "
|
||||
STR_UNNAMED: "Sans titre"
|
||||
STR_HOLD_OPEN_TO_DELETE: "Maintenir Ouvrir pour supprimer"
|
||||
STR_NO_SERVER_URL: "URL serveur non configurée"
|
||||
STR_FETCH_FEED_FAILED: "Échec récupération flux"
|
||||
STR_PARSE_FEED_FAILED: "Échec analyse flux"
|
||||
STR_NEXT_PAGE: "Page suivante »"
|
||||
STR_PREV_PAGE: "« Page précédente"
|
||||
STR_NETWORK_PREFIX: "Réseau : "
|
||||
STR_IP_ADDRESS_PREFIX: "IP : "
|
||||
STR_ERROR_GENERAL_FAILURE: "Erreur : Échec général"
|
||||
@@ -233,13 +194,14 @@ STR_SELECT: "OK"
|
||||
STR_SELECTED: "Sélectionné"
|
||||
STR_TOGGLE: "Modifier"
|
||||
STR_TOGGLE_BOOKMARK: "Basculer le marque-page"
|
||||
STR_BOOKMARK_REMOVED: "Marque-page supprimé."
|
||||
STR_HOLD_OPEN_TO_DELETE: "Maintenir Ouvrir pour supprimer"
|
||||
STR_CONFIRM: "Confirmer"
|
||||
STR_CANCEL: "Annuler"
|
||||
STR_CONNECT: "Connecter"
|
||||
STR_OPEN: "Ouvrir"
|
||||
STR_DOWNLOAD: "Télécharger"
|
||||
STR_RETRY: "Réessayer"
|
||||
STR_TAP_TO_RETRY: "Appuyer pour réessayer"
|
||||
STR_YES: "Oui"
|
||||
STR_NO: "Non"
|
||||
STR_SHOW: "Afficher"
|
||||
@@ -252,9 +214,6 @@ STR_DIR_RIGHT: "Droite"
|
||||
STR_DIR_UP: "Haut"
|
||||
STR_DIR_DOWN: "Bas"
|
||||
STR_OK_BUTTON: "OK"
|
||||
STR_KEY_SHIFT: "Maj"
|
||||
STR_KEY_MODE_SYMBOLS: "?123"
|
||||
STR_KEY_MODE_ABC: "abc"
|
||||
STR_SLEEP_COVER_FILTER: "Filtre écran de veille"
|
||||
STR_FILTER_CONTRAST: "Contraste"
|
||||
STR_CUSTOMISE_STATUS_BAR: "Personnaliser la barre d'état"
|
||||
@@ -272,36 +231,15 @@ STR_EXAMPLE_BOOK: "Titre du livre"
|
||||
STR_PREVIEW: "Aperçu"
|
||||
STR_TITLE: "Titre"
|
||||
STR_BATTERY: "Batterie"
|
||||
STR_XTC_STATUS_BAR: "Barre d'état XTC"
|
||||
STR_BOTTOM: "Bas"
|
||||
STR_TOP: "Haut"
|
||||
STR_CLOCK: "Horloge"
|
||||
STR_CLOCK_UTC_OFFSET: "Décalage UTC horloge"
|
||||
STR_CLOCK_FORMAT: "Format de l'heure"
|
||||
STR_CLOCK_FORMAT_24H: "24 heures"
|
||||
STR_CLOCK_FORMAT_12H: "12 heures"
|
||||
STR_CURRENT_TIME: "Heure actuelle :"
|
||||
STR_NEXT_FIELD: "Suivant"
|
||||
STR_CLOCK_SYNC: "Synchro horloge"
|
||||
STR_CLOCK_SYNC_NOW: "Synchroniser l'heure"
|
||||
STR_CLOCK_SYNCING: "Synchro via NTP…"
|
||||
STR_CLOCK_SYNC_OK: "Horloge synchronisée"
|
||||
STR_CLOCK_SYNC_FAIL: "Échec synchro"
|
||||
STR_CLOCK_SYNC_NO_WIFI: "Wi-Fi non connecté"
|
||||
STR_CLOCK_SYNC_NO_WIFI_HINT: "Connectez le Wi-Fi avant de réessayer."
|
||||
STR_CLOCK_SYNCED: "Horloge synchronisée"
|
||||
STR_UI_THEME: "Thème interface"
|
||||
STR_THEME_CLASSIC: "Classique"
|
||||
STR_THEME_LYRA: "Lyra"
|
||||
STR_THEME_ROUNDEDRAFF: "RoundedRaff"
|
||||
STR_THEME_LYRA_EXTENDED: "Lyra Extended"
|
||||
STR_SUNLIGHT_FADING_FIX: "Correction lisibilité au soleil"
|
||||
STR_QUICK_RESUME_TIMEOUT: "Reprise rapide après délai"
|
||||
STR_REMAP_FRONT_BUTTONS: "Configurer boutons façade"
|
||||
STR_BOOKMARKS: "Marque-pages"
|
||||
STR_BOOKMARK_ADDED: "Marque-page ajouté."
|
||||
STR_BOOKMARK_REMOVED: "Marque-page supprimé."
|
||||
STR_OPDS_BROWSER: "Navigateur OPDS"
|
||||
STR_SEARCH: "Rechercher"
|
||||
STR_COVER_CUSTOM: "Couverture + Perso"
|
||||
STR_QUICK_RESUME: "Reprise rapide"
|
||||
STR_MENU_RECENT_BOOKS: "Livres récents"
|
||||
@@ -329,7 +267,6 @@ STR_GO_HOME_BUTTON: "Retour Accueil"
|
||||
STR_SYNC_PROGRESS: "Synchro progression"
|
||||
STR_DELETE_CACHE: "Supprimer cache livre"
|
||||
STR_DELETE: "Supprimer"
|
||||
STR_CONFIRM_DELETE_BOOKMARK: "Supprimer ce marque-page ?"
|
||||
STR_DISPLAY_QR: "Afficher la page en QR"
|
||||
STR_CHAPTER_PREFIX: "Chapitre : "
|
||||
STR_PAGES_SEPARATOR: " pages | "
|
||||
@@ -353,7 +290,6 @@ STR_UPLOAD_LOCAL: "Envoyer progression locale"
|
||||
STR_NO_REMOTE_MSG: "Aucune progression en ligne"
|
||||
STR_UPLOAD_PROMPT: "Envoyer position actuelle ?"
|
||||
STR_UPLOAD_SUCCESS: "Progression envoyée !"
|
||||
STR_ALREADY_SYNCED: "Déjà synchronisé"
|
||||
STR_SYNC_FAILED_MSG: "Échec de la synchro"
|
||||
STR_SAVE_PROGRESS_FAILED: "Échec de l'enregistrement"
|
||||
STR_SECTION_PREFIX: "Section "
|
||||
@@ -362,70 +298,21 @@ STR_BOOK_S_STYLE: "Style du livre"
|
||||
STR_EMBEDDED_STYLE: "Style intégré"
|
||||
STR_FOCUS_READING: "Lecture focalisée"
|
||||
STR_OPDS_SERVER_URL: "URL serveur OPDS"
|
||||
STR_PWR_BTN_FOOTNOTE_BACK: "Retour rapide depuis notes de bas de page"
|
||||
STR_BACK_SHORT_TO_FILE_BROWSER: "Retour court vers fichiers"
|
||||
STR_SET_SLEEP_COVER: "Définir comme couverture"
|
||||
STR_FOOTNOTES: "Notes de bas de page"
|
||||
STR_NO_FOOTNOTES: "Aucune note sur cette page"
|
||||
STR_LINK: "[lien]"
|
||||
STR_SCREENSHOT_BUTTON: "Capture d'écran"
|
||||
STR_SLEEP_TIMER_VALUE_FORMAT: "%u min"
|
||||
STR_SLEEP_NEVER: "Jamais"
|
||||
STR_STEP_HINT_FRONT: "Boutons avant :"
|
||||
STR_STEP_HINT_SIDE: "Boutons latéraux :"
|
||||
STR_ADD_SERVER: "Ajouter un serveur"
|
||||
STR_SERVER_NAME: "Nom du serveur"
|
||||
STR_NO_SERVERS: "Aucun serveur OPDS configuré"
|
||||
STR_DELETE_SERVER: "Supprimer le serveur"
|
||||
STR_OPDS_SERVERS: "Serveurs OPDS"
|
||||
STR_OPDS_DOWNLOAD_FOLDER: "Dossier de téléchargement"
|
||||
STR_OPDS_FILENAME_FORMAT: "Format du nom de fichier"
|
||||
STR_FMT_AUTHOR_TITLE: "Auteur - Titre"
|
||||
STR_FMT_TITLE_AUTHOR: "Titre - Auteur"
|
||||
STR_FMT_TITLE: "Titre"
|
||||
STR_OPDS_SD_ROOT: "Racine SD"
|
||||
STR_SCREENSHOT_BUTTON: "Capture d'écran"
|
||||
STR_AUTO_TURN_ENABLED: "Tourne-page auto : "
|
||||
STR_AUTO_TURN_PAGES_PER_MIN: "Tourne-page auto (pages par minute)"
|
||||
STR_MANAGE_FONTS: "Gérer les polices"
|
||||
STR_FONT_BROWSER: "Navigateur de polices"
|
||||
STR_LOADING_FONT_LIST: "Chargement des polices…"
|
||||
STR_NO_FONTS_AVAILABLE: "Aucune police disponible"
|
||||
STR_FONT_INSTALLED: "Police installée !"
|
||||
STR_FONT_INSTALL_FAILED: "Échec installation police"
|
||||
STR_INSTALLED: "Installée"
|
||||
STR_DOWNLOAD_ALL: "Tout télécharger"
|
||||
STR_UPDATE_ALL: "Tout mettre à jour"
|
||||
STR_UPDATE_AVAILABLE: "Mettre à jour"
|
||||
STR_CRASH_TITLE: "Plantage système"
|
||||
STR_CRASH_DESCRIPTION: "Un rapport détaillé a été enregistré sous crash_report.txt. Veuillez l'inclure dans votre rapport de bug."
|
||||
STR_CRASH_REASON: "Raison du plantage :"
|
||||
STR_CRASH_NO_REASON: "(Aucune raison enregistrée)"
|
||||
STR_TILT_PAGE_TURN: "Tourner par inclinaison"
|
||||
STR_KB_HINT_MOVE_CURSOR: "Appuyer GAUCHE ou DROITE pour déplacer le curseur"
|
||||
STR_KB_HINT_RETURN_CURSOR: "Appuyer GAUCHE pour revenir au curseur"
|
||||
STR_KB_HINT_HIDE_PASSWORD: "Maintenir DROITE puis appuyer [***] pour masquer"
|
||||
STR_KB_HINT_SHOW_PASSWORD: "Maintenir DROITE puis appuyer [abc] pour afficher"
|
||||
STR_KB_HINT_TOGGLE_HIDE_PASSWORD: "Appuyer [***] pour masquer le mot de passe"
|
||||
STR_KB_HINT_TOGGLE_SHOW_PASSWORD: "Appuyer [abc] pour afficher le mot de passe"
|
||||
STR_KB_HINT_EDIT_ENTRY: "Maintenir HAUT pour modifier"
|
||||
STR_KB_TIPS: "Conseils :"
|
||||
STR_KB_HINT_RETURN_KEYBOARD: "Appuyer BAS pour revenir au clavier"
|
||||
STR_KB_HINT_EXIT_URL_MODE: "Appuyer ABC pour quitter le mode URL"
|
||||
STR_KB_HINT_CLEAR_TEXT: "Maintenir DEL pour effacer le texte"
|
||||
STR_KB_HINT_SECONDARY_CHAR: "Maintenir OK pour caractère secondaire"
|
||||
STR_KB_HINT_UPPER_SECONDARY: "Maintenir OK pour MAJUSCULE ou secondaire"
|
||||
STR_KB_HINT_LOWER_SECONDARY: "Maintenir OK pour minuscule ou secondaire"
|
||||
STR_KB_HINT_URL_SNIPPETS: "Appuyer URL pour les raccourcis"
|
||||
STR_SD_FIRMWARE_UPDATE: "Mise à jour du firmware par carte SD"
|
||||
STR_SELECT_FIRMWARE_FILE: "Sélectionner le fichier firmware (.bin)"
|
||||
STR_NO_BIN_FILES: "Aucun fichier .bin trouvé"
|
||||
STR_VALIDATING_FIRMWARE: "Validation du firmware…"
|
||||
STR_INVALID_FIRMWARE: "Fichier firmware invalide"
|
||||
STR_FIRMWARE_TOO_LARGE: "Firmware trop volumineux pour la partition"
|
||||
STR_FIRMWARE_TOO_SMALL: "Fichier firmware trop petit"
|
||||
STR_FIRMWARE_UPDATE_PROMPT: "Mettre à jour le firmware ?"
|
||||
STR_FIRMWARE_FILE_OPEN_FAILED: "Impossible d'ouvrir le fichier"
|
||||
STR_FIRMWARE_WRITE_FAILED: "Échec de l'écriture du firmware"
|
||||
STR_FIRMWARE_UPDATE_DO_NOT_POWER_OFF: "Ne pas éteindre l'appareil !"
|
||||
STR_RECOVERY_MODE: "Mode Récupération"
|
||||
STR_RECOVERY_MODE_HINT: "Placez firmware.bin à la racine de la carte SD et sélectionnez-le"
|
||||
STR_ADD_HIDDEN_NETWORK: "Ajouter un réseau masqué..."
|
||||
STR_ENTER_WIFI_SSID: "Saisir le nom du réseau (SSID)"
|
||||
@@ -394,38 +394,3 @@ STR_RECOVERY_MODE: "Wiederherstellungsmodus"
|
||||
STR_RECOVERY_MODE_HINT: "Lege firmware.bin im SD-Kartenwurzelverzeichnis ab und wähle es aus"
|
||||
STR_ADD_HIDDEN_NETWORK: "Verstecktes Netzwerk hinzufügen…"
|
||||
STR_ENTER_WIFI_SSID: "Netzwerknamen eingeben (SSID)"
|
||||
STR_ACCOUNT_CREATED: "Konto erstellt"
|
||||
STR_ALREADY_SYNCED: "Bereits synchronisiert"
|
||||
STR_ASK_EVERY_TIME: "Immer fragen"
|
||||
STR_BOOKMARK_OPTION: "Lesezeichen"
|
||||
STR_CONNECTING_SAVED_WIFI: "Verbinde mit gespeichertem WLAN-Netzwerk…"
|
||||
STR_CREATING_ACCOUNT: "Erstelle Konto…"
|
||||
STR_DICTIONARY: "Wörterbuch"
|
||||
STR_DICT_ERROR: "Wörterbuch Fehler"
|
||||
STR_DICT_INDEXING: "Indexiere Wörterbuch…"
|
||||
STR_DICT_LOOKING_UP: "Suche…"
|
||||
STR_DICT_NOT_FOUND: "Nicht gefunden"
|
||||
STR_DICT_NO_DICT_SET: "Kein Wörterbuch festgelegt"
|
||||
STR_EOB_CONTINUE_WITH: "Weiter mit"
|
||||
STR_EOB_HOME: "Home"
|
||||
STR_FINDING_SAVED_WIFI: "Finde gespeichertes WLAN-Netzwerk…"
|
||||
STR_INDEX_FAILED: "Fehler beim Indexieren - ungültiges Buch"
|
||||
STR_KEY_MODE_ABC: "abc"
|
||||
STR_KEY_MODE_SYMBOLS: "?123"
|
||||
STR_KEY_SHIFT: "Shift"
|
||||
STR_KOSYNC: "KOSync"
|
||||
STR_LOOKUP: "Nachschlagen"
|
||||
STR_OPDS_SD_ROOT: "SD-Karten Hauptverzeichnis"
|
||||
STR_PWR_BTN_FOOTNOTE_BACK: "Schnellrücksprung aus Fußnoten"
|
||||
STR_SHOW_NETWORKS: "Zeige Netzwerke"
|
||||
STR_SIGNUP_FAILED: "Anmeldung fehlgeschlagen"
|
||||
STR_SIGN_UP: "Anmelden"
|
||||
STR_SMART_SYNC: "Smart"
|
||||
STR_SYNC_BEHAVIOR: "Synchronisierungsverhalten"
|
||||
STR_TAP_TO_RETRY: "Tippen zum Wiederholen"
|
||||
STR_USERNAME_TAKEN: "Benutzername ist bereits registriert"
|
||||
STR_FILE_OPEN_FAILED: "Kann Datei nicht öffnen"
|
||||
STR_INVALID_BMP_FILE: "Ungültige BMP-Datei"
|
||||
STR_DICT_DECOMPRESS_ERROR: "Konnte Definition nicht entpacken"
|
||||
STR_DICT_LOW_MEMORY: "Nicht genug Speicher"
|
||||
STR_DICT_READ_FAILED: "Konnte Definition nicht lesen"
|
||||
@@ -10,41 +10,25 @@ STR_BROWSE_FILES: "סייר קבצים"
|
||||
STR_FILE_TRANSFER: "העברת קבצים"
|
||||
STR_SETTINGS_TITLE: "הגדרות"
|
||||
STR_CONTINUE_READING: "המשך קריאה"
|
||||
STR_RESUME: "המשך"
|
||||
STR_NO_OPEN_BOOK: "אין ספר פתוח"
|
||||
STR_START_READING: "התחל לקרוא"
|
||||
STR_START_READING: "התחל לקרוא למטה"
|
||||
STR_NO_FILES_FOUND: "לא נמצאו קבצים"
|
||||
STR_SELECT_CHAPTER: "בחר פרק"
|
||||
STR_NO_CHAPTERS: "אין פרקים"
|
||||
STR_END_OF_BOOK: "סוף הספר"
|
||||
STR_EMPTY_CHAPTER: "פרק ריק"
|
||||
STR_INDEXING: "מאנדקס..."
|
||||
STR_INDEX_FAILED: "האינדוקס נכשל - ספר לא תקין"
|
||||
STR_MEMORY_ERROR: "שגיאת זיכרון"
|
||||
STR_PAGE_LOAD_ERROR: "שגיאה בטעינת הדף"
|
||||
STR_EMPTY_FILE: "קובץ ריק"
|
||||
STR_INVALID_BMP_FILE: "קובץ BMP לא תקין"
|
||||
STR_FILE_OPEN_FAILED: "לא ניתן לפתוח את הקובץ"
|
||||
STR_OUT_OF_BOUNDS: "מחוץ לטווח"
|
||||
STR_LOADING: "טוען..."
|
||||
STR_LOADING_POPUP: "טוען"
|
||||
STR_LOOKUP: "חפש במילון"
|
||||
STR_DICT_LOOKING_UP: "מחפש..."
|
||||
STR_DICT_INDEXING: "מאנדקס מילון..."
|
||||
STR_DICT_NOT_FOUND: "לא נמצא"
|
||||
STR_DICT_NO_DICT_SET: "לא הוגדר מילון"
|
||||
STR_DICT_ERROR: "שגיאת מילון"
|
||||
STR_DICT_READ_FAILED: "לא ניתן לקרוא את ההגדרה"
|
||||
STR_DICT_DECOMPRESS_ERROR: "לא ניתן לחלץ את ההגדרה"
|
||||
STR_DICT_LOW_MEMORY: "אין מספיק זיכרון"
|
||||
STR_WIFI_NETWORKS: "רשתות אלחוטיות (WiFi)"
|
||||
STR_NO_NETWORKS: "לא נמצאו רשתות"
|
||||
STR_NETWORKS_FOUND: "נמצאו %zu רשתות"
|
||||
STR_SCANNING: "סורק..."
|
||||
STR_FINDING_SAVED_WIFI: "מחפש רשת אלחוטית שמורה..."
|
||||
STR_CONNECTING: "מתחבר..."
|
||||
STR_CONNECTING_SAVED_WIFI: "מתחבר לרשת אלחוטית שמורה..."
|
||||
STR_SHOW_NETWORKS: "הצג"
|
||||
STR_CONNECTED: "מחובר!"
|
||||
STR_CONNECTION_FAILED: "החיבור נכשל"
|
||||
STR_FORGET_NETWORK: "לשכוח רשת זו?"
|
||||
@@ -75,7 +59,7 @@ STR_CALIBRE_INSTRUCTION_3: "3) בתוכנת Calibre: בחר \"שלח למכשי
|
||||
STR_CALIBRE_INSTRUCTION_4: "השאר מסך זה פתוח בזמן ההעברה"
|
||||
STR_CAT_DISPLAY: "תצוגה"
|
||||
STR_CAT_READER: "קורא"
|
||||
STR_CAT_CONTROLS: "לחצנים"
|
||||
STR_CAT_CONTROLS: "מקשים"
|
||||
STR_CAT_SYSTEM: "מערכת"
|
||||
STR_SLEEP_SCREEN: "מסך מצב שינה"
|
||||
STR_SLEEP_COVER_MODE: "תצוגת כריכה במצב שינה"
|
||||
@@ -84,13 +68,11 @@ STR_EXTRA_SPACING: "מרווח פסקאות מוגדל"
|
||||
STR_TEXT_AA: "החלקת קצוות טקסט"
|
||||
STR_IMAGES: "תמונות"
|
||||
STR_IMAGES_DISPLAY: "הצג תמונות"
|
||||
STR_IMAGES_PLACEHOLDER: "מסגרת ריקה"
|
||||
STR_IMAGES_PLACEHOLDER: "סמן"
|
||||
STR_IMAGES_SUPPRESS: "הסתר תמונות"
|
||||
STR_EOB_HOME: "מסך הבית"
|
||||
STR_EOB_CONTINUE_WITH: "המשך עם"
|
||||
STR_SHORT_PWR_BTN: "לחיצה קצרה על לחצן ההפעלה"
|
||||
STR_ORIENTATION: "כיוון מסך"
|
||||
STR_SIDE_BTN_LAYOUT: "פריסת לחצני צד (בקריאה)"
|
||||
STR_SHORT_PWR_BTN: "לחיצה קצרה על כפתור ההפעלה"
|
||||
STR_ORIENTATION: "כיוון קריאה (מסך)"
|
||||
STR_SIDE_BTN_LAYOUT: "פריסת כפתורי צד (בקריאה)"
|
||||
STR_TOUCH_READER_CONTROLS: "שליטה במגע (קורא)"
|
||||
STR_LONG_PRESS_BEHAVIOR: "פעולת לחיצה ארוכה"
|
||||
STR_LONG_PRESS_BEHAVIOR_OFF: "כבוי"
|
||||
@@ -106,11 +88,11 @@ STR_LAYOUT: "פריסה"
|
||||
STR_STYLE: "סגנון"
|
||||
STR_NOT_IN_PREVIEW: "לא מוצג בתצוגה המקדימה"
|
||||
STR_ALIGNMENT: "יישור"
|
||||
STR_LINE_SPACING: "מרווח בין שורות"
|
||||
STR_LINE_SPACING: "מרווח שורות"
|
||||
STR_SCREEN_MARGIN: "שוליים"
|
||||
STR_PARA_ALIGNMENT: "יישור פסקה"
|
||||
STR_HYPHENATION: "מיקוף"
|
||||
STR_TIME_TO_SLEEP: "טיימר למצב שינה"
|
||||
STR_TIME_TO_SLEEP: "זמן עד לשינה"
|
||||
STR_SHOW_HIDDEN_FILES: "הצג קבצים נסתרים"
|
||||
STR_REFRESH_FREQ: "תדירות רענון מסך"
|
||||
STR_KOREADER_SYNC: "סנכרון KOReader"
|
||||
@@ -122,19 +104,11 @@ STR_PASSWORD: "סיסמה"
|
||||
STR_SYNC_SERVER_URL: "כתובת שרת סנכרון"
|
||||
STR_DOCUMENT_MATCHING: "התאמת מסמכים"
|
||||
STR_SEND_METADATA: "שלח מטא-נתוני מסמך"
|
||||
STR_SYNC_BEHAVIOR: "אופן הסנכרון"
|
||||
STR_ASK_EVERY_TIME: "שאל בכל פעם"
|
||||
STR_SMART_SYNC: "סנכרון חכם"
|
||||
STR_AUTHENTICATE: "התחבר לחשבון"
|
||||
STR_SIGN_UP: "הרשמה"
|
||||
STR_CREATING_ACCOUNT: "יוצר חשבון..."
|
||||
STR_ACCOUNT_CREATED: "החשבון נוצר"
|
||||
STR_SIGNUP_FAILED: "ההרשמה נכשלה"
|
||||
STR_USERNAME_TAKEN: "שם המשתמש כבר רשום במערכת"
|
||||
STR_AUTHENTICATE: "התחבר"
|
||||
STR_KOREADER_USERNAME: "שם משתמש ב-KOReader"
|
||||
STR_KOREADER_PASSWORD: "סיסמת KOReader"
|
||||
STR_FILENAME: "לפי שם קובץ"
|
||||
STR_BINARY: "לפי תוכן"
|
||||
STR_FILENAME: "שם קובץ"
|
||||
STR_BINARY: "בינארי"
|
||||
STR_SET_CREDENTIALS_FIRST: "הגדר תחילה פרטי התחברות"
|
||||
STR_WIFI_CONN_FAILED: "חיבור הרשת נכשל"
|
||||
STR_AUTHENTICATING: "מאמת נתונים..."
|
||||
@@ -169,7 +143,7 @@ STR_PAGE_TURN: "העברת דף"
|
||||
STR_FORCE_REFRESH: "רענון מסך מלא"
|
||||
STR_PORTRAIT: "לאורך"
|
||||
STR_LANDSCAPE_CW: "לרוחב (ימינה)"
|
||||
STR_INVERTED: "הפוך"
|
||||
STR_INVERTED: "היפוך צבעים"
|
||||
STR_ORIENTATION_INVERTED: "לאורך 180°"
|
||||
STR_LANDSCAPE_CCW: "לרוחב (שמאלה)"
|
||||
STR_PREV_NEXT: "הקודם/הבא"
|
||||
@@ -197,8 +171,8 @@ STR_UPDATING: "מעדכן..."
|
||||
STR_NO_UPDATE: "לא נמצאו עדכונים"
|
||||
STR_UPDATE_FAILED: "העדכון נכשל"
|
||||
STR_UPDATE_COMPLETE: "העדכון הושלם"
|
||||
STR_POWER_ON_HINT: "לחץ לחיצה ארוכה על לחצן ההפעלה כדי להדליק שוב"
|
||||
STR_RESTARTING_HINT: "מופעל מחדש... אם המכשיר לא נדלק, החזק את לחצן ההפעלה מספר שניות."
|
||||
STR_POWER_ON_HINT: "לחץ לחיצה ארוכה על כפתור ההפעלה כדי להדליק שוב"
|
||||
STR_RESTARTING_HINT: "מופעל מחדש... אם המכשיר לא נדלק, החזק את כפתור ההפעלה מספר שניות."
|
||||
STR_NO_ENTRIES: "לא נמצאו רשומות"
|
||||
STR_DOWNLOADING: "מוריד..."
|
||||
STR_DOWNLOAD_FAILED: "ההורדה נכשלה"
|
||||
@@ -220,7 +194,7 @@ STR_EXIT: "יציאה »"
|
||||
STR_HOME: "מסך הבית »"
|
||||
STR_SELECT: "בחר"
|
||||
STR_SELECTED: "נבחר"
|
||||
STR_TOGGLE: "שנה"
|
||||
STR_TOGGLE: "בחר"
|
||||
STR_TOGGLE_BOOKMARK: "הוסף/הסר סימנייה"
|
||||
STR_CONFIRM: "אישור"
|
||||
STR_CANCEL: "ביטול"
|
||||
@@ -228,7 +202,6 @@ STR_CONNECT: "התחבר"
|
||||
STR_OPEN: "פתח"
|
||||
STR_DOWNLOAD: "הורד"
|
||||
STR_RETRY: "נסה שוב"
|
||||
STR_TAP_TO_RETRY: "הקש כדי לנסות שוב"
|
||||
STR_YES: "כן"
|
||||
STR_NO: "לא"
|
||||
STR_SHOW: "הצג"
|
||||
@@ -241,9 +214,6 @@ STR_DIR_RIGHT: "ימין"
|
||||
STR_DIR_UP: "למעלה"
|
||||
STR_DIR_DOWN: "למטה"
|
||||
STR_OK_BUTTON: "אישור"
|
||||
STR_KEY_SHIFT: "Shift"
|
||||
STR_KEY_MODE_SYMBOLS: "?123"
|
||||
STR_KEY_MODE_ABC: "abc"
|
||||
STR_SLEEP_COVER_FILTER: "פילטר תמונה במצב שינה"
|
||||
STR_FILTER_CONTRAST: "ניגודיות (קונטרסט)"
|
||||
STR_CUSTOMISE_STATUS_BAR: "התאם אישית שורת מצב"
|
||||
@@ -270,7 +240,7 @@ STR_THEME_LYRA: "Lyra"
|
||||
STR_THEME_ROUNDEDRAFF: "RoundedRaff"
|
||||
STR_THEME_LYRA_EXTENDED: "Lyra מורחב"
|
||||
STR_SUNLIGHT_FADING_FIX: "תיקון דהיית מסך בשמש"
|
||||
STR_REMAP_FRONT_BUTTONS: "שנה תפקיד ללחצנים קדמיים"
|
||||
STR_REMAP_FRONT_BUTTONS: "שנה תפקיד לכפתורים קדמיים"
|
||||
STR_OPDS_BROWSER: "דפדפן OPDS"
|
||||
STR_SEARCH: "חיפוש"
|
||||
STR_COVER_CUSTOM: "כריכה + מותאם אישית"
|
||||
@@ -284,16 +254,16 @@ STR_CALIBRE_SETUP: "הגדרות"
|
||||
STR_CALIBRE_STATUS: "מצב"
|
||||
STR_CLEAR_BUTTON: "נקה"
|
||||
STR_DEFAULT_VALUE: "ברירת מחדל"
|
||||
STR_REMAP_PROMPT: "לחץ על לחצן קדמי לכל פעולה"
|
||||
STR_REMAP_PROMPT: "לחץ על כפתור קדמי לכל פעולה"
|
||||
STR_UNASSIGNED: "לא מוקצה"
|
||||
STR_ALREADY_ASSIGNED: "כבר בשימוש"
|
||||
STR_REMAP_RESET_HINT: "לחצן צד עליון: שחזר לפריסת ברירת מחדל"
|
||||
STR_REMAP_CANCEL_HINT: "לחצן צד תחתון: בטל הגדרה מחדש"
|
||||
STR_HW_BACK_LABEL: "חזור (לחצן 1)"
|
||||
STR_HW_CONFIRM_LABEL: "אישור (לחצן 2)"
|
||||
STR_HW_LEFT_LABEL: "שמאלה (לחצן 3)"
|
||||
STR_HW_RIGHT_LABEL: "ימינה (לחצן 4)"
|
||||
STR_GO_TO_PERCENT: "קפוץ למיקום (%)"
|
||||
STR_REMAP_RESET_HINT: "כפתור צד עליון: שחזר לפריסת ברירת מחדל"
|
||||
STR_REMAP_CANCEL_HINT: "כפתור צד תחתון: בטל הגדרה מחדש"
|
||||
STR_HW_BACK_LABEL: "חזור (כפתור 1)"
|
||||
STR_HW_CONFIRM_LABEL: "אישור (כפתור 2)"
|
||||
STR_HW_LEFT_LABEL: "שמאלה (כפתור 3)"
|
||||
STR_HW_RIGHT_LABEL: "ימינה (כפתור 4)"
|
||||
STR_GO_TO_PERCENT: "עבור לאחוז %"
|
||||
STR_GO_HOME_BUTTON: "חזור למסך הבית"
|
||||
STR_SYNC_PROGRESS: "סנכרן התקדמות"
|
||||
STR_DELETE_CACHE: "מחק קבצי מטמון (Cache)"
|
||||
@@ -321,16 +291,14 @@ STR_UPLOAD_LOCAL: "העלה התקדמות מהמכשיר לשרת"
|
||||
STR_NO_REMOTE_MSG: "לא נמצאה התקדמות בשרת"
|
||||
STR_UPLOAD_PROMPT: "להעלות את המיקום הנוכחי לשרת?"
|
||||
STR_UPLOAD_SUCCESS: "ההתקדמות הועלתה בהצלחה!"
|
||||
STR_ALREADY_SYNCED: "כבר מסונכרן"
|
||||
STR_SYNC_FAILED_MSG: "הסנכרון נכשל"
|
||||
STR_SAVE_PROGRESS_FAILED: "שמירת ההתקדמות נכשלה"
|
||||
STR_SECTION_PREFIX: "חלק "
|
||||
STR_UPLOAD: "העלה"
|
||||
STR_BOOK_S_STYLE: "לפי הספר"
|
||||
STR_BOOK_S_STYLE: "עיצוב הספר המקורי"
|
||||
STR_EMBEDDED_STYLE: "סגנון מוטמע"
|
||||
STR_FOCUS_READING: "קריאה ממוקדת"
|
||||
STR_OPDS_SERVER_URL: "כתובת שרת OPDS"
|
||||
STR_BACK_SHORT_TO_FILE_BROWSER: "חזרה קצרה לסייר הקבצים"
|
||||
STR_SET_SLEEP_COVER: "הגדר כריכה"
|
||||
STR_FOOTNOTES: "הערות שוליים"
|
||||
STR_NO_FOOTNOTES: "אין הערות שוליים בדף זה"
|
||||
@@ -347,7 +315,6 @@ STR_OPDS_FILENAME_FORMAT: "תבנית שם קובץ"
|
||||
STR_FMT_AUTHOR_TITLE: "מחבר - כותרת"
|
||||
STR_FMT_TITLE_AUTHOR: "כותרת - מחבר"
|
||||
STR_FMT_TITLE: "כותרת"
|
||||
STR_OPDS_SD_ROOT: "שורש כרטיס ה-SD"
|
||||
STR_AUTO_TURN_ENABLED: "דפדוף אוטומטי פועל: "
|
||||
STR_AUTO_TURN_PAGES_PER_MIN: "דפדוף אוטומטי (דפים בדקה)"
|
||||
STR_MANAGE_FONTS: "ניהול גופנים"
|
||||
@@ -380,7 +347,7 @@ STR_KB_HINT_TOGGLE_SHOW_PASSWORD: "לחץ על [abc] כדי להציג סיסמ
|
||||
STR_KB_HINT_EDIT_ENTRY: "החזק למעלה כדי לערוך"
|
||||
STR_KB_TIPS: "טיפים:"
|
||||
STR_KB_HINT_RETURN_KEYBOARD: "לחץ למטה כדי לחזור למקלדת"
|
||||
STR_KB_HINT_EXIT_URL_MODE: "לחץ על ABC ליציאה ממצב URL"
|
||||
STR_KB_HINT_EXIT_URL_MODE: "לחץ על ABC ליציאה ממצב אינטרנט"
|
||||
STR_KB_HINT_CLEAR_TEXT: "החזק מחיקה (DEL) לניקוי כל הטקסט"
|
||||
STR_KB_HINT_SECONDARY_CHAR: "החזק בחר (SELECT) לתו משני"
|
||||
STR_KB_HINT_UPPER_SECONDARY: "החזק בחר (SELECT) לאות גדולה או לתו משני"
|
||||
@@ -402,8 +369,8 @@ STR_RECOVERY_MODE_HINT: "שים את הקובץ firmware.bin בתיקייה הר
|
||||
STR_QUICK_RESUME_TIMEOUT: "חזרה מהירה לאחר פסק זמן"
|
||||
STR_FRONT_BTN_FOLLOW_ORIENTATION: "התאמת לחצנים קדמיים לכיוון המסך"
|
||||
STR_REMOVE_READ_FROM_RECENTS: "הסר ספרים שנקראו מרשימת האחרונים"
|
||||
STR_MOVE_FINISHED_TO_READ: "העבר ספרים שהסתיימו לתיקיית 'read'"
|
||||
STR_DISABLED: "כבוי"
|
||||
STR_MOVE_FINISHED_TO_READ: "העבר ספרים שהסתיימו לתיקיית 'נקראו'"
|
||||
STR_DISABLED: "מבוטל"
|
||||
STR_HOLD_OPEN_TO_DELETE: "לחיצה ארוכה על 'פתח' כדי למחוק"
|
||||
STR_CLOCK: "שעון"
|
||||
STR_CLOCK_UTC_OFFSET: "הפרש זמן UTC"
|
||||
@@ -429,7 +396,6 @@ STR_CONFIRM_DELETE_BOOKMARK: "למחוק סימנייה זו?"
|
||||
STR_LONG_PRESS_MENU: "לחיצה ארוכה על אישור"
|
||||
STR_KOSYNC: "KOSync"
|
||||
STR_BOOKMARK_OPTION: "סימנייה"
|
||||
STR_DICTIONARY: "מילון"
|
||||
STR_PWR_BTN_FOOTNOTE_BACK: "חזרה מהירה מהערות שוליים"
|
||||
STR_SLEEP_TIMER_VALUE_FORMAT: "%u דקות"
|
||||
STR_SLEEP_NEVER: "אף פעם"
|
||||
|
||||
Loaded 20 of 59 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user