## Summary This PR introduces **Focus Reading**, a generic implementation of artificial fixation points (similar to Bionic Reading) designed to improve reading speed and focus by bolding the initial characters of words. This is achieved by dynamically bolding characters during indexing. <img width="500" alt="Focus Reading on X3" src="https://github.com/user-attachments/assets/94a632a5-82da-47be-957c-538b35bf84d9" /> ### Implementation Details #### Core Text Engine (`ParsedText`) - Modified `ParsedText::addWord` to implement a custom bolding algorithm. It uses a 45% ratio for bolding, with a minimum of 1 character and a maximum of 9. - UTF-8 Safety: Integrated `utf8NextCodepoint` to ensure character counting and string slicing occur at safe byte boundaries, preventing corruption of multi-byte characters (e.g., accented letters or smart quotes). - Intelligent Tokenization: This correctly identifies and separates "word" characters (letters, apostrophes, hyphens) from "non-word" characters (numbers, brackets, smart quotes). - Formatting Preservation: The logic ensures that punctuation is not "stolen" for the bolding count and that existing styles (like italics or underlines) are preserved across the bold/regular split. - Processing at indexing stage reduces CPU load at render-time and ensures layout/fit is unaffected. - Split details are tracked with `wordIsFocusSuffix`. After splitting and layout, suffixes are merged back into their preceding word entries to prevent a doubling of RAM usage. #### Settings and UI - Version Management: Bumped `SECTION_FILE_VERSION` to `21` - Global Settings: Added `focusReadingEnabled` to `CrossPointSettings`. - User Interface: Added a new toggle in the "Reader" section of the settings menu, positioned after the "Embedded Style" option. - Localization: Added the `STR_FOCUS_READING` string #### Plumbing - Plumbed the `focusReadingEnabled` boolean through `EpubReaderActivity`, `Section`, and `ChapterHtmlSlimParser` to ensure the user's setting reaches the `ParsedText` constructor during chapter indexing. ## Additional Context ### Files Changed - `lib/Epub/Epub/ParsedText.h / .cpp`: Core fixation logic and UTF-8 tokenization. - `lib/Epub/Epub/Section.h / .cpp`: Cache header updates and invalidation logic. - `lib/Epub/Epub/parsers/ChapterHtmlSlimParser.h / .cpp`: Plumbing the setting to text blocks. - `src/CrossPointSettings.h`: Data persistence for the new setting. - `src/SettingsList.h`: UI toggle implementation. - `src/activities/reader/EpubReaderActivity.cpp`: Handling settings changes during reading sessions. - `lib/I18n/translations/*.yaml`: UI strings. --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? _**YES**_
299 lines
12 KiB
YAML
299 lines
12 KiB
YAML
_language_name: "Català"
|
|
_language_code: "CA"
|
|
_order: "9"
|
|
|
|
STR_CROSSPOINT: "CrossPoint"
|
|
STR_BOOTING: "ARRENCANT"
|
|
STR_SLEEPING: "ENTRANT EN REPÒS"
|
|
STR_ENTERING_SLEEP: "Entrant en repòs"
|
|
STR_BROWSE_FILES: "Explora fitxers"
|
|
STR_FILE_TRANSFER: "Transferència"
|
|
STR_SETTINGS_TITLE: "Configuració"
|
|
STR_CONTINUE_READING: "Continua llegint"
|
|
STR_NO_OPEN_BOOK: "Cap llibre obert"
|
|
STR_START_READING: "Inicia la lectura a continuació"
|
|
STR_NO_FILES_FOUND: "No s'han trobat fitxers"
|
|
STR_SELECT_CHAPTER: "Selecciona el capítol"
|
|
STR_NO_CHAPTERS: "Sense capítols"
|
|
STR_END_OF_BOOK: "Final del llibre"
|
|
STR_EMPTY_CHAPTER: "Capítol buit"
|
|
STR_INDEXING: "S'està indexant"
|
|
STR_MEMORY_ERROR: "Error de memòria"
|
|
STR_PAGE_LOAD_ERROR: "Error en carregar la pàgina"
|
|
STR_EMPTY_FILE: "Fitxer buit"
|
|
STR_OUT_OF_BOUNDS: "Fora de límits"
|
|
STR_LOADING: "S'està carregant..."
|
|
STR_LOADING_POPUP: "S'està carregant"
|
|
STR_WIFI_NETWORKS: "Xarxes WiFi"
|
|
STR_NO_NETWORKS: "No s'han trobat xarxes"
|
|
STR_NETWORKS_FOUND: "%zu xarxes trobades"
|
|
STR_SCANNING: "S'està escanejant..."
|
|
STR_CONNECTING: "S'està connectant..."
|
|
STR_CONNECTED: "S'ha connectat!"
|
|
STR_CONNECTION_FAILED: "Error de connexió"
|
|
STR_FORGET_NETWORK: "Voleu oblidar aquesta xarxa?"
|
|
STR_SAVE_PASSWORD: "Voleu desar la contrasenya per a la propera vegada?"
|
|
STR_PRESS_OK_SCAN: "Premeu OK per tornar a escanejar"
|
|
STR_JOIN_NETWORK: "Uneix-te a una xarxa"
|
|
STR_CREATE_HOTSPOT: "Crea un punt d'accés"
|
|
STR_JOIN_DESC: "Connecta't a una xarxa WiFi existent"
|
|
STR_HOTSPOT_DESC: "Crea una xarxa WiFi per unir-s'hi"
|
|
STR_STARTING_HOTSPOT: "S'està iniciant el punt d'accés..."
|
|
STR_HOTSPOT_MODE: "Mode de punt d'accés"
|
|
STR_CONNECT_WIFI_HINT: "Connecteu el dispositiu a aquesta xarxa WiFi"
|
|
STR_OPEN_URL_HINT: "Obriu aquest URL al navegador"
|
|
STR_OR_HTTP_PREFIX: "o http://"
|
|
STR_SCAN_QR_HINT: "o escanegeu el codi QR amb el telèfon:"
|
|
STR_CALIBRE_WIRELESS: "Calibre sense fils"
|
|
STR_CALIBRE_WEB_URL: "OPDS URL"
|
|
STR_NETWORK_LEGEND: "* = Encriptat | + = Desat"
|
|
STR_MAC_ADDRESS: "Adreça MAC:"
|
|
STR_CHECKING_WIFI: "S'està comprovant el WiFi..."
|
|
STR_ENTER_WIFI_PASSWORD: "Introduïu la contrasenya WiFi"
|
|
STR_TO_PREFIX: "a "
|
|
STR_CALIBRE_RECEIVING: "S'està rebent: "
|
|
STR_CALIBRE_RECEIVED: "S'ha rebut: "
|
|
STR_CALIBRE_INSTRUCTION_1: "1) Instal·leu el connector CrossPoint Reader"
|
|
STR_CALIBRE_INSTRUCTION_2: "2) Estigueu a la mateixa xarxa WiFi"
|
|
STR_CALIBRE_INSTRUCTION_3: "3) A Calibre: \"Envia a un dispositiu\""
|
|
STR_CALIBRE_INSTRUCTION_4: "\"Mantingueu aquesta pantalla oberta mentre s'envia\""
|
|
STR_CAT_DISPLAY: "Visualització"
|
|
STR_CAT_READER: "Lector"
|
|
STR_CAT_CONTROLS: "Controls"
|
|
STR_CAT_SYSTEM: "Sistema"
|
|
STR_SLEEP_SCREEN: "Pantalla de repòs"
|
|
STR_SLEEP_COVER_MODE: "Mode de pantalla de repòs"
|
|
STR_HIDE_BATTERY: "Oculta el % de bateria"
|
|
STR_EXTRA_SPACING: "Espaiat de paràgraf extra"
|
|
STR_TEXT_AA: "Antialiàsing del text"
|
|
STR_IMAGES: "Imatges"
|
|
STR_IMAGES_DISPLAY: "Mostrar"
|
|
STR_IMAGES_PLACEHOLDER: "Text de mostra"
|
|
STR_IMAGES_SUPPRESS: "Suprimir"
|
|
STR_SHORT_PWR_BTN: "Clic curt del botó d'engegada"
|
|
STR_ORIENTATION: "Orientació de lectura"
|
|
STR_SIDE_BTN_LAYOUT: "Disposició botons laterals"
|
|
STR_LONG_PRESS_BEHAVIOR: "Comportament de prémer llargament el botó"
|
|
STR_LONG_PRESS_BEHAVIOR_OFF: "Desactivat"
|
|
STR_LONG_PRESS_BEHAVIOR_SKIP: "Saltar capítols"
|
|
STR_LONG_PRESS_BEHAVIOR_ORIENTATION: "Canvi d'orientació"
|
|
STR_FONT_FAMILY: "Tipus de lletra"
|
|
STR_FONT_SIZE: "Mida de la lletra (UI)"
|
|
STR_LINE_SPACING: "Interlineat del lector"
|
|
STR_SCREEN_MARGIN: "Marge de pantalla del lector"
|
|
STR_PARA_ALIGNMENT: "Alineació de paràgrafs del lector"
|
|
STR_HYPHENATION: "Partició de mots"
|
|
STR_TIME_TO_SLEEP: "Temps per entrar en repòs"
|
|
STR_SHOW_HIDDEN_FILES: "Mostra fitxers ocults"
|
|
STR_REFRESH_FREQ: "Freqüència de refresc"
|
|
STR_KOREADER_SYNC: "Sincronització del KOReader"
|
|
STR_CHECK_UPDATES: "Comprova si hi ha actualitzacions"
|
|
STR_LANGUAGE: "Idioma"
|
|
STR_CLEAR_READING_CACHE: "Esborra la memòria cau de lectura"
|
|
STR_USERNAME: "Nom d'usuari"
|
|
STR_PASSWORD: "Contrasenya"
|
|
STR_SYNC_SERVER_URL: "URL del servidor de sincronització"
|
|
STR_DOCUMENT_MATCHING: "Coincidència de documents"
|
|
STR_AUTHENTICATE: "Autentica"
|
|
STR_KOREADER_USERNAME: "Nom d'usuari del KOReader"
|
|
STR_KOREADER_PASSWORD: "Contrasenya del KOReader"
|
|
STR_FILENAME: "Nom de fitxer"
|
|
STR_BINARY: "Binari"
|
|
STR_SET_CREDENTIALS_FIRST: "Estableix les credencials primer"
|
|
STR_WIFI_CONN_FAILED: "Connexió WiFi fallida"
|
|
STR_AUTHENTICATING: "S'està autenticant..."
|
|
STR_AUTH_SUCCESS: "Autenticació correcta!"
|
|
STR_KOREADER_AUTH: "Autenticació del KOReader"
|
|
STR_SYNC_READY: "La sincronització del KOReader està preparada per utilitzar-se"
|
|
STR_AUTH_FAILED: "Autenticació fallida"
|
|
STR_DONE: "Fet"
|
|
STR_CLEAR_CACHE_WARNING_1: "Això esborrarà totes les dades de lectura de la memòria cau."
|
|
STR_CLEAR_CACHE_WARNING_2: "Es perdrà tot el progrés de lectura!"
|
|
STR_CLEAR_CACHE_WARNING_3: "Els llibres hauran de ser reindexats"
|
|
STR_CLEAR_CACHE_WARNING_4: "quan s'obrin de nou."
|
|
STR_CLEARING_CACHE: "S'està esborrant la memòria cau..."
|
|
STR_CACHE_CLEARED: "Memòria cau esborrada"
|
|
STR_ITEMS_REMOVED: "elements suprimits"
|
|
STR_FAILED_LOWER: "ha fallat"
|
|
STR_CLEAR_CACHE_FAILED: "No s'ha pogut esborrar la memòria cau"
|
|
STR_CHECK_SERIAL_OUTPUT: "Comprova la sortida en sèrie per obtenir detalls"
|
|
STR_DARK: "Fosc"
|
|
STR_LIGHT: "Clar"
|
|
STR_CUSTOM: "Personalitzat"
|
|
STR_COVER: "Portada"
|
|
STR_NONE_OPT: "Cap"
|
|
STR_FIT: "Ajustar"
|
|
STR_CROP: "Retallar"
|
|
STR_NEVER: "Mai"
|
|
STR_IN_READER: "Al lector"
|
|
STR_ALWAYS: "Sempre"
|
|
STR_IGNORE: "Ignora"
|
|
STR_SLEEP: "Dormir"
|
|
STR_PAGE_TURN: "Canvi de pàgina"
|
|
STR_PORTRAIT: "Vertical"
|
|
STR_LANDSCAPE_CW: "Horitzontal horari"
|
|
STR_INVERTED: "Invertit"
|
|
STR_LANDSCAPE_CCW: "Horitzontal antihorari"
|
|
STR_PREV_NEXT: "Anterior/Següent"
|
|
STR_NEXT_PREV: "Següent/Anterior"
|
|
STR_NOTO_SERIF: "Noto Serif"
|
|
STR_NOTO_SANS: "Noto Sans"
|
|
STR_OPEN_DYSLEXIC: "Open Dyslexic"
|
|
STR_SMALL: "Petita"
|
|
STR_MEDIUM: "Mitjana"
|
|
STR_LARGE: "Gran"
|
|
STR_X_LARGE: "Molt gran"
|
|
STR_TIGHT: "Estret"
|
|
STR_NORMAL: "Normal"
|
|
STR_WIDE: "Ample"
|
|
STR_JUSTIFY: "Justificat"
|
|
STR_ALIGN_LEFT: "Esquerra"
|
|
STR_CENTER: "Centre"
|
|
STR_ALIGN_RIGHT: "Dreta"
|
|
STR_MIN_1: "1 min"
|
|
STR_MIN_5: "5 min"
|
|
STR_MIN_10: "10 min"
|
|
STR_MIN_15: "15 min"
|
|
STR_MIN_30: "30 min"
|
|
STR_PAGES_1: "1 pàgina"
|
|
STR_PAGES_5: "5 pàgines"
|
|
STR_PAGES_10: "10 pàgines"
|
|
STR_PAGES_15: "15 pàgines"
|
|
STR_PAGES_30: "30 pàgines"
|
|
STR_UPDATE: "Actualitza"
|
|
STR_CHECKING_UPDATE: "S'està comprovant si hi ha actualitzacions..."
|
|
STR_NEW_UPDATE: "Nova actualització disponible!"
|
|
STR_CURRENT_VERSION: "Versió actual: "
|
|
STR_NEW_VERSION: "Nova versió: "
|
|
STR_UPDATING: "S'està actualitzant..."
|
|
STR_NO_UPDATE: "No hi ha actualitzacions disponibles"
|
|
STR_UPDATE_FAILED: "Ha fallat l'actualització"
|
|
STR_UPDATE_COMPLETE: "Actualització completada"
|
|
STR_POWER_ON_HINT: "Premeu i manteniu premut el botó d'encesa per tornar a engegar"
|
|
STR_NO_ENTRIES: "No s'ha trobat cap entrada"
|
|
STR_DOWNLOADING: "S'està baixant..."
|
|
STR_DOWNLOAD_FAILED: "Ha fallat la baixada"
|
|
STR_ERROR_MSG: "Error:"
|
|
STR_UNNAMED: "Sense nom"
|
|
STR_NO_SERVER_URL: "No s'ha configurat cap URL de servidor"
|
|
STR_FETCH_FEED_FAILED: "Ha fallat l'obtenció del feed"
|
|
STR_PARSE_FEED_FAILED: "Ha fallat l'anàlisi del feed"
|
|
STR_NETWORK_PREFIX: "Xarxa: "
|
|
STR_IP_ADDRESS_PREFIX: "Adreça IP: "
|
|
STR_ERROR_GENERAL_FAILURE: "Error: Fallada general"
|
|
STR_ERROR_NETWORK_NOT_FOUND: "Error: No s'ha trobat la xarxa"
|
|
STR_ERROR_CONNECTION_TIMEOUT: "Error: temps de connexió esgotat"
|
|
STR_SD_CARD: "Targeta SD"
|
|
STR_BACK: "« Enrere"
|
|
STR_EXIT: "« Surt"
|
|
STR_HOME: "« Inici"
|
|
STR_SELECT: "Selecciona"
|
|
STR_SELECTED: "Seleccionat"
|
|
STR_TOGGLE: "Canvia"
|
|
STR_CONFIRM: "Confirma"
|
|
STR_CANCEL: "Cancel·la"
|
|
STR_CONNECT: "Connecta"
|
|
STR_OPEN: "Obre"
|
|
STR_DOWNLOAD: "Descarrega"
|
|
STR_RETRY: "Nou intent"
|
|
STR_YES: "Sí"
|
|
STR_NO: "No"
|
|
STR_SHOW: "Mostrar"
|
|
STR_HIDE: "Amagar"
|
|
STR_STATE_ON: "ON"
|
|
STR_STATE_OFF: "OFF"
|
|
STR_NOT_SET: "No establert"
|
|
STR_DIR_LEFT: "Esquerra"
|
|
STR_DIR_RIGHT: "Dreta"
|
|
STR_DIR_UP: "Amunt"
|
|
STR_DIR_DOWN: "Avall"
|
|
STR_OK_BUTTON: "OK"
|
|
STR_SLEEP_COVER_FILTER: "Filtre de pantalla de repòs"
|
|
STR_FILTER_CONTRAST: "Contrast"
|
|
STR_CUSTOMISE_STATUS_BAR: "Personalitza la barra d'estat"
|
|
STR_CHAPTER_PAGE_COUNT: "Comptador de pàgines del capítol"
|
|
STR_BOOK_PROGRESS_PERCENTAGE: "Percentatge de progrés del llibre"
|
|
STR_PROGRESS_BAR: "Barra de progrés"
|
|
STR_PROGRESS_BAR_THICKNESS: "Gruix de la barra de progrés"
|
|
STR_PROGRESS_BAR_THIN: "Fina"
|
|
STR_PROGRESS_BAR_MEDIUM: "Mitjana"
|
|
STR_PROGRESS_BAR_THICK: "Gruixuda"
|
|
STR_BOOK: "Llibre"
|
|
STR_CHAPTER: "Capítol"
|
|
STR_EXAMPLE_CHAPTER: "Capítol 21"
|
|
STR_EXAMPLE_BOOK: "Títol del llibre"
|
|
STR_PREVIEW: "Vista prèvia"
|
|
STR_TITLE: "Títol"
|
|
STR_BATTERY: "Bateria"
|
|
STR_UI_THEME: "Tema de la interfície"
|
|
STR_THEME_CLASSIC: "Clàssic"
|
|
STR_THEME_LYRA: "Lyra"
|
|
STR_THEME_LYRA_EXTENDED: "Lyra Ampliat"
|
|
STR_SUNLIGHT_FADING_FIX: "Correcció de l'esvaïment pel sol"
|
|
STR_REMAP_FRONT_BUTTONS: "Reassigna els botons frontals"
|
|
STR_OPDS_BROWSER: "Navegador OPDS"
|
|
STR_COVER_CUSTOM: "Portada + Personalitzat"
|
|
STR_MENU_RECENT_BOOKS: "Llibres recents"
|
|
STR_NO_RECENT_BOOKS: "No hi ha llibres recents"
|
|
STR_CALIBRE_DESC: "Usa les transferències sense fils de Calibre"
|
|
STR_FORGET_AND_REMOVE: "Voleu suprimir la contrasenya desada?"
|
|
STR_FORGET_BUTTON: "Oblida"
|
|
STR_CALIBRE_STARTING: "S'està iniciant el Calibre..."
|
|
STR_CALIBRE_SETUP: "Configura"
|
|
STR_CALIBRE_STATUS: "Estat"
|
|
STR_CLEAR_BUTTON: "Esborra"
|
|
STR_DEFAULT_VALUE: "Per defecte"
|
|
STR_REMAP_PROMPT: "Premeu un botó frontal per a cada rol"
|
|
STR_UNASSIGNED: "No assignat"
|
|
STR_ALREADY_ASSIGNED: "Ja assignat"
|
|
STR_REMAP_RESET_HINT: "Botó lateral Amunt: Restableix la disposició per defecte"
|
|
STR_REMAP_CANCEL_HINT: "Botó lateral Avall: Cancel·la la reassignació"
|
|
STR_HW_BACK_LABEL: "Enrere (1r botó)"
|
|
STR_HW_CONFIRM_LABEL: "Confirma (2n botó)"
|
|
STR_HW_LEFT_LABEL: "Esquerra (3r botó)"
|
|
STR_HW_RIGHT_LABEL: "Dreta (4t botó)"
|
|
STR_GO_TO_PERCENT: "Ves al %"
|
|
STR_GO_HOME_BUTTON: "Ves a l'inici"
|
|
STR_SYNC_PROGRESS: "Sincronitza el progrés"
|
|
STR_DELETE_CACHE: "Esborra la memòria cau del llibre"
|
|
STR_DELETE: "Esborra"
|
|
STR_DISPLAY_QR: "Mostra la pàgina com a QR"
|
|
STR_CHAPTER_PREFIX: "Capítol: "
|
|
STR_PAGES_SEPARATOR: " pàgines | "
|
|
STR_BOOK_PREFIX: "Llibre: "
|
|
STR_CALIBRE_URL_HINT: "Per al Calibre, afegiu /opds a la URL"
|
|
STR_PERCENT_STEP_HINT: "Esquerra/Dreta: 1% Amunt/Avall: 10%"
|
|
STR_SYNCING_TIME: "S'està sincronitzant el temps..."
|
|
STR_CALC_HASH: "S'està calculant el hash del document..."
|
|
STR_HASH_FAILED: "No s'ha pogut calcular el hash del document"
|
|
STR_FETCH_PROGRESS: "S'està obtenint el progrés remot..."
|
|
STR_UPLOAD_PROGRESS: "S'està pujant el progrés..."
|
|
STR_NO_CREDENTIALS_MSG: "No s'han configurat credencials"
|
|
STR_KOREADER_SETUP_HINT: "Configureu el compte de KOReader a la configuració"
|
|
STR_PROGRESS_FOUND: "S'ha trobat progrés!"
|
|
STR_REMOTE_LABEL: "Remot:"
|
|
STR_LOCAL_LABEL: "Local:"
|
|
STR_PAGE_OVERALL_FORMAT: "Pàgina %d, %.2f%% total"
|
|
STR_PAGE_TOTAL_OVERALL_FORMAT: "Pàgina %d/%d, %.2f%% total"
|
|
STR_DEVICE_FROM_FORMAT: " De: %s"
|
|
STR_APPLY_REMOTE: "Aplica el progrés remot"
|
|
STR_UPLOAD_LOCAL: "Puja el progrés local"
|
|
STR_NO_REMOTE_MSG: "No s'ha trobat progrés remot"
|
|
STR_UPLOAD_PROMPT: "Voleu pujar la posició actual?"
|
|
STR_UPLOAD_SUCCESS: "Progrés pujat!"
|
|
STR_SYNC_FAILED_MSG: "Sincronització fallida"
|
|
STR_SAVE_PROGRESS_FAILED: "No s'ha pogut desar el progrés"
|
|
STR_SECTION_PREFIX: "Secció "
|
|
STR_UPLOAD: "Puja"
|
|
STR_BOOK_S_STYLE: "Estil del llibre"
|
|
STR_EMBEDDED_STYLE: "Estil incrustat"
|
|
STR_FOCUS_READING: "Lectura enfocada"
|
|
STR_OPDS_SERVER_URL: "URL del servidor OPDS"
|
|
STR_FOOTNOTES: "Notes al peu"
|
|
STR_NO_FOOTNOTES: "No hi ha notes al peu en aquesta pàgina"
|
|
STR_LINK: "[enllaç]"
|
|
STR_SCREENSHOT_BUTTON: "Fes una captura de pantalla"
|
|
STR_AUTO_TURN_ENABLED: "Passar automàtic activat: "
|
|
STR_AUTO_TURN_PAGES_PER_MIN: "Passar automàtic (pàgines per minut)"
|
|
STR_TILT_PAGE_TURN: "Pas de pàgina per inclinació"
|