diff --git a/frontend/apps/cloudstorage/cloudstorage.lua b/frontend/apps/cloudstorage/cloudstorage.lua index 828a52208..149ba05af 100644 --- a/frontend/apps/cloudstorage/cloudstorage.lua +++ b/frontend/apps/cloudstorage/cloudstorage.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ButtonDialog = require("ui/widget/buttondialog") local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local ConfirmBox = require("ui/widget/confirmbox") @@ -343,7 +344,7 @@ end function CloudStorage:onMenuHold(item) if item.type == "folder_long_press" then - local title = T(_("Select this directory?\n\n%1"), item.url) + local title = T(_("Select this directory?\n\n%1"), BD.dirpath(item.url)) local onConfirm = self.onConfirm local button_dialog button_dialog = ButtonDialogTitle:new{ @@ -524,7 +525,7 @@ function CloudStorage:synchronizeSettings(item) local dropbox_sync_folder = item.sync_source_folder or "not set" local local_sync_folder = item.sync_dest_folder or "not set" syn_dialog = ButtonDialogTitle:new { - title = T(_("Dropbox folder:\n%1\nLocal folder:\n%2"), dropbox_sync_folder, local_sync_folder), + title = T(_("Dropbox folder:\n%1\nLocal folder:\n%2"), BD.dirpath(dropbox_sync_folder), BD.dirpath(local_sync_folder)), title_align = "center", buttons = { { diff --git a/frontend/apps/cloudstorage/dropbox.lua b/frontend/apps/cloudstorage/dropbox.lua index a3756984d..013b84b25 100644 --- a/frontend/apps/cloudstorage/dropbox.lua +++ b/frontend/apps/cloudstorage/dropbox.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ConfirmBox = require("ui/widget/confirmbox") local DocumentRegistry = require("document/documentregistry") local DropBoxApi = require("apps/cloudstorage/dropboxapi") @@ -26,12 +27,12 @@ function DropBox:downloadFile(item, password, path, close) local __, filename = util.splitFilePathName(path) if G_reader_settings:isTrue("show_unsupported") and not DocumentRegistry:hasProvider(filename) then UIManager:show(InfoMessage:new{ - text = T(_("File saved to:\n%1"), path), + text = T(_("File saved to:\n%1"), BD.filename(path)), }) else UIManager:show(ConfirmBox:new{ text = T(_("File saved to:\n%1\nWould you like to read the downloaded book now?"), - path), + BD.filepath(path)), ok_callback = function() close() ReaderUI:showReader(path) @@ -40,7 +41,7 @@ function DropBox:downloadFile(item, password, path, close) end else UIManager:show(InfoMessage:new{ - text = T(_("Could not save file to:\n%1"), path), + text = T(_("Could not save file to:\n%1"), BD.filepath(path)), timeout = 3, }) end diff --git a/frontend/apps/cloudstorage/ftp.lua b/frontend/apps/cloudstorage/ftp.lua index 76a356169..ca025c81a 100644 --- a/frontend/apps/cloudstorage/ftp.lua +++ b/frontend/apps/cloudstorage/ftp.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ConfirmBox = require("ui/widget/confirmbox") local DocumentRegistry = require("document/documentregistry") local FtpApi = require("apps/cloudstorage/ftpapi") @@ -30,12 +31,12 @@ function Ftp:downloadFile(item, address, user, pass, path, close) local __, filename = util.splitFilePathName(path) if G_reader_settings:isTrue("show_unsupported") and not DocumentRegistry:hasProvider(filename) then UIManager:show(InfoMessage:new{ - text = T(_("File saved to:\n%1"), path), + text = T(_("File saved to:\n%1"), BD.filepath(path)), }) else UIManager:show(ConfirmBox:new{ text = T(_("File saved to:\n%1\nWould you like to read the downloaded book now?"), - path), + BD.filepath(path)), ok_callback = function() close() ReaderUI:showReader(path) @@ -44,7 +45,7 @@ function Ftp:downloadFile(item, address, user, pass, path, close) end else UIManager:show(InfoMessage:new{ - text = T(_("Could not save file to:\n%1"), path), + text = T(_("Could not save file to:\n%1"), BD.filepath(path)), timeout = 3, }) end diff --git a/frontend/apps/cloudstorage/webdav.lua b/frontend/apps/cloudstorage/webdav.lua index 16e4a0b33..d17c3183d 100644 --- a/frontend/apps/cloudstorage/webdav.lua +++ b/frontend/apps/cloudstorage/webdav.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ConfirmBox = require("ui/widget/confirmbox") local DocumentRegistry = require("document/documentregistry") local InfoMessage = require("ui/widget/infomessage") @@ -22,12 +23,12 @@ function WebDav:downloadFile(item, address, username, password, local_path, clos local __, filename = util.splitFilePathName(local_path) if G_reader_settings:isTrue("show_unsupported") and not DocumentRegistry:hasProvider(filename) then UIManager:show(InfoMessage:new{ - text = T(_("File saved to:\n%1"), local_path), + text = T(_("File saved to:\n%1"), BD.filepath(local_path)), }) else UIManager:show(ConfirmBox:new{ text = T(_("File saved to:\n%1\nWould you like to read the downloaded book now?"), - local_path), + BD.filepath(local_path)), ok_callback = function() close() ReaderUI:showReader(local_path) @@ -36,7 +37,7 @@ function WebDav:downloadFile(item, address, username, password, local_path, clos end else UIManager:show(InfoMessage:new{ - text = T(_("Could not save file to:\n%1"), local_path), + text = T(_("Could not save file to:\n%1"), BD.filepath(local_path)), timeout = 3, }) end diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index f38919c5c..938be81b1 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -109,8 +109,7 @@ function FileManager:init() self.path_text = TextWidget:new{ face = Font:getFace("xx_smallinfofont"), - text = filemanagerutil.abbreviate(self.root_path), - para_direction_rtl = false, -- force LTR + text = BD.directory(filemanagerutil.abbreviate(self.root_path)), max_width = Screen:getWidth() - 2*Size.padding.small, truncate_left = true, } @@ -179,7 +178,7 @@ function FileManager:init() self.focused_file = nil -- use it only once function file_chooser:onPathChanged(path) -- luacheck: ignore - FileManager.instance.path_text:setText(filemanagerutil.abbreviate(path)) + FileManager.instance.path_text:setText(BD.directory(filemanagerutil.abbreviate(path))) UIManager:setDirty(FileManager.instance, function() return "ui", FileManager.instance.path_text.dimen, FileManager.instance.dithered end) @@ -223,7 +222,7 @@ function FileManager:init() enabled = DocSettings:hasSidecarFile(util.realpath(file)), callback = function() UIManager:show(ConfirmBox:new{ - text = util.template(_("Purge .sdr to reset settings for this document?\n\n%1"), self.file_dialog.title), + text = util.template(_("Purge .sdr to reset settings for this document?\n\n%1"), BD.filename(self.file_dialog.title)), ok_text = _("Purge"), ok_callback = function() filemanagerutil.purgeSettings(file) @@ -247,7 +246,7 @@ function FileManager:init() text = _("Delete"), callback = function() UIManager:show(ConfirmBox:new{ - text = _("Are you sure that you want to delete this file?\n") .. file .. ("\n") .. _("If you delete a file, it is permanently lost."), + text = _("Are you sure that you want to delete this file?\n") .. BD.filepath(file) .. ("\n") .. _("If you delete a file, it is permanently lost."), ok_text = _("Delete"), ok_callback = function() deleteFile(file) @@ -358,8 +357,15 @@ function FileManager:init() }) end + local title + if lfs.attributes(file, "mode") == "directory" then + title = BD.directory(file:match("([^/]+)$")) + else + title = BD.filename(file:match("([^/]+)$")) + end + self.file_dialog = ButtonDialogTitle:new{ - title = file:match("([^/]+)$"), + title = title, title_align = "center", buttons = buttons, } @@ -567,7 +573,7 @@ function FileManager:tapPlus() end self.file_dialog = ButtonDialogTitle:new{ - title = filemanagerutil.abbreviate(self.file_chooser.path), + title = BD.dirpath(filemanagerutil.abbreviate(self.file_chooser.path)), title_align = "center", buttons = buttons, } @@ -666,7 +672,7 @@ end function FileManager:setHome(path) path = path or self.file_chooser.path UIManager:show(ConfirmBox:new{ - text = util.template(_("Set '%1' as HOME directory?"), path), + text = util.template(_("Set '%1' as HOME directory?"), BD.dirpath(path)), ok_text = _("Set as HOME"), ok_callback = function() G_reader_settings:saveSetting("home_dir", path) @@ -679,7 +685,7 @@ function FileManager:openRandomFile(dir) local random_file = DocumentRegistry:getRandomFile(dir, false) if random_file then UIManager:show(MultiConfirmBox:new { - text = T(_("Do you want to open %1?"), util.basename(random_file)), + text = T(_("Do you want to open %1?"), BD.filename(util.basename(random_file))), choice1_text = _("Open"), choice1_callback = function() FileManager.instance:onClose() @@ -724,12 +730,12 @@ function FileManager:pasteHere(file) end if util.execute(self.cp_bin, "-r", orig, dest) == 0 then UIManager:show(InfoMessage:new { - text = T(_("Copied to: %1"), dest), + text = T(_("Copied to: %1"), BD.dirpath(dest)), timeout = 2, }) else UIManager:show(InfoMessage:new { - text = T(_("An error occurred while trying to copy %1"), orig), + text = T(_("An error occurred while trying to copy %1"), BD.filepath(orig)), timeout = 2, }) end @@ -750,12 +756,12 @@ function FileManager:pasteHere(file) G_reader_settings:saveSetting("lastfile", dest_file) end UIManager:show(InfoMessage:new { - text = T(_("Moved to: %1"), dest), + text = T(_("Moved to: %1"), BD.dirpath(dest)), timeout = 2, }) else UIManager:show(InfoMessage:new { - text = T(_("An error occurred while trying to move %1"), orig), + text = T(_("An error occurred while trying to move %1"), BD.filepath(orig)), timeout = 2, }) end @@ -772,9 +778,9 @@ function FileManager:pasteHere(file) if mode == "file" or mode == "directory" then local text if mode == "file" then - text = T(_("The file %1 already exists. Do you want to overwrite it?"), basename) + text = T(_("The file %1 already exists. Do you want to overwrite it?"), BD.filename(basename)) else - text = T(_("The directory %1 already exists. Do you want to overwrite it?"), basename) + text = T(_("The directory %1 already exists. Do you want to overwrite it?"), BD.directory(basename)) end UIManager:show(ConfirmBox:new { @@ -800,7 +806,7 @@ function FileManager:createFolder(curr_folder, new_folder) local text if code == 0 then self:onRefresh() - text = T(_("Folder created:\n%1"), new_folder) + text = T(_("Folder created:\n%1"), BD.directory(new_folder)) else text = _("The folder has not been created.") end @@ -815,7 +821,7 @@ function FileManager:deleteFile(file) local file_abs_path = util.realpath(file) if file_abs_path == nil then UIManager:show(InfoMessage:new{ - text = util.template(_("File %1 not found"), file), + text = util.template(_("File %1 not found"), BD.filepath(file)), }) return end @@ -839,12 +845,12 @@ function FileManager:deleteFile(file) end ReadCollection:removeItemByPath(file, is_dir) UIManager:show(InfoMessage:new{ - text = util.template(_("Deleted %1"), file), + text = util.template(_("Deleted %1"), BD.filepath(file)), timeout = 2, }) else UIManager:show(InfoMessage:new{ - text = util.template(_("An error occurred while trying to delete %1"), file), + text = util.template(_("An error occurred while trying to delete %1"), BD.filepath(file)), }) end end @@ -867,21 +873,21 @@ function FileManager:renameFile(file) end if move_history then UIManager:show(InfoMessage:new{ - text = util.template(_("Renamed from %1 to %2"), file, dest), + text = util.template(_("Renamed from %1 to %2"), BD.filepath(file), BD.filepath(dest)), timeout = 2, }) else UIManager:show(InfoMessage:new{ text = util.template( _("Failed to move history data of %1 to %2.\nThe reading history may be lost."), - file, dest), + BD.filepath(file), BD.filepath(dest)), }) end end else UIManager:show(InfoMessage:new{ text = util.template( - _("Failed to rename from %1 to %2"), file, dest), + _("Failed to rename from %1 to %2"), BD.filepath(file), BD.filepath(dest)), }) end end diff --git a/frontend/apps/filemanager/filemanagerbookinfo.lua b/frontend/apps/filemanager/filemanagerbookinfo.lua index a7944f2b7..2748e9a82 100644 --- a/frontend/apps/filemanager/filemanagerbookinfo.lua +++ b/frontend/apps/filemanager/filemanagerbookinfo.lua @@ -2,6 +2,7 @@ This module provides a way to display book information (filename and book metadata) ]] +local BD = require("ui/bidi") local DocSettings = require("docsettings") local DocumentRegistry = require("document/documentregistry") local ImageViewer = require("ui/widget/imageviewer") @@ -46,10 +47,10 @@ function BookInfo:show(file, book_props) local size_f = util.getFriendlySize(file_size) local size_b = util.getFormattedSize(file_size) local size = string.format("%s (%s bytes)", size_f, size_b) - table.insert(kv_pairs, { _("Filename:"), filename }) + table.insert(kv_pairs, { _("Filename:"), BD.filename(filename) }) table.insert(kv_pairs, { _("Format:"), filetype:upper() }) table.insert(kv_pairs, { _("Size:"), size }) - table.insert(kv_pairs, { _("Directory:"), filemanagerutil.abbreviate(directory) }) + table.insert(kv_pairs, { _("Directory:"), BD.dirpath(filemanagerutil.abbreviate(directory)) }) table.insert(kv_pairs, "----") -- book_props may be provided if caller already has them available @@ -123,10 +124,20 @@ function BookInfo:show(file, book_props) local title = book_props.title if title == "" or title == nil then title = _("N/A") end - table.insert(kv_pairs, { _("Title:"), title }) + table.insert(kv_pairs, { _("Title:"), BD.auto(title) }) local authors = book_props.authors - if authors == "" or authors == nil then authors = _("N/A") end + if authors == "" or authors == nil then + authors = _("N/A") + elseif authors:find("\n") then -- BD auto isolate each author + authors = util.splitToArray(authors, "\n") + for i=1, #authors do + authors[i] = BD.auto(authors[i]) + end + authors = table.concat(authors, "\n") + else + authors = BD.auto(authors) + end table.insert(kv_pairs, { _("Authors:"), authors }) local series = book_props.series @@ -135,7 +146,7 @@ function BookInfo:show(file, book_props) else -- Shorten calibre series decimal number (#4.0 => #4) series = series:gsub("(#%d+)%.0$", "%1") end - table.insert(kv_pairs, { _("Series:"), series }) + table.insert(kv_pairs, { _("Series:"), BD.auto(series) }) local pages = book_props.pages if pages == "" or pages == nil then pages = _("N/A") end @@ -146,7 +157,17 @@ function BookInfo:show(file, book_props) table.insert(kv_pairs, { _("Language:"), language }) local keywords = book_props.keywords - if keywords == "" or keywords == nil then keywords = _("N/A") end + if keywords == "" or keywords == nil then + keywords = _("N/A") + elseif keywords:find("\n") then -- BD auto isolate each keywords + keywords = util.splitToArray(keywords, "\n") + for i=1, #keywords do + keywords[i] = BD.auto(keywords[i]) + end + keywords = table.concat(keywords, "\n") + else + keywords = BD.auto(keywords) + end table.insert(kv_pairs, { _("Keywords:"), keywords }) local description = book_props.description @@ -157,6 +178,9 @@ function BookInfo:show(file, book_props) -- in PDF) be HTML. description = util.htmlToPlainTextIfHtml(book_props.description) end + -- (We don't BD wrap description: it may be multi-lines, and the value we set + -- here may be viewed in a TextViewer that has auto_para_direction=true, which + -- will show the right thing, that'd we rather not mess with BD wrapping.) table.insert(kv_pairs, { _("Description:"), description }) -- Cover image diff --git a/frontend/apps/filemanager/filemanagerhistory.lua b/frontend/apps/filemanager/filemanagerhistory.lua index 86eeb65ab..e60147c29 100644 --- a/frontend/apps/filemanager/filemanagerhistory.lua +++ b/frontend/apps/filemanager/filemanagerhistory.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local DocSettings = require("docsettings") local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") @@ -53,7 +54,7 @@ function FileManagerHistory:onMenuHold(item) callback = function() local ConfirmBox = require("ui/widget/confirmbox") UIManager:show(ConfirmBox:new{ - text = util.template(_("Purge .sdr to reset settings for this document?\n\n%1"), item.text), + text = util.template(_("Purge .sdr to reset settings for this document?\n\n%1"), BD.filename(item.text)), ok_text = _("Purge"), ok_callback = function() filemanagerutil.purgeSettings(item.file) @@ -80,7 +81,7 @@ function FileManagerHistory:onMenuHold(item) callback = function() local ConfirmBox = require("ui/widget/confirmbox") UIManager:show(ConfirmBox:new{ - text = _("Are you sure that you want to delete this file?\n") .. item.file .. ("\n") .. _("If you delete a file, it is permanently lost."), + text = _("Are you sure that you want to delete this file?\n") .. BD.filepath(item.file) .. ("\n") .. _("If you delete a file, it is permanently lost."), ok_text = _("Delete"), ok_callback = function() local FileManager = require("apps/filemanager/filemanager") @@ -116,7 +117,7 @@ function FileManagerHistory:onMenuHold(item) }, } self.histfile_dialog = ButtonDialogTitle:new{ - title = item.text:match("([^/]+)$"), + title = BD.filename(item.text:match("([^/]+)$")), title_align = "center", buttons = buttons, } diff --git a/frontend/apps/filemanager/filemanagermenu.lua b/frontend/apps/filemanager/filemanagermenu.lua index 8f362f2e5..ba623df78 100644 --- a/frontend/apps/filemanager/filemanagermenu.lua +++ b/frontend/apps/filemanager/filemanagermenu.lua @@ -469,7 +469,7 @@ function FileManagerMenu:setUpdateItemTable() end local last_file = G_reader_settings:readSetting("lastfile") local path, file_name = util.splitFilePathName(last_file); -- luacheck: no unused - return T(_("Last: %1"), file_name) + return T(_("Last: %1"), BD.filename(file_name)) end, enabled_func = function() return G_reader_settings:readSetting("lastfile") ~= nil @@ -480,7 +480,7 @@ function FileManagerMenu:setUpdateItemTable() hold_callback = function() local last_file = G_reader_settings:readSetting("lastfile") UIManager:show(ConfirmBox:new{ - text = T(_("Would you like to open the last document: %1?"), last_file), + text = T(_("Would you like to open the last document: %1?"), BD.filepath(last_file)), ok_text = _("OK"), ok_callback = function() self:openLastDoc() diff --git a/frontend/apps/filemanager/filemanagershortcuts.lua b/frontend/apps/filemanager/filemanagershortcuts.lua index 7e63a1ca7..c55ff57d6 100644 --- a/frontend/apps/filemanager/filemanagershortcuts.lua +++ b/frontend/apps/filemanager/filemanagershortcuts.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ButtonDialog = require("ui/widget/buttondialog") local InfoMessage = require("ui/widget/infomessage") local InputContainer = require("ui/widget/container/inputcontainer") @@ -73,7 +74,7 @@ function FileManagerShortcuts:addNewFolder() title = self.title, input = friendly_name, input_type = "text", - description = T(_("Title for selected folder:\n%1"), path), + description = T(_("Title for selected folder:\n%1"), BD.dirpath(path)), buttons = { { { @@ -162,7 +163,7 @@ function FileManagerShortcuts:editFolderShortcut(item) title = _("Edit friendly name"), input = item.friendly_name, input_type = "text", - description = T(_("Rename title for selected folder:\n%1"), item.folder), + description = T(_("Rename title for selected folder:\n%1"), BD.dirpath(item.folder)), buttons = { { { diff --git a/frontend/apps/opdscatalog/opdscatalog.lua b/frontend/apps/opdscatalog/opdscatalog.lua index 13b22651e..db8f2b9fc 100644 --- a/frontend/apps/opdscatalog/opdscatalog.lua +++ b/frontend/apps/opdscatalog/opdscatalog.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local ConfirmBox = require("ui/widget/confirmbox") local FrameContainer = require("ui/widget/container/framecontainer") @@ -26,7 +27,7 @@ function OPDSCatalog:init() file_downloaded_callback = function(downloaded_file) UIManager:show(ConfirmBox:new{ text = T(_("File saved to:\n%1\nWould you like to read the downloaded book now?"), - downloaded_file), + BD.filepath(downloaded_file)), ok_text = _("Read now"), cancel_text = _("Read later"), ok_callback = function() diff --git a/frontend/apps/reader/modules/readerdictionary.lua b/frontend/apps/reader/modules/readerdictionary.lua index 3406f60ec..e5bb38cd3 100644 --- a/frontend/apps/reader/modules/readerdictionary.lua +++ b/frontend/apps/reader/modules/readerdictionary.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ConfirmBox = require("ui/widget/confirmbox") local DataStorage = require("datastorage") local Device = require("device") @@ -233,7 +234,7 @@ function ReaderDictionary:addToMainMenu(menu_items) text = T(_([[ If you'd like to change the order in which dictionaries are queried (and their results displayed), you can: - move all dictionary directories out of %1. -- move them back there, one by one, in the order you want them to be used.]]), self.data_dir) +- move them back there, one by one, in the order you want them to be used.]]), BD.dirpath(self.data_dir)) }) end, }, @@ -928,7 +929,7 @@ function ReaderDictionary:downloadDictionary(dict, download_location, continue) logger.dbg("file downloaded to", download_location) else UIManager:show(InfoMessage:new{ - text = _("Could not save file to:\n") .. download_location, + text = _("Could not save file to:\n") .. BD.filepath(download_location), --timeout = 3, }) return false diff --git a/frontend/apps/reader/modules/readerfont.lua b/frontend/apps/reader/modules/readerfont.lua index fef150b48..66a4efc5f 100644 --- a/frontend/apps/reader/modules/readerfont.lua +++ b/frontend/apps/reader/modules/readerfont.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local CenterContainer = require("ui/widget/container/centercontainer") local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") @@ -397,7 +398,7 @@ a { color: black; } f:write("\n") f:close() UIManager:show(ConfirmBox:new{ - text = T(_("Document created as:\n%1\n\nWould you like to read it now?"), fonts_test_path), + text = T(_("Document created as:\n%1\n\nWould you like to read it now?"), BD.filepath(fonts_test_path)), ok_callback = function() UIManager:scheduleIn(1.0, function() self.ui:switchDocument(fonts_test_path) diff --git a/frontend/apps/reader/modules/readergesture.lua b/frontend/apps/reader/modules/readergesture.lua index 2cccf378d..28705395b 100644 --- a/frontend/apps/reader/modules/readergesture.lua +++ b/frontend/apps/reader/modules/readergesture.lua @@ -1490,7 +1490,7 @@ function ReaderGesture:gestureAction(action, ges) local current_network = NetworkMgr:getCurrentNetwork() -- this method is only available for some implementations if current_network and current_network.ssid then - info_text = T(_("Already connected to network %1."), current_network.ssid) + info_text = T(_("Already connected to network %1."), BD.wrap(current_network.ssid)) else info_text = _("Already connected.") end diff --git a/frontend/apps/reader/modules/readerhighlight.lua b/frontend/apps/reader/modules/readerhighlight.lua index a12946a77..6b4efa2e3 100644 --- a/frontend/apps/reader/modules/readerhighlight.lua +++ b/frontend/apps/reader/modules/readerhighlight.lua @@ -791,7 +791,7 @@ function ReaderHighlight:viewSelectionHTML(debug_view) if css_files then for i=1, #css_files do local button = { - text = T(_("View %1"), css_files[i]), + text = T(_("View %1"), BD.filepath(css_files[i])), callback = function() local css_text = self.ui.document:getDocumentFileContent(css_files[i]) local cssviewer diff --git a/frontend/apps/reader/modules/readerhyphenation.lua b/frontend/apps/reader/modules/readerhyphenation.lua index 199912905..34caaad68 100644 --- a/frontend/apps/reader/modules/readerhyphenation.lua +++ b/frontend/apps/reader/modules/readerhyphenation.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Device = require("device") local Event = require("ui/event") local InfoMessage = require("ui/widget/infomessage") @@ -25,13 +26,16 @@ function ReaderHyphenation:init() table.insert(self.hyph_table, { text_func = function() - local limits_text = _("language defaults") - if G_reader_settings:readSetting("hyph_left_hyphen_min") - or G_reader_settings:readSetting("hyph_right_hyphen_min") then - limits_text = T("%1 - %2", G_reader_settings:readSetting("hyph_left_hyphen_min"), + -- Note: with our callback, we either get hyph_left_hyphen_min and + -- hyph_right_hyphen_min both nil, or both defined. + if G_reader_settings:readSetting("hyph_left_hyphen_min") or + G_reader_settings:readSetting("hyph_right_hyphen_min") then + -- @translators to RTL language translators: %1/left is the min length of the start of a hyphenated word, %2/right is the min length of the end of a hyphenated word (note that there is yet no support for hyphenation with RTL languages, so this will mostly apply to LTR documents) + return T(_("Left/right minimal sizes: %1 - %2"), + G_reader_settings:readSetting("hyph_left_hyphen_min"), G_reader_settings:readSetting("hyph_right_hyphen_min")) end - return T(_("Left/right minimal sizes: %1"), limits_text) + return _("Left/right minimal sizes: language defaults") end, callback = function() local DoubleSpinWidget = require("/ui/widget/doublespinwidget") @@ -120,7 +124,7 @@ These settings will apply to all books with any hyphenation dictionary. self.hyph_alg = v.filename self.ui.doc_settings:saveSetting("hyph_alg", self.hyph_alg) UIManager:show(InfoMessage:new{ - text = T(_("Changed hyphenation to %1."), v.name), + text = T(_("Changed hyphenation to %1."), BD.wrap(v.name)), }) self.ui.document:setHyphDictionary(v.filename) -- Apply hyphenation sides limits @@ -137,7 +141,7 @@ These settings will apply to all books with any hyphenation dictionary. -- one is set, no fallback will ever be used - if a fallback one -- is set, no default is wanted; so when we set one below, we -- remove the other). - text = T( _("Would you like %1 to be used as the default (★) or fallback (�) hyphenation language?\n\nDefault will always take precedence while fallback will only be used if the language of the book can't be automatically determined."), v.name), + text = T( _("Would you like %1 to be used as the default (★) or fallback (�) hyphenation language?\n\nDefault will always take precedence while fallback will only be used if the language of the book can't be automatically determined."), BD.wrap(v.name)), choice1_text = _("Default"), choice1_callback = function() G_reader_settings:saveSetting("hyph_alg_default", v.filename) diff --git a/frontend/apps/reader/modules/readerlink.lua b/frontend/apps/reader/modules/readerlink.lua index 27145c27d..fb49de393 100644 --- a/frontend/apps/reader/modules/readerlink.lua +++ b/frontend/apps/reader/modules/readerlink.lua @@ -534,7 +534,7 @@ function ReaderLink:onGotoLink(link, neglect_current_location, allow_footnote_po display_filename = display_filename .. anchor end UIManager:show(ConfirmBox:new{ - text = T(_("Would you like to read this local document?\n\n%1\n"), display_filename), + text = T(_("Would you like to read this local document?\n\n%1\n"), BD.filepath(display_filename)), ok_callback = function() UIManager:scheduleIn(0.1, function() self.ui:switchDocument(linked_filename) @@ -543,7 +543,7 @@ function ReaderLink:onGotoLink(link, neglect_current_location, allow_footnote_po }) else UIManager:show(InfoMessage:new{ - text = T(_("Link to unsupported local file:\n%1"), link_url), + text = T(_("Link to unsupported local file:\n%1"), BD.url(link_url)), }) end return true @@ -551,7 +551,7 @@ function ReaderLink:onGotoLink(link, neglect_current_location, allow_footnote_po -- Not supported UIManager:show(InfoMessage:new{ - text = T(_("Invalid or external link:\n%1"), link_url), + text = T(_("Invalid or external link:\n%1"), BD.url(link_url)), -- no timeout to allow user to type that link in his web browser }) -- don't propagate, user will notice and tap elsewhere if he wants to change page @@ -658,7 +658,7 @@ function ReaderLink:onGoToExternalLink(link_url) -- No external link handler return false end - text = T(_("External link:\n\n%1"), link_url) + text = T(_("External link:\n\n%1"), BD.url(link_url)) end -- Add all alternative handlers buttons diff --git a/frontend/apps/reader/modules/readermenu.lua b/frontend/apps/reader/modules/readermenu.lua index 697c37dac..356a3ba8d 100644 --- a/frontend/apps/reader/modules/readermenu.lua +++ b/frontend/apps/reader/modules/readermenu.lua @@ -228,7 +228,7 @@ function ReaderMenu:setUpdateItemTable() return _("Open previous document") end local path, file_name = util.splitFilePathName(previous_file) -- luacheck: no unused - return T(_("Previous: %1"), file_name) + return T(_("Previous: %1"), BD.filename(file_name)) end, enabled_func = function() return self:getPreviousFile() ~= nil @@ -239,7 +239,7 @@ function ReaderMenu:setUpdateItemTable() hold_callback = function() local previous_file = self:getPreviousFile() UIManager:show(ConfirmBox:new{ - text = T(_("Would you like to open the previous document: %1?"), previous_file), + text = T(_("Would you like to open the previous document: %1?"), BD.filepath(previous_file)), ok_text = _("OK"), ok_callback = function() self.ui:switchDocument(previous_file) diff --git a/frontend/apps/reader/modules/readerstatus.lua b/frontend/apps/reader/modules/readerstatus.lua index c5ced29f4..42e36249d 100644 --- a/frontend/apps/reader/modules/readerstatus.lua +++ b/frontend/apps/reader/modules/readerstatus.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local BookStatusWidget = require("ui/widget/bookstatuswidget") local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local Device = require("device") @@ -181,7 +182,7 @@ function ReaderStatus:deleteFile(file, text_end_book) message_end_book = "You've reached the end of the document.\n" end UIManager:show(ConfirmBox:new{ - text = T(_("%1Are you sure that you want to delete this file?\n%2\nIf you delete a file, it is permanently lost."), message_end_book, file), + text = T(_("%1Are you sure that you want to delete this file?\n%2\nIf you delete a file, it is permanently lost."), message_end_book, BD.filepath(file)), ok_text = _("Delete"), ok_callback = function() local FileManager = require("apps/filemanager/filemanager") diff --git a/frontend/apps/reader/modules/readerstyletweak.lua b/frontend/apps/reader/modules/readerstyletweak.lua index e9eb9fae2..da3c2cd21 100644 --- a/frontend/apps/reader/modules/readerstyletweak.lua +++ b/frontend/apps/reader/modules/readerstyletweak.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local ButtonTable = require("ui/widget/buttontable") local CenterContainer = require("ui/widget/container/centercontainer") @@ -498,7 +499,7 @@ You can enable individual tweaks on this book with a tap, or view more details a table.insert(item_table, { title = title, id = file, -- keep ".css" in id, to distinguish between koreader/user tweaks - description = T(_("User style tweak at %1"), filepath), + description = T(_("User style tweak at %1"), BD.filepath(filepath)), priority = 10, -- give user tweaks a higher priority css_path = filepath, }) diff --git a/frontend/apps/reader/modules/readertypeset.lua b/frontend/apps/reader/modules/readertypeset.lua index 3b9b961b8..0ab5fed18 100644 --- a/frontend/apps/reader/modules/readertypeset.lua +++ b/frontend/apps/reader/modules/readertypeset.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ConfirmBox = require("ui/widget/confirmbox") local Event = require("ui/event") local InfoMessage = require("ui/widget/infomessage") @@ -252,7 +253,7 @@ function ReaderTypeset:genStyleSheetMenu() text_func = function() local text = _("Obsolete") if obsoleted_css[self.css] then - text = T(_("Obsolete (%1)"), obsoleted_css[self.css]) + text = T(_("Obsolete (%1)"), BD.filename(obsoleted_css[self.css])) end if obsoleted_css[G_reader_settings:readSetting("copt_css")] then text = text .. " ★" @@ -450,7 +451,7 @@ end function ReaderTypeset:makeDefaultStyleSheet(css, text, touchmenu_instance) UIManager:show(ConfirmBox:new{ - text = T( _("Set default style to %1?"), text), + text = T( _("Set default style to %1?"), BD.filename(text)), ok_callback = function() G_reader_settings:saveSetting("copt_css", css) if touchmenu_instance then touchmenu_instance:updateItems() end diff --git a/frontend/apps/reader/modules/readerwikipedia.lua b/frontend/apps/reader/modules/readerwikipedia.lua index 889a606ac..1e9265e59 100644 --- a/frontend/apps/reader/modules/readerwikipedia.lua +++ b/frontend/apps/reader/modules/readerwikipedia.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local ConfirmBox = require("ui/widget/confirmbox") local DataStorage = require("datastorage") @@ -175,7 +176,7 @@ function ReaderWikipedia:addToMainMenu(menu_items) if not default_dir then default_dir = require("apps/filemanager/filemanagerutil").getDefaultDir() end local dialog dialog = ButtonDialogTitle:new{ - title = T(_("Current Wikipedia 'Save as EPUB' directory:\n\n%1\n"), default_dir), + title = T(_("Current Wikipedia 'Save as EPUB' directory:\n\n%1\n"), BD.dirpath(default_dir)), buttons = { { { @@ -220,7 +221,7 @@ function ReaderWikipedia:addToMainMenu(menu_items) onConfirm = function(path) G_reader_settings:saveSetting("wikipedia_save_dir", path) UIManager:show(InfoMessage:new{ - text = T(_("Wikipedia 'Save as EPUB' directory set to:\n%1"), path), + text = T(_("Wikipedia 'Save as EPUB' directory set to:\n%1"), BD.dirpath(path)), }) end } @@ -257,7 +258,7 @@ Where do you want them saved?]]) end G_reader_settings:saveSetting("wikipedia_save_dir", wikipedia_dir) UIManager:show(InfoMessage:new{ - text = T(_("Wikipedia 'Save as EPUB' directory set to:\n%1"), wikipedia_dir), + text = T(_("Wikipedia 'Save as EPUB' directory set to:\n%1"), BD.dirpath(wikipedia_dir)), }) end, cancel_text = _("Select directory"), diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index 5f947cf67..94d6c7dec 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -4,6 +4,7 @@ ReaderUI is an abstraction for a reader interface. It works using data gathered from a document interface. ]]-- +local BD = require("ui/bidi") local Cache = require("cache") local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") @@ -448,14 +449,14 @@ function ReaderUI:showReader(file, provider) if lfs.attributes(file, "mode") ~= "file" then UIManager:show(InfoMessage:new{ - text = T(_("File '%1' does not exist."), file) + text = T(_("File '%1' does not exist."), BD.filepath(file)) }) return end if not DocumentRegistry:hasProvider(file) and provider == nil then UIManager:show(InfoMessage:new{ - text = T(_("File '%1' is not supported."), file) + text = T(_("File '%1' is not supported."), BD.filepath(file)) }) self:showFileManager(file) return @@ -471,7 +472,7 @@ function ReaderUI:showReader(file, provider) (provider.provider == "mupdf" and type(bookmarks[1].page) == "string")) then UIManager:show(ConfirmBox:new{ text = T(_("The document '%1' with bookmarks or highlights was previously opened with a different engine. To prevent issues, bookmarks need to be deleted before continuing."), - file), + BD.filepath(file)), ok_text = _("Delete"), ok_callback = function() doc_settings:delSetting("bookmarks") @@ -488,7 +489,7 @@ end function ReaderUI:showReaderCoroutine(file, provider) UIManager:show(InfoMessage:new{ - text = T(_("Opening file '%1'."), file), + text = T(_("Opening file '%1'."), BD.filepath(file)), timeout = 0.0, }) -- doShowReader might block for a long time, so force repaint here diff --git a/frontend/device/android/device.lua b/frontend/device/android/device.lua index aa0af7aaa..5cd2290c6 100644 --- a/frontend/device/android/device.lua +++ b/frontend/device/android/device.lua @@ -142,9 +142,10 @@ function Device:init() -- we cannot blit to a window here since we have no focus yet. local UIManager = require("ui/uimanager") local InfoMessage = require("ui/widget/infomessage") + local BD = require("ui/bidi") UIManager:scheduleIn(0.1, function() UIManager:show(InfoMessage:new{ - text = T(_("Opening file '%1'."), new_file), + text = T(_("Opening file '%1'."), BD.filepath(new_file)), timeout = 0.0, }) end) @@ -255,7 +256,8 @@ function Device:retrieveNetworkInfo() if ip == "0" or gw == "0" then return _("Not connected") else - return T(_("Connected to %1\n IP address: %2\n gateway: %3"), ssid, ip, gw) + local BD = require("ui/bidi") + return T(_("Connected to %1\n IP address: %2\n gateway: %3"), BD.wrap(ssid), BD.ltr(ip), BD.ltr(gw)) end end diff --git a/frontend/ui/bidi.lua b/frontend/ui/bidi.lua index c8551057c..63b67eb93 100644 --- a/frontend/ui/bidi.lua +++ b/frontend/ui/bidi.lua @@ -84,31 +84,35 @@ function Bidi.setup(lang) Bidi.default = Bidi.rtl Bidi.wrap = Bidi.rtl Bidi.filename = Bidi._filename_rtl - Bidi.filepath = Bidi.ltr -- see if we need to split and _filename_rtl() the filename part - Bidi.directory = Bidi.ltr - Bidi.dirpath = Bidi.ltr - Bidi.path = Bidi.ltr - Bidi.url = Bidi.ltr + Bidi.filepath = Bidi._filepath_rtl -- filename auto, but with extension on the right + Bidi.directory = Bidi._path -- will keep any trailing / on the right + Bidi.dirpath = Bidi._path + Bidi.path = Bidi._path + Bidi.url = Bidi._path else Bidi.default = Bidi.ltr Bidi.wrap = Bidi.nowrap - Bidi.filename = Bidi.nowrap - Bidi.filepath = Bidi.nowrap - Bidi.directory = Bidi.nowrap - Bidi.dirpath = Bidi.nowrap - Bidi.path = Bidi.nowrap - Bidi.url = Bidi.nowrap + Bidi.filename = Bidi._filename_ltr + Bidi.filepath = Bidi._filepath_ltr + Bidi.directory = Bidi._path -- will keep any trailing / on the right + Bidi.dirpath = Bidi._path + Bidi.path = Bidi._path + Bidi.url = Bidi._path end -- If RTL UI text, let's have untranslated strings (so english) still rendered LTR if Bidi._rtl_ui_text then _.wrapUntranslated = function(text) -- We need to split by line and wrap each line as LTR (as the -- paragraph direction will still be RTL). - local lines = {} - for s in text:gmatch("[^\r\n]+") do - table.insert(lines, Bidi.ltr(s)) + local parts = {} + for part in util.gsplit(text, "\n", true, true) do + if part == "\n" then + table.insert(parts, "\n") + elseif part ~= "" then + table.insert(parts, Bidi.ltr(part)) + end end - return table.concat(lines, "\n") + return table.concat(parts) end else _.wrapUntranslated = _.wrapUntranslated_nowrap @@ -171,6 +175,10 @@ local RLI = "\xE2\x81\xA7" -- U+2067 RLI / RIGHT-TO-LEFT ISOLATE local FSI = "\xE2\x81\xA8" -- U+2068 FSI / FIRST STRONG ISOLATE local PDI = "\xE2\x81\xA9" -- U+2069 PDI / POP DIRECTIONAL ISOLATE +-- Not currently needed: +-- local LRM = "\xE2\x80\x8E" -- U+200E LRM / LEFT-TO-RIGHT MARK +-- local RLM = "\xE2\x80\x8F" -- U+200F RLM / RIGHT-TO-LEFT MARK + function Bidi.ltr(text) return string.format("%s%s%s", LRI, text, PDI) end @@ -205,12 +213,29 @@ end -- shown as real RTL). -- Note: when the filename or path are standalone in a TextWidget, it's -- better to use "para_direction_rtl = false" without any wrapping. -Bidi.filename = Bidi.nowrap -- aliased to Bidi._filename_rtl if _rtl_ui_text -Bidi.filepath = Bidi.nowrap -- aliased to Bidi.ltr if _rtl_ui_text -Bidi.directory = Bidi.nowrap -- aliased to Bidi.ltr if _rtl_ui_text -Bidi.dirpath = Bidi.nowrap -- aliased to Bidi.ltr if _rtl_ui_text -Bidi.path = Bidi.nowrap -- aliased to Bidi.ltr if _rtl_ui_text -Bidi.url = Bidi.nowrap -- aliased to Bidi.ltr if _rtl_ui_text +-- These are replaced above and aliased to the right wrapper depending +-- on Bidi._rtl_ui_text +Bidi.filename = Bidi.nowrap +Bidi.filepath = Bidi.nowrap +Bidi.directory = Bidi.nowrap +Bidi.dirpath = Bidi.nowrap +Bidi.path = Bidi.nowrap +Bidi.url = Bidi.nowrap + +function Bidi._filename_ltr(filename) + -- We always want to show the extension on the left, + -- but the text before should be auto. + local name, suffix = util.splitFileNameSuffix(filename) + -- Let the first strong character of the filename decides + -- about the direction + if suffix == "" then + return Bidi.auto(name) + end + return Bidi.auto(name) .. "." .. suffix + -- No need to additionally wrap it in ltr(), as the + -- default text direction must be LTR. + -- return Bidi.ltr(Bidi.auto(name) .. "." .. suffix) +end function Bidi._filename_rtl(filename) -- We always want to show the extension either on the left @@ -219,7 +244,43 @@ function Bidi._filename_rtl(filename) local name, suffix = util.splitFileNameSuffix(filename) -- Let the first strong character of the filename decides -- about the direction + if suffix == "" then + return Bidi.auto(name) + end return Bidi.auto(name .. "." .. Bidi.ltr(suffix)) end +function Bidi._filename_auto_ext_right(filename) + -- Auto/First strong char for name part, but extension still + -- on the right + local name, suffix = util.splitFileNameSuffix(filename) + if suffix == "" then + return Bidi.auto(name) + end + return Bidi.ltr(Bidi.auto(name) .. "." .. suffix) +end + +function Bidi._path(path) + -- by wrapping each component in path in FSI (first strong char) + local parts = {} + for part in util.gsplit(path, "/", true, true) do + if part == "/" then + table.insert(parts, "/") + elseif part ~= "" then + table.insert(parts, Bidi.auto(part)) + end + end + return Bidi.ltr(table.concat(parts)) +end + +function Bidi._filepath_ltr(path) + local dirpath, filename = util.splitFilePathName(path) + return Bidi.ltr(Bidi._path(dirpath) .. filename) +end + +function Bidi._filepath_rtl(path) + local dirpath, filename = util.splitFilePathName(path) + return Bidi.ltr(Bidi._path(dirpath) .. Bidi._filename_auto_ext_right(filename)) +end + return Bidi diff --git a/frontend/ui/data/koptoptions.lua b/frontend/ui/data/koptoptions.lua index 73d2a1bef..915d024c5 100644 --- a/frontend/ui/data/koptoptions.lua +++ b/frontend/ui/data/koptoptions.lua @@ -334,7 +334,7 @@ if BD.mirroredUILayout() then -- be mirrored - but that's not enough: we need to swap LEFT and RIGHT, -- so they appear in a more expected and balanced order to RTL users: -- {JUSTIFY, LEFT, CENTER, RIGHT, AUTO} - local j = KoptOptions[3].options[6] + local j = KoptOptions[3].options[7] assert(j.name == "justification") j.item_icons[2], j.item_icons[4] = j.item_icons[4], j.item_icons[2] j.values[2], j.values[4] = j.values[4], j.values[2] diff --git a/frontend/ui/elements/common_info_menu_table.lua b/frontend/ui/elements/common_info_menu_table.lua index a7d4b68e5..f1039a650 100644 --- a/frontend/ui/elements/common_info_menu_table.lua +++ b/frontend/ui/elements/common_info_menu_table.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") local InfoMessage = require("ui/widget/infomessage") @@ -44,7 +45,7 @@ common_info.about = { keep_menu_open = true, callback = function() UIManager:show(InfoMessage:new{ - text = T(_("KOReader %1\n\nA document viewer for E Ink devices.\n\nLicensed under Affero GPL v3. All dependencies are free software.\n\nhttp://koreader.rocks/"), version), + text = T(_("KOReader %1\n\nA document viewer for E Ink devices.\n\nLicensed under Affero GPL v3. All dependencies are free software.\n\nhttp://koreader.rocks/"), BD.ltr(version)), icon_file = "resources/ko-icon.png", alpha = true, }) diff --git a/frontend/ui/network/manager.lua b/frontend/ui/network/manager.lua index c4306c640..6abd95372 100644 --- a/frontend/ui/network/manager.lua +++ b/frontend/ui/network/manager.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ConfirmBox = require("ui/widget/confirmbox") local DataStorage = require("datastorage") local Device = require("device") @@ -225,7 +226,7 @@ function NetworkMgr:getProxyMenuTable() end return { text_func = function() - return T(_("HTTP proxy %1"), (proxy_enabled() and proxy() or "")) + return T(_("HTTP proxy %1"), (proxy_enabled() and BD.url(proxy()) or "")) end, checked_func = function() return proxy_enabled() end, callback = function() @@ -388,7 +389,7 @@ function NetworkMgr:reconnectOrShowNetworkMenu(complete_callback) complete_callback() end UIManager:show(InfoMessage:new{ - text = T(_("Connected to network %1"), network.ssid), + text = T(_("Connected to network %1"), BD.wrap(network.ssid)), timeout = 3, }) return diff --git a/frontend/ui/otamanager.lua b/frontend/ui/otamanager.lua index 055e34403..ff51241c2 100644 --- a/frontend/ui/otamanager.lua +++ b/frontend/ui/otamanager.lua @@ -2,6 +2,7 @@ Checks for updates on the specified nightly build server. ]] +local BD = require("ui/bidi") local ConfirmBox = require("ui/widget/confirmbox") local DataStorage = require("datastorage") local Device = require("device") @@ -243,13 +244,13 @@ function OTAManager:fetchAndProcessUpdate() }) elseif ota_version then local update_message = T(_("Do you want to update?\nInstalled version: %1\nAvailable version: %2"), - local_version, - ota_version) + BD.ltr(local_version), + BD.ltr(ota_version)) local update_ok_text = _("Update") if ota_version < local_version then update_message = T(_("The currently installed version is newer than the available version.\nWould you still like to continue and downgrade?\nInstalled version: %1\nAvailable version: %2"), - local_version, - ota_version) + BD.ltr(local_version), + BD.ltr(ota_version)) update_ok_text = _("Downgrade") end @@ -262,9 +263,9 @@ function OTAManager:fetchAndProcessUpdate() if isAndroid then -- download the package if not present. if android.download(link, ota_package) then - android.notification(T(_("The file %1 already exists."), ota_package)) + android.notification(T(_("The file %1 already exists."), BD.filename(ota_package))) else - android.notification(T(_("Downloading %1"), ota_package)) + android.notification(T(_("Downloading %1"), BD.filename(ota_package))) end elseif Device:isSDL() then Device:openLink(link) diff --git a/frontend/ui/screensaver.lua b/frontend/ui/screensaver.lua index cf932d5f4..10e477a7e 100644 --- a/frontend/ui/screensaver.lua +++ b/frontend/ui/screensaver.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local BookStatusWidget = require("ui/widget/bookstatuswidget") @@ -66,7 +67,7 @@ function Screensaver:chooseFolder() logger.dbg("set screensaver directory to", path) G_reader_settings:saveSetting("screensaver_dir", path) UIManager:show(InfoMessage:new{ - text = T(_("Screensaver directory set to:\n%1"), path), + text = T(_("Screensaver directory set to:\n%1"), BD.dirpath(path)), timeout = 3, }) end, @@ -87,7 +88,7 @@ function Screensaver:chooseFolder() screensaver_dir = DataStorage:getDataDir() .. "/screenshots/" end self.choose_dialog = ButtonDialogTitle:new{ - title = T(_("Current screensaver image directory:\n%1"), screensaver_dir), + title = T(_("Current screensaver image directory:\n%1"), BD.dirpath(screensaver_dir)), buttons = buttons } UIManager:show(self.choose_dialog) @@ -120,13 +121,13 @@ function Screensaver:chooseFile(document_cover) if document_cover then G_reader_settings:saveSetting("screensaver_document_cover", file_path) UIManager:show(InfoMessage:new{ - text = T(_("Screensaver document cover set to:\n%1"), file_path), + text = T(_("Screensaver document cover set to:\n%1"), BD.filepath(file_path)), timeout = 3, }) else G_reader_settings:saveSetting("screensaver_image", file_path) UIManager:show(InfoMessage:new{ - text = T(_("Screensaver image set to:\n%1"), file_path), + text = T(_("Screensaver image set to:\n%1"), BD.filepath(file_path)), timeout = 3, }) end @@ -149,8 +150,8 @@ function Screensaver:chooseFile(document_cover) if screensaver_image == nil then screensaver_image = DataStorage:getDataDir() .. "/resources/koreader.png" end - local title = document_cover and T(_("Current screensaver document cover:\n%1"), screensaver_document_cover) - or T(_("Current screensaver image:\n%1"), screensaver_image) + local title = document_cover and T(_("Current screensaver document cover:\n%1"), BD.filepath(screensaver_document_cover)) + or T(_("Current screensaver image:\n%1"), BD.filepath(screensaver_image)) self.choose_dialog = ButtonDialogTitle:new{ title = title, buttons = buttons diff --git a/frontend/ui/widget/dictquicklookup.lua b/frontend/ui/widget/dictquicklookup.lua index ecf5fcff4..83349d991 100644 --- a/frontend/ui/widget/dictquicklookup.lua +++ b/frontend/ui/widget/dictquicklookup.lua @@ -365,14 +365,14 @@ function DictQuickLookup:update() end local epub_path = dir .. "/" .. filename UIManager:show(ConfirmBox:new{ - text = T(_("Save as %1?"), filename), + text = T(_("Save as %1?"), BD.filename(filename)), ok_callback = function() UIManager:scheduleIn(0.1, function() local Wikipedia = require("ui/wikipedia") Wikipedia:createEpubWithUI(epub_path, self.lookupword, lang, function(success) if success then UIManager:show(ConfirmBox:new{ - text = T(_("Article saved to:\n%1\n\nWould you like to read the downloaded article now?"), epub_path), + text = T(_("Article saved to:\n%1\n\nWould you like to read the downloaded article now?"), BD.filepath(epub_path)), ok_callback = function() -- close all dict/wiki windows, without scheduleIn(highlight.clear()) self:onHoldClose(true) diff --git a/frontend/ui/widget/menu.lua b/frontend/ui/widget/menu.lua index b277bce8b..09ec4c607 100644 --- a/frontend/ui/widget/menu.lua +++ b/frontend/ui/widget/menu.lua @@ -627,8 +627,7 @@ function Menu:init() if self.show_path then self.path_text = TextWidget:new{ face = Font:getFace("xx_smallinfofont"), - text = self.path, - para_direction_rtl = false, -- force LTR + text = BD.directory(self.path), max_width = self.dimen.w - 2*Size.padding.small, truncate_left = true, } @@ -1035,7 +1034,7 @@ function Menu:updateItems(select_number) self:updatePageInfo(select_number) if self.show_path then - self.path_text:setText(self.path) + self.path_text:setText(BD.directory(self.path)) end UIManager:setDirty(self.show_parent, function() diff --git a/frontend/ui/widget/networksetting.lua b/frontend/ui/widget/networksetting.lua index 153a4b4f3..3d17297ee 100644 --- a/frontend/ui/widget/networksetting.lua +++ b/frontend/ui/widget/networksetting.lua @@ -30,6 +30,7 @@ Example: ]] +local BD = require("ui/bidi") local bit = require("bit") local Blitbuffer = require("ffi/blitbuffer") local CenterContainer = require("ui/widget/container/centercontainer") @@ -469,7 +470,7 @@ function NetworkSetting:init() UIManager:close(self, 'ui', self.dimen) end UIManager:show(InfoMessage:new{ - text = T(_("Connected to network %1"), connected_item.info.ssid), + text = T(_("Connected to network %1"), BD.wrap(connected_item.info.ssid)), timeout = 3, }) if self.connect_callback then diff --git a/frontend/ui/widget/opdsbrowser.lua b/frontend/ui/widget/opdsbrowser.lua index 876865309..5f0cef14f 100644 --- a/frontend/ui/widget/opdsbrowser.lua +++ b/frontend/ui/widget/opdsbrowser.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ButtonDialog = require("ui/widget/buttondialog") local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local Cache = require("cache") @@ -303,7 +304,7 @@ function OPDSBrowser:fetchFeed(item_url, username, password, method) return elseif code == 301 then UIManager:show(InfoMessage:new{ - text = T(_("The catalog has been permanently moved. Please update catalog URL to '%1'."), headers['Location']), + text = T(_("The catalog has been permanently moved. Please update catalog URL to '%1'."), BD.url(headers['Location'])), }) elseif code == 401 then UIManager:show(InfoMessage:new{ @@ -355,7 +356,7 @@ function OPDSBrowser:getCatalog(item_url, username, password) elseif not ok and catalog then logger.info("cannot get catalog info from", item_url, catalog) UIManager:show(InfoMessage:new{ - text = T(_("Cannot get catalog info from %1"), (item_url or "")), + text = T(_("Cannot get catalog info from %1"), (BD.url(item_url) or "")), }) return end @@ -545,7 +546,7 @@ function OPDSBrowser:downloadFile(item, format, remote_url) end else UIManager:show(InfoMessage:new { - text = _("Could not save file to:\n") .. local_path, + text = _("Could not save file to:\n") .. BD.filepath(local_path), timeout = 3, }) end @@ -559,7 +560,7 @@ function OPDSBrowser:downloadFile(item, format, remote_url) if lfs.attributes(local_path, "mode") == "file" then UIManager:show(ConfirmBox:new { - text = T(_("The file %1 already exists. Do you want to overwrite it?"), local_path), + text = T(_("The file %1 already exists. Do you want to overwrite it?"), BD.filepath(local_path)), ok_text = _("Overwrite"), ok_callback = function() download() @@ -572,7 +573,7 @@ end function OPDSBrowser:createNewDownloadDialog(path, buttons) self.download_dialog = ButtonDialogTitle:new{ - title = T(_("Download directory:\n%1\n\nDownload file type:"), path), + title = T(_("Download directory:\n%1\n\nDownload file type:"), BD.dirpath(path)), buttons = buttons } end diff --git a/frontend/ui/widget/pathchooser.lua b/frontend/ui/widget/pathchooser.lua index 98f1099e6..6fddda997 100644 --- a/frontend/ui/widget/pathchooser.lua +++ b/frontend/ui/widget/pathchooser.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local FileChooser = require("ui/widget/filechooser") local Font = require("ui/font") @@ -104,14 +105,14 @@ function PathChooser:onMenuHold(item) local filesize = util.getFormattedSize(attr.size) local lastmod = os.date("%Y-%m-%d %H:%M", attr.modification) title = T(_("Select this file?\n\n%1\n\nFile size: %2 bytes\nLast modified: %3"), - path, filesize, lastmod) + BD.filepath(path), filesize, lastmod) else - title = T(_("Select this file?\n\n%1"), path) + title = T(_("Select this file?\n\n%1"), BD.filepath(path)) end elseif attr.mode == "directory" then - title = T(_("Select this directory?\n\n%1"), path) + title = T(_("Select this directory?\n\n%1"), BD.dirpath(path)) else -- just in case we get something else - title = T(_("Select this path?\n\n%1"), path) + title = T(_("Select this path?\n\n%1"), BD.path(path)) end local onConfirm = self.onConfirm self.button_dialog = ButtonDialogTitle:new{ diff --git a/frontend/ui/widget/screenshoter.lua b/frontend/ui/widget/screenshoter.lua index bd6c8f9a6..16e939e20 100644 --- a/frontend/ui/widget/screenshoter.lua +++ b/frontend/ui/widget/screenshoter.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local ConfirmBox = require("ui/widget/confirmbox") local DataStorage = require("datastorage") @@ -42,7 +43,7 @@ function Screenshoter:onScreenshot(filename) local screenshot_name = filename or os.date(self.screenshot_fn_fmt) Screen:shot(screenshot_name) local widget = ConfirmBox:new{ - text = T( _("Saved screenshot to %1.\nWould you like to set it as screensaver?"), screenshot_name), + text = T( _("Saved screenshot to %1.\nWould you like to set it as screensaver?"), BD.filepath(screenshot_name)), ok_text = _("Yes"), ok_callback = function() G_reader_settings:saveSetting("screensaver_type", "image_file") @@ -67,7 +68,7 @@ function Screenshoter:chooseFolder() onConfirm = function(path) G_reader_settings:saveSetting("screenshot_dir", path .. "/") UIManager:show(InfoMessage:new{ - text = T(_("Screenshot directory set to:\n%1"), path), + text = T(_("Screenshot directory set to:\n%1"), BD.dirpath(path)), timeout = 3, }) end, @@ -85,7 +86,7 @@ function Screenshoter:chooseFolder() }) local screenshot_dir = G_reader_settings:readSetting("screenshot_dir") or DataStorage:getDataDir() .. "/screenshots/" self.choose_dialog = ButtonDialogTitle:new{ - title = T(_("Current screenshot directory:\n%1"), screenshot_dir), + title = T(_("Current screenshot directory:\n%1"), BD.dirpath(screenshot_dir)), buttons = buttons } UIManager:show(self.choose_dialog) diff --git a/frontend/ui/widget/sortwidget.lua b/frontend/ui/widget/sortwidget.lua index 015aafd81..da9317e20 100644 --- a/frontend/ui/widget/sortwidget.lua +++ b/frontend/ui/widget/sortwidget.lua @@ -182,8 +182,16 @@ function SortWidget:init() self.item_height = Size.item.height_big -- group for footer + local footer_left_text = "◀" + local footer_right_text = "▶" + local footer_first_up_text = "◀◀" + local footer_last_down_text = "▶▶" + if BD.mirroredUILayout() then + footer_left_text, footer_right_text = footer_right_text, footer_left_text + footer_first_up_text, footer_last_down_text = footer_last_down_text, footer_first_up_text + end self.footer_left = Button:new{ - text = "◀", + text = footer_left_text, width = self.width_widget * 13 / 100, callback = function() self:prevPage() end, text_font_size = 28, @@ -192,7 +200,7 @@ function SortWidget:init() radius = 0, } self.footer_right = Button:new{ - text = "▶", + text = footer_right_text, width = self.width_widget * 13 / 100, callback = function() self:nextPage() end, text_font_size = 28, @@ -201,7 +209,7 @@ function SortWidget:init() radius = 0, } self.footer_first_up = Button:new{ - text = "◀◀", + text = footer_first_up_text, width = self.width_widget * 13 / 100, callback = function() if self.marked > 0 then @@ -216,7 +224,7 @@ function SortWidget:init() radius = 0, } self.footer_last_down = Button:new{ - text = "▶▶", + text = footer_last_down_text, width = self.width_widget * 13 / 100, callback = function() if self.marked > 0 then @@ -415,13 +423,18 @@ function SortWidget:_populateItems() ) end - self.footer_page:setText(T(_("%1/%2"), self.show_page, self.pages), self.width_widget * 22 / 100) + self.footer_page:setText(T(_("%1 / %2"), self.show_page, self.pages), self.width_widget * 22 / 100) + local footer_first_up_text = "◀◀" + local footer_last_down_text = "▶▶" + if BD.mirroredUILayout() then + footer_first_up_text, footer_last_down_text = footer_last_down_text, footer_first_up_text + end if self.marked > 0 then self.footer_first_up:setText("▲", self.width_widget * 13 / 100) self.footer_last_down:setText("▼", self.width_widget * 13 / 100) else - self.footer_first_up:setText("◀◀", self.width_widget * 13 / 100) - self.footer_last_down:setText("▶▶", self.width_widget * 13 / 100) + self.footer_first_up:setText(footer_first_up_text, self.width_widget * 13 / 100) + self.footer_last_down:setText(footer_last_down_text, self.width_widget * 13 / 100) end self.footer_left:enableDisable(self.show_page > 1) self.footer_right:enableDisable(self.show_page < self.pages) diff --git a/frontend/util.lua b/frontend/util.lua index ce093670b..4a6bf3ab8 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -954,14 +954,15 @@ end function util.unpackArchive(archive, extract_to) dbg.dassert(type(archive) == "string") + local BD = require("ui/bidi") local ok if archive:match("%.tar%.bz2$") or archive:match("%.tar%.gz$") or archive:match("%.tar%.lz$") or archive:match("%.tgz$") then ok = os.execute(("./tar xf %q -C %q"):format(archive, extract_to)) else - return false, T(_("Couldn't extract archive:\n\n%1\n\nUnrecognized filename extension."), archive) + return false, T(_("Couldn't extract archive:\n\n%1\n\nUnrecognized filename extension."), BD.filepath(archive)) end if not ok then - return false, T(_("Extracting archive failed:\n\n%1", archive)) + return false, T(_("Extracting archive failed:\n\n%1", BD.filepath(archive))) end return true end diff --git a/plugins/SSH.koplugin/main.lua b/plugins/SSH.koplugin/main.lua index 4968240a6..4e6aef0f3 100644 --- a/plugins/SSH.koplugin/main.lua +++ b/plugins/SSH.koplugin/main.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local DataStorage = require("datastorage") local Device = require("device") local InfoMessage = require("ui/widget/infomessage") -- luacheck:ignore @@ -178,7 +179,7 @@ function SSH:addToMainMenu(menu_items) callback = function() local info = InfoMessage:new{ timeout = 60, - text = T(_("Put your public SSH keys in %1"), path.."/settings/SSH/authorized_keys"), + text = T(_("Put your public SSH keys in %1"), BD.filepath(path.."/settings/SSH/authorized_keys")), } UIManager:show(info) end, diff --git a/plugins/calibrecompanion.koplugin/main.lua b/plugins/calibrecompanion.koplugin/main.lua index d3d2f13b6..44c828a01 100644 --- a/plugins/calibrecompanion.koplugin/main.lua +++ b/plugins/calibrecompanion.koplugin/main.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local InputContainer = require("ui/widget/container/inputcontainer") local InfoMessage = require("ui/widget/infomessage") local UIManager = require("ui/uimanager") @@ -127,7 +128,7 @@ function CalibreCompanion:addToMainMenu(menu_items) address = G_reader_settings:readSetting("calibre_wireless_url") address = string.format("%s:%s", address["address"], address["port"]) end - return T(_("Server address (%1)"), address) + return T(_("Server address (%1)"), BD.ltr(address)) end, sub_item_table = { { @@ -214,7 +215,7 @@ function CalibreCompanion:initCalibreMQ(host, port) self:onReceiveJSON(data) if not self.connect_message then UIManager:show(InfoMessage:new{ - text = T(_("Connected to calibre server at %1:%2"), host, port), + text = T(_("Connected to calibre server at %1"), BD.ltr(T("%1:%2", host, port))), }) self.connect_message = true if self.failed_connect_callback then @@ -467,7 +468,7 @@ function CalibreCompanion:sendBook(arg) outfile:close() logger.info("complete writing file", filename) UIManager:show(InfoMessage:new{ - text = _("Received file:") .. filename, + text = _("Received file:") .. BD.filepath(filename), timeout = 1, }) -- switch to JSON data receiving mode diff --git a/plugins/coverbrowser.koplugin/bookinfomanager.lua b/plugins/coverbrowser.koplugin/bookinfomanager.lua index 1bc0c70d3..84d868a16 100644 --- a/plugins/coverbrowser.koplugin/bookinfomanager.lua +++ b/plugins/coverbrowser.koplugin/bookinfomanager.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local Blitbuffer = require("ffi/blitbuffer") local DataStorage = require("datastorage") local Device = require("device") @@ -844,7 +845,7 @@ Do you want to prune the cache of removed books?]] local orig_moved_offset = info.movable:getMovedOffset() info:free() - info.text = T(_("Indexing %1 / %2…\n\n%3"), i, nb_files, filename) + info.text = T(_("Indexing %1 / %2…\n\n%3"), i, nb_files, BD.filename(filename)) info:init() local text_widget = table.remove(info.movable[1][1], 3) local text_widget_size = text_widget:getSize() diff --git a/plugins/coverbrowser.koplugin/covermenu.lua b/plugins/coverbrowser.koplugin/covermenu.lua index 3581816dd..57c5129a2 100644 --- a/plugins/coverbrowser.koplugin/covermenu.lua +++ b/plugins/coverbrowser.koplugin/covermenu.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local DocumentRegistry = require("document/documentregistry") local DocSettings = require("docsettings") local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") @@ -95,7 +96,7 @@ function CoverMenu:updateItems(select_number) self:updatePageInfo(select_number) if self.show_path then - self.path_text:setText(self.path) + self.path_text:setText(BD.directory(self.path)) end self.show_parent.dithered = self._has_cover_images UIManager:setDirty(self.show_parent, function() diff --git a/plugins/coverbrowser.koplugin/listmenu.lua b/plugins/coverbrowser.koplugin/listmenu.lua index 31ad6a40e..4691700ef 100644 --- a/plugins/coverbrowser.koplugin/listmenu.lua +++ b/plugins/coverbrowser.koplugin/listmenu.lua @@ -230,7 +230,7 @@ function ListMenuItem:update() local pad_width = Screen:scaleBySize(10) -- on the left, in between, and on the right local wleft_width = dimen.w - wright:getWidth() - 3*pad_width local wleft = TextBoxWidget:new{ - text = self.text, + text = BD.directory(self.text), face = Font:getFace("cfont", _fontSize(20)), width = wleft_width, alignment = "left", @@ -479,17 +479,26 @@ function ListMenuItem:update() local series_mode = BookInfoManager:getSetting("series_mode") -- whether to use or not title and authors + -- (We wrap each metadata text with BD.auto() to get for each of them + -- the text direction from the first strong character - which should + -- individually be the best thing, and additionnaly prevent shuffling + -- if concatenated.) if self.do_filename_only or bookinfo.ignore_meta then title = filename_without_suffix -- made out above + title = BD.auto(title) authors = nil else title = bookinfo.title and bookinfo.title or filename_without_suffix + title = BD.auto(title) authors = bookinfo.authors -- If multiple authors (crengine separates them with \n), we -- can display them on multiple lines, but limit to 2, and -- append "et al." to the 2nd if there are more if authors and authors:find("\n") then authors = util.splitToArray(authors, "\n") + for i=1, #authors do + authors[i] = BD.auto(authors[i]) + end if #authors > 1 and bookinfo.series and series_mode == "series_in_separate_line" then authors = { T(_("%1 et al."), authors[1]) } elseif #authors > 2 then @@ -499,12 +508,15 @@ function ListMenuItem:update() -- as we'll fit 3 lines instead of 2, we can avoid some loops by starting from a lower font size fontsize_title = _fontSize(17) fontsize_authors = _fontSize(15) + elseif authors then + authors = BD.auto(authors) end end -- add Series metadata if requested if bookinfo.series then -- Shorten calibre series decimal number (#4.0 => #4) bookinfo.series = bookinfo.series:gsub("(#%d+)%.0$", "%1") + bookinfo.series = BD.auto(bookinfo.series) if series_mode == "append_series_to_title" then if title then title = title .. " - " .. bookinfo.series @@ -645,6 +657,7 @@ function ListMenuItem:update() if self.file_deleted then -- unless file was deleted (can happen with History) hint = " " .. _("(deleted)") end + local text = BD.filename(self.text) local text_widget local fontsize_no_bookinfo = _fontSize(18) repeat @@ -652,7 +665,7 @@ function ListMenuItem:update() text_widget:free() end text_widget = TextBoxWidget:new{ - text = self.text .. hint, + text = text .. hint, face = Font:getFace("cfont", fontsize_no_bookinfo), width = dimen.w - 2 * Screen:scaleBySize(10), alignment = "left", diff --git a/plugins/coverbrowser.koplugin/mosaicmenu.lua b/plugins/coverbrowser.koplugin/mosaicmenu.lua index a5ff6522f..b38cc5400 100644 --- a/plugins/coverbrowser.koplugin/mosaicmenu.lua +++ b/plugins/coverbrowser.koplugin/mosaicmenu.lua @@ -99,10 +99,15 @@ local FakeCover = FrameContainer:new{ padding = 0, bordersize = Size.line.thin, dim = nil, + -- Provided filename, title and authors should not be BD wrapped filename = nil, file_deleted = nil, title = nil, authors = nil, + -- The *_add should be provided BD wrapped if needed + filename_add = nil, + title_add = nil, + authors_add = nil, -- these font sizes will be scaleBySize'd by Font:getFace() authors_font_max = 20, authors_font_min = 6, @@ -123,14 +128,25 @@ function FakeCover:init() local title = self.title local filename = self.filename -- (some engines may have already given filename (without extension) as title) + local bd_wrap_title_as_filename = false if not title then -- use filename as title (big and centered) title = filename filename = nil + if not self.title_add and self.filename_add then + -- filename_add ("…" or "(deleted)") always comes without any title_add + self.title_add = self.filename_add + self.filename_add = nil + end + bd_wrap_title_as_filename = true + end + if filename then + filename = BD.filename(filename) end -- If no authors, and title is filename without extension, it was -- probably made by an engine, and we can consider it a filename, and -- act according to common usage in naming files. - if not authors and title and self.filename:sub(1,title:len()) == title then + if not authors and title and self.filename and self.filename:sub(1,title:len()) == title then + bd_wrap_title_as_filename = true -- Replace a hyphen surrounded by spaces (which most probably was -- used to separate Authors/Title/Serie/Year/Categorie in the -- filename with a \n @@ -150,16 +166,35 @@ function FakeCover:init() -- together on a last line: so, move the zero-width-space -- before it. title = title:gsub("%.\xE2\x80\x8B(%w%w?%w?%w?%w?)$", "\xE2\x80\x8B.%1") + -- These substitutions will hopefully have no impact with the following BD wrapping + end + if title then + title = bd_wrap_title_as_filename and BD.filename(title) or BD.auto(title) end -- If multiple authors (crengine separates them with \n), we -- can display them on multiple lines, but limit to 3, and -- append "et al." on a 4th line if there are more if authors and authors:find("\n") then authors = util.splitToArray(authors, "\n") + for i=1, #authors do + authors[i] = BD.auto(authors[i]) + end if #authors > 3 then authors = { authors[1], authors[2], T(_("%1 et al."), authors[3]) } end authors = table.concat(authors, "\n") + elseif authors then + authors = BD.auto(authors) + end + -- Add any _add, which must be already BD wrapped if needed + if self.filename_add then + filename = (filename and filename or "") .. self.filename_add + end + if self.title_add then + title = (title and title or "") .. self.title_add + end + if self.authors_add then + authors = (authors and authors or "") .. self.authors_add end -- We build the VerticalGroup widget with decreasing font sizes till @@ -207,7 +242,7 @@ function FakeCover:init() end if filename then filename_wg = TextBoxWidget:new{ - text = BD.filename(filename), + text = filename, face = Font:getFace("cfont", math.max(self.filename_font_max - sizedec, self.filename_font_min)), width = text_width, alignment = "center", @@ -429,6 +464,7 @@ function MosaicMenuItem:update() if text:match('/$') then -- remove /, more readable text = text:sub(1, -2) end + text = BD.directory(text) local nbitems = TextBoxWidget:new{ text = self.mandatory, face = Font:getFace("infont", 15), @@ -553,25 +589,27 @@ function MosaicMenuItem:update() else -- add Series metadata if requested local series_mode = BookInfoManager:getSetting("series_mode") + local title_add, authors_add if bookinfo.series then -- Shorten calibre series decimal number (#4.0 => #4) bookinfo.series = bookinfo.series:gsub("(#%d+)%.0$", "%1") + bookinfo.series = BD.auto(bookinfo.series) if series_mode == "append_series_to_title" then if bookinfo.title then - bookinfo.title = bookinfo.title .. " - " .. bookinfo.series + title_add = " - " .. bookinfo.series else - bookinfo.title = bookinfo.series + title_add = bookinfo.series end end if not bookinfo.authors then if series_mode == "append_series_to_authors" or series_mode == "series_in_separate_line" then - bookinfo.authors = bookinfo.series + authors_add = bookinfo.series end else if series_mode == "append_series_to_authors" then - bookinfo.authors = bookinfo.authors .. " - " .. bookinfo.series + authors_add = " - " .. bookinfo.series elseif series_mode == "series_in_separate_line" then - bookinfo.authors = bookinfo.authors .. "\n \n" .. bookinfo.series + authors_add = "\n \n" .. bookinfo.series end end end @@ -585,6 +623,8 @@ function MosaicMenuItem:update() filename = self.text, title = not bookinfo.ignore_meta and bookinfo.title, authors = not bookinfo.ignore_meta and bookinfo.authors, + title_add = not bookinfo.ignore_meta and title_add, + authors_add = not bookinfo.ignore_meta and authors_add, file_deleted = self.file_deleted, } } @@ -622,7 +662,8 @@ function MosaicMenuItem:update() width = dimen.w, height = dimen.h, bordersize = border_size, - filename = self.text .. "\n" .. hint, + filename = self.text, + filename_add = "\n" .. hint, initial_sizedec = 4, -- start with a smaller font when filenames only file_deleted = self.file_deleted, } diff --git a/plugins/docsettingtweak.koplugin/main.lua b/plugins/docsettingtweak.koplugin/main.lua index d8f8ab53f..33a4d9f5f 100644 --- a/plugins/docsettingtweak.koplugin/main.lua +++ b/plugins/docsettingtweak.koplugin/main.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local DataStorage = require("datastorage") local FFIUtil = require("ffi/util") local InputDialog = require("ui/widget/inputdialog") @@ -48,7 +49,7 @@ function DocSettingTweak:editDirectoryDefaults() directory_defaults_file:close() local config_editor config_editor = InputDialog:new{ - title = T(_("Directory Defaults: %1"),directory_defaults_path), + title = T(_("Directory Defaults: %1"), BD.filepath(directory_defaults_path)), input = defaults, input_type = "string", para_direction_rtl = false, -- force LTR diff --git a/plugins/evernote.koplugin/main.lua b/plugins/evernote.koplugin/main.lua index 5bce641ef..9b8839f2f 100644 --- a/plugins/evernote.koplugin/main.lua +++ b/plugins/evernote.koplugin/main.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local InputContainer = require("ui/widget/container/inputcontainer") local LoginDialog = require("ui/widget/logindialog") local InfoMessage = require("ui/widget/infomessage") @@ -242,7 +243,7 @@ For Windows: netsh interface portproxy add listeningaddress:0.0.0.0 listeningpor For Linux: $socat tcp-listen:41185,reuseaddr,fork tcp:localhost:41184 For more information, please visit https://github.com/koreader/koreader/wiki/Evernote-export.]]) - ,DataStorage:getDataDir()) + , BD.dirpath(DataStorage:getDataDir())) }) end } @@ -595,7 +596,7 @@ function EvernoteExporter:exportClippings(clippings) end end if (self.html_export or self.txt_export) and export_count > 0 then - msg = msg .. T(_("\nNotes can be found in %1/."), realpath(self.clipping_dir)) + msg = msg .. T(_("\nNotes can be found in %1/."), BD.dirpath(realpath(self.clipping_dir))) end UIManager:show(InfoMessage:new{ text = msg }) end diff --git a/plugins/newsdownloader.koplugin/main.lua b/plugins/newsdownloader.koplugin/main.lua index 40f6672d9..2474912f9 100644 --- a/plugins/newsdownloader.koplugin/main.lua +++ b/plugins/newsdownloader.koplugin/main.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local DataStorage = require("datastorage") --local DownloadBackend = require("internaldownloadbackend") --local DownloadBackend = require("luahttpdownloadbackend") @@ -125,7 +126,7 @@ function NewsDownloader:addToMainMenu(menu_items) callback = function() UIManager:show(InfoMessage:new{ text = T(_("News downloader retrieves RSS and Atom news entries and stores them to:\n%1\n\nEach entry is a separate html file, that can be browsed by KOReader file manager.\nItems download limit can be configured in Settings."), - news_download_dir_path) + BD.dirpath(news_download_dir_path)) }) end, }, @@ -183,7 +184,7 @@ function NewsDownloader:loadConfigAndProcessFeeds() local download_full_article = feed.download_full_article == nil or feed.download_full_article local include_images = feed.include_images if url and limit then - local feed_message = T(_("Processing %1/%2:\n%3"), idx, total_feed_entries, url) + local feed_message = T(_("Processing %1/%2:\n%3"), idx, total_feed_entries, BD.url(url)) UI:info(feed_message) NewsDownloader:processFeedSource(url, tonumber(limit), unsupported_feeds_urls, download_full_article, include_images, feed_message) else @@ -198,7 +199,7 @@ function NewsDownloader:loadConfigAndProcessFeeds() for k,url in pairs(unsupported_feeds_urls) do unsupported_urls = unsupported_urls .. url if k ~= #unsupported_feeds_urls then - unsupported_urls = unsupported_urls .. ", " + unsupported_urls = BD.url(unsupported_urls) .. ", " end end UI:info(T(_("Downloading news finished. Could not process some feeds. Unsupported format in: %1"), unsupported_urls)) @@ -408,7 +409,7 @@ function NewsDownloader:changeFeedConfig() feed_config_file:close() local config_editor config_editor = InputDialog:new{ - title = T(_("Config: %1"),feed_config_path), + title = T(_("Config: %1"), BD.filepath(feed_config_path)), input = config, input_type = "string", para_direction_rtl = false, -- force LTR diff --git a/plugins/send2ebook.koplugin/main.lua b/plugins/send2ebook.koplugin/main.lua index 5155c5745..62376f110 100644 --- a/plugins/send2ebook.koplugin/main.lua +++ b/plugins/send2ebook.koplugin/main.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local DataStorage = require("datastorage") local DocSettings = require("frontend/docsettings") local ReadHistory = require("readhistory") @@ -103,7 +104,7 @@ function Send2Ebook:addToMainMenu(menu_items) keep_menu_open = true, callback = function() UIManager:show(InfoMessage:new{ - text = T(_('Send2Ebook lets you send articles found on PC/Android phone to your Ebook reader (using ftp server).\n\nMore details: https://github.com/mwoz123/send2ebook\n\nDownloads to local folder: %1'), download_dir_path) + text = T(_('Send2Ebook lets you send articles found on PC/Android phone to your Ebook reader (using ftp server).\n\nMore details: https://github.com/mwoz123/send2ebook\n\nDownloads to local folder: %1'), BD.dirpath(download_dir_path)) }) end, }, @@ -143,7 +144,7 @@ function Send2Ebook:process() local ftp_files_table = FtpApi:listFolder(connection_url .. ftp_config.folder, ftp_config.folder) --args looks strange but otherwise resonse with invalid paths if not ftp_files_table then - info = InfoMessage:new{ text = T(_("Could not get file list for server: %1, user: %2, folder: %3"), ftp_config.address, ftp_config.username, ftp_config.folder) } + info = InfoMessage:new{ text = T(_("Could not get file list for server: %1, user: %2, folder: %3"), BD.ltr(ftp_config.address), ftp_config.username, BD.dirpath(ftp_config.folder)) } else local total_entries = table.getn(ftp_files_table) logger.dbg("Send2Ebook: total_entries ", total_entries) diff --git a/plugins/statistics.koplugin/main.lua b/plugins/statistics.koplugin/main.lua index 7c98d17de..f6d2ca3b9 100644 --- a/plugins/statistics.koplugin/main.lua +++ b/plugins/statistics.koplugin/main.lua @@ -1,3 +1,4 @@ +local BD = require("ui/bidi") local BookStatusWidget = require("ui/widget/bookstatuswidget") local ConfirmBox = require("ui/widget/confirmbox") local DataStorage = require("datastorage") @@ -235,7 +236,7 @@ Cannot open database in %1. The database may have been moved or deleted. Do you want to create an empty database? ]]), - db_location), + BD.filepath(db_location)), cancel_text = _("Close"), cancel_callback = function() return diff --git a/plugins/texteditor.koplugin/main.lua b/plugins/texteditor.koplugin/main.lua index 1349c90ab..77bff2370 100644 --- a/plugins/texteditor.koplugin/main.lua +++ b/plugins/texteditor.koplugin/main.lua @@ -171,7 +171,7 @@ Enable this if you are mostly editing code, HTML, CSS…]]), local file_path = self.history[i] local directory, filename = util.splitFilePathName(file_path) -- luacheck: no unused table.insert(sub_item_table, { - text = T("%1. %2", i, filename), + text = T("%1. %2", i, BD.filename(filename)), keep_menu_open = true, callback = function(touchmenu_instance) self:setupWhenDoneFunc(touchmenu_instance) @@ -186,10 +186,10 @@ Enable this if you are mostly editing code, HTML, CSS…]]), local filesize = util.getFormattedSize(attr.size) local lastmod = os.date("%Y-%m-%d %H:%M", attr.modification) text = T(_("File path:\n%1\n\nFile size: %2 bytes\nLast modified: %3\n\nRemove this file from text editor history?"), - file_path, filesize, lastmod) + BD.filepath(file_path), filesize, lastmod) else text = T(_("File path:\n%1\n\nThis file does not exist anymore.\n\nRemove it from text editor history?"), - file_path) + BD.filepath(file_path)) end UIManager:show(ConfirmBox:new{ text = text, @@ -332,7 +332,7 @@ function TextEditor:checkEditFile(file_path, from_history, possibly_new_file) local attr = lfs.attributes(file_path) if not possibly_new_file and not attr then UIManager:show(ConfirmBox:new{ - text = T(_("This file does not exist anymore:\n\n%1\n\nDo you want to create it and start editing it?"), file_path), + text = T(_("This file does not exist anymore:\n\n%1\n\nDo you want to create it and start editing it?"), BD.filepath(file_path)), ok_text = _("Yes"), cancel_text = _("No"), ok_callback = function() @@ -350,7 +350,7 @@ function TextEditor:checkEditFile(file_path, from_history, possibly_new_file) if attr then -- File exists if attr.mode ~= "file" then UIManager:show(InfoMessage:new{ - text = T(_("This file is not a regular file:\n\n%1"), file_path) + text = T(_("This file is not a regular file:\n\n%1"), BD.filepath(file_path)) }) return end @@ -368,7 +368,7 @@ function TextEditor:checkEditFile(file_path, from_history, possibly_new_file) if not from_history and attr.size > self.min_file_size_warn then UIManager:show(ConfirmBox:new{ text = T(_("This file is %2:\n\n%1\n\nAre you sure you want to open it?\n\nOpening big files may take some time."), - file_path, util.getFriendlySize(attr.size)), + BD.filepath(file_path), util.getFriendlySize(attr.size)), ok_text = _("Yes"), cancel_text = _("No"), ok_callback = function() @@ -389,7 +389,7 @@ function TextEditor:checkEditFile(file_path, from_history, possibly_new_file) self:editFile(file_path) else UIManager:show(InfoMessage:new{ - text = T(_("This file can not be created:\n\n%1\n\nReason: %2"), file_path, err) + text = T(_("This file can not be created:\n\n%1\n\nReason: %2"), BD.filepath(file_path), err) }) return end @@ -526,7 +526,7 @@ Lua syntax check failed: KOReader may crash if this is saved. Do you really want to save to this file? -%2]]), parse_error, file_path), _("Do not save"), _("Save anyway")) +%2]]), parse_error, BD.filepath(file_path)), _("Do not save"), _("Save anyway")) -- we'll get the safer "Do not save" on tap outside if save_anyway then local ok, err = self:saveFileContent(file_path, content) @@ -543,7 +543,7 @@ Do you really want to save to this file? Text content is empty. Do you want to keep this file as empty, or do you prefer to delete it? -%1]]), file_path), _("Keep empty file"), _("Delete file")) +%1]]), BD.filepath(file_path)), _("Keep empty file"), _("Delete file")) -- we'll get the safer "Keep empty file" on tap outside if delete_file then local ok, err = self:deleteFile(file_path) diff --git a/plugins/wallabag.koplugin/main.lua b/plugins/wallabag.koplugin/main.lua index 3ed4e3c03..142adff79 100644 --- a/plugins/wallabag.koplugin/main.lua +++ b/plugins/wallabag.koplugin/main.lua @@ -2,6 +2,7 @@ @module koplugin.wallabag ]] +local BD = require("ui/bidi") local DataStorage = require("datastorage") local DocSettings = require("docsettings") local Event = require("ui/event") @@ -163,7 +164,7 @@ function Wallabag:addToMainMenu(menu_items) else path = filemanagerutil.abbreviate(self.directory) end - return T(_("Set download directory (%1)"), path) + return T(_("Set download directory (%1)"), BD.dirpath(path)) end, keep_menu_open = true, callback = function(touchmenu_instance) @@ -261,7 +262,7 @@ The 'Synchronize remotely deleted files' option will remove local files that no More details: https://wallabag.org -Downloads to directory: %1]]), filemanagerutil.abbreviate(self.directory)) +Downloads to directory: %1]]), BD.dirpath(filemanagerutil.abbreviate(self.directory))) }) end, }, @@ -824,7 +825,7 @@ Enter the details of your Wallabag server and account. Client ID and client secret are long strings so you might prefer to save the empty settings and edit the config file directly in your installation directory: %1/wallabag.lua -Restart KOReader after editing the config file.]]), DataStorage:getSettingsDir()) +Restart KOReader after editing the config file.]]), BD.dirpath(DataStorage:getSettingsDir())) self.settings_dialog = MultiInputDialog:new { title = _("Wallabag settings"), @@ -994,11 +995,11 @@ function Wallabag:onAddWallabagArticle(article_url) local wallabag_result = self:addArticle(article_url) if wallabag_result then UIManager:show(InfoMessage:new{ - text = T(_("Article added to Wallabag:\n%1"), article_url), + text = T(_("Article added to Wallabag:\n%1"), BD.url(article_url)), }) else UIManager:show(InfoMessage:new{ - text = T(_("Error adding link to Wallabag:\n%1"), article_url), + text = T(_("Error adding link to Wallabag:\n%1"), BD.url(article_url)), }) end