#!/usr/bin/env luajit --[[ tool to generate localized metadata for application stores. We currently support F-Droid(fastlane) and Flathub(appstream). usage: ./tools/update_metadata.lua ]]-- package.path = "frontend/?.lua;base/" .. package.path local _ = require("gettext") -- we can't require util here, some C libraries might not be available local function htmlEscape(text) return text:gsub("[}{\">/<'&]", { ["&"] = "&", ["<"] = "<", [">"] = ">", ['"'] = """, ["'"] = "'", ["/"] = "/", }) end local metadata = { summary = _("Ebook reader"), desc = { paragraphs = { _("KOReader is an ebook reader optimized for e-ink screens. It can open many formats and provides advanced text adjustments."), _("See below for a selection of its many features:"), }, highlights = { _("Supports both fixed page formats (PDF, DjVu, CBT, CBZ) and reflowable e-book formats (EPUB, FB2, Mobi, DOC, CHM, TXT, HTML). Scanned PDF/DjVu documents can be reflowed. Special flow directions for reading double column PDFs and manga."), _("Multi-lingual user interface optimized for e-ink screens. Highly customizable reader view with complete typesetting options. Multi-lingual hyphenation dictionaries are bundled in."), _("Non-Latin script support for books, including the Hebrew, Arabic, Persian, Russian, Chinese, Japanese and Korean languages."), _("Unique Book Map and Page Browser features to navigate your book."), _("Special multi-page highlight mode with many local and online export options."), _("Can synchronize your reading progress across all your KOReader running devices."), _("Integrated with Calibre, Wallabag, Wikipedia, Google translate and other content providers."), }, }, notes = { _ ("Release notes available on the link below"), }, screenshots = { { image = "https://github.com/koreader/koreader-artwork/raw/master/koreader-menu-framed.png", default = true, }, { image = "https://github.com/koreader/koreader-artwork/raw/master/koreader-footnotes-framed.png", }, { image = "https://github.com/koreader/koreader-artwork/raw/master/koreader-dictionary-framed.png", } }, keywords = { _("reader"), _("viewer"), _("dictionary"), _("wikipedia"), _("wallabag"), _("annotations"), -- don't translate formats "epub", "fb2", "pdf", "djvu", }, -- appstream metadata that needs no translation component = [[ rocks.koreader.KOReader KOReader KOReader Community CC0-1.0 AGPL-3.0-only https://koreader.rocks/ https://github.com/koreader/koreader/issues https://koreader.rocks/user_guide https://hosted.weblate.org/engage/koreader/ https://github.com/koreader/koreader https://github.com/koreader/koreader #ffffff #303030 360 pointing keyboard gamepad 1024 600 always touch application/epub+zip application/fb2 application/fb3 application/msword application/oxps application/pdf application/rtf application/tcr application/vnd.amazon.mobi8-ebook application/vnd.comicbook+tar application/vnd.comicbook+zip application/vnd.ms-htmlhelp application/vnd.openxmlformats-officedocument.wordprocessingml.document application/vnd.palm application/x-cbz application/x-chm application/x-fb2 application/x-fb3 application/x-mobipocket-ebook application/x-tar application/xhtml+xml application/xml application/zip image/djvu image/gif image/jp2 image/jpeg image/jxr image/png image/svg+xml image/tiff image/vnd.djvu image/vnd.ms-photo image/x-djvu image/x-portable-arbitrarymap image/x-portable-bitmap text/html text/plain rocks.koreader.KOReader.desktop Office Viewer Literature ]], } local updated_files = {} local function writeFile(str, path) local f = io.open(path, "w") table.insert(updated_files, path) if f then f:write(str) f:write("\n") f:close() end end local function isLocaleDir(str) for _, v in ipairs({"templates", "README.md", "LICENSE"}) do if str == v then return false end end return true end local function getLocales() local locales = {} local output = io.popen('ls l10n') if not output then return {} end for dir in output:lines() do if isLocaleDir(dir) then locales[#locales + 1] = dir end end output:close() table.insert(locales, 1, "en") return locales end local locales = getLocales() local function htmlDescription(lang) local lang = lang or "en" local desc = metadata.desc local t = {} _.changeLang(lang) for i, v in ipairs (desc.paragraphs) do table.insert(t, "

