feat(koplugin): add i18n catalog and sync info dialog (#4050)

- i18n loader at apps/readest.koplugin/i18n.lua: isolated callable,
  falls back to KOReader's gettext when a string is untranslated
- Translation catalog at locales/<i18next-code>/translation.po for 31
  languages, mirroring apps/readest-app/public/locales/
- scripts/extract-i18n.js (scan _("...") and _([[...]]); preserve
  existing, drop obsolete, add new) and scripts/apply-translations.js
  (bulk import from /tmp/koplugin-translations/<lang>.json)
- Mirror apps/readest-app SyncInfoDialog: rename showMetaHashInfo to
  showSyncInfo, dialog title "Sync Info", new Last Synced row computed
  as max(last_synced_at_config, last_synced_at_notes) from doc_settings
- syncconfig.lua / syncannotations.lua mark per-book sync timestamps
  on push/pull success
- Rename "Meta Hash" -> "Book Fingerprint" in koplugin and
  apps/readest-app SyncInfoDialog.tsx; translations propagated to
  all readest-app locales
- "book config" -> "reading progress" wording across user-facing
  strings (matches QiuYukang fork terminology)
- Replace "Log out as " / "Login failed: " concat prefixes with
  T(_("...%1..."), arg) placeholder pattern (RTL / verb-final friendly)
- pnpm lint:lua: luajit -b syntax check across koplugin .lua files;
  soft-skips when luajit is missing locally; CI installs luajit and
  runs the check unconditionally

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-05-04 11:35:36 +08:00
committed by GitHub
parent 7bb1133706
commit c59097b0ac
77 changed files with 7599 additions and 126 deletions
+11 -1
View File
@@ -5,7 +5,7 @@ local UIManager = require("ui/uimanager")
local logger = require("logger")
local sha2 = require("ffi/sha2")
local T = require("ffi/util").template
local _ = require("gettext")
local _ = require("i18n")
local SyncAnnotations = {}
@@ -179,6 +179,11 @@ function SyncAnnotations:push(ui, settings, client, interactive, full_sync)
if success then
settings.last_notes_sync_at = os.time() * 1000
G_reader_settings:saveSetting("readest_sync", settings)
if ui.doc_settings then
local doc_readest_sync = ui.doc_settings:readSetting("readest_sync") or {}
doc_readest_sync.last_synced_at_notes = os.time()
ui.doc_settings:saveSetting("readest_sync", doc_readest_sync)
end
end
end
)
@@ -339,6 +344,11 @@ function SyncAnnotations:pull(ui, settings, client, book_hash, meta_hash, dialog
settings.last_notes_sync_at = os.time() * 1000
G_reader_settings:saveSetting("readest_sync", settings)
if ui.doc_settings then
local doc_readest_sync = ui.doc_settings:readSetting("readest_sync") or {}
doc_readest_sync.last_synced_at_notes = os.time()
ui.doc_settings:saveSetting("readest_sync", doc_readest_sync)
end
if interactive then
UIManager:show(InfoMessage:new{