" .. htmlEscape(_(v)) .. "

") end table.insert(t, "") return table.concat(t, "\n") end local function tag(element, lang, str, pad) local offset = "" local pad = pad or 0 if pad >= 1 then for i = 1, pad do offset = offset .. " " end end if lang == "en" then return string.format("%s<%s>%s", offset, element, str, element) else return string.format('%s<%s xml:lang="%s">%s', offset, element, lang, str, element) end end local function genAppstream() local metadata_file = "platform/common/koreader.metainfo.xml" print("Building appstream metadata, this might take a while...") local t = {} local desc = metadata.desc table.insert(t, '') table.insert(t, '') table.insert(t, '') table.insert(t, metadata.component) local orig, translated _.changeLang("en") orig = metadata.summary for __, lang in ipairs(locales) do _.changeLang(lang) translated = _(metadata.summary) if orig ~= translated or lang == "en" then table.insert(t, tag("summary", lang, htmlEscape(translated), 2)) end end table.insert(t, ' ') for i, v in ipairs (desc.paragraphs) do _.changeLang("en") orig = v for __, lang in ipairs(locales) do _.changeLang(lang) translated = _(v) if orig ~= translated or lang == "en" then table.insert(t, tag("p", lang, htmlEscape(translated), 4)) end end end table.insert(t, '
    ') for i, v in ipairs(desc.highlights) do _.changeLang("en") orig = v for __, lang in ipairs(locales) do _.changeLang(lang) translated = _(v) if orig ~= translated or lang == "en" then table.insert(t, tag("li", lang, htmlEscape(translated), 6)) end end end table.insert(t, '
') table.insert(t, '
') table.insert(t, ' ') for i, v in ipairs(metadata.screenshots) do if v.default then table.insert(t, ' ') else table.insert(t, ' ') end table.insert(t, tag("image", "en", v.image, 6)) if v.caption then _.changeLang(en) orig = v.caption for __, lang in ipairs(locales) do _.changeLang(lang) translated = _(v.caption) if orig ~= translated or lang == "en" then table.insert(t, tag("caption", lang, htmlEscape(translated), 6)) end end end table.insert(t, ' ') end table.insert(t, ' ') table.insert(t, ' ') for i, v in ipairs(metadata.keywords) do _.changeLang(en) orig = v for __, lang in ipairs(locales) do _.changeLang(lang) translated = _(v) if orig ~= translated or lang == "en" then table.insert(t, tag("keyword", lang, htmlEscape(translated), 4)) end end end table.insert(t, ' ') table.insert(t, [[ ]]) for i, v in ipairs(metadata.notes) do _.changeLang(en) orig = v for __, lang in ipairs(locales) do _.changeLang(lang) translated = _(v) if orig ~= translated or lang == "en" then table.insert(t, tag("p", lang, htmlEscape(translated), 8)) end end end table.insert(t, [[ https://github.com/koreader/koreader/releases/tag/%%VERSION%% ]]) table.insert(t, '
') writeFile(table.concat(t, "\n"), metadata_file) end local function genFastlane() print("Building fastlane metadata") local short, full = "short_description.txt", "full_description.txt" local short_orig = metadata.summary local full_orig = htmlDescription() local short_translated, full_translated for __, lang in ipairs(locales) do _.changeLang(lang) if lang == "en" then metadata_dir = "metadata/en-US/" metadata_file = metadata_dir .. short writeFile(short_orig, metadata_file) metadata_file = metadata_dir .. full writeFile(full_orig, metadata_file) else metadata_dir = "metadata/" .. lang .. "/" short_translated = _(metadata.summary) full_translated = htmlDescription(lang) if short_orig ~= short_translated or full_orig ~= full_translated then os.execute('mkdir -p ' .. metadata_dir) end if short_orig ~= short_translated then metadata_file = metadata_dir .. short writeFile(short_translated, metadata_file) end if full_orig ~= full_translated then metadata_file = metadata_dir .. full writeFile(full_translated, metadata_file) end end end end genAppstream() genFastlane() print("All done! Updated files:") print(table.concat(updated_files, "\n"))