update tool to generate metadata translations (#11869)

* updated:

    - strings to translate
    - english metadata

* added:

    - appstream: metadata generator
    - appstream: translation of screenshot captions, if they're present.
    - appstream: link to gh release notes
reviewable/pr11905/r1
Martín Fernández 3 weeks ago committed by GitHub
parent a21db40745
commit 3fb2f18041
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -9,7 +9,7 @@ update: all
$(SYMLINK) $(abspath $(APPIMAGE_DIR)/AppRun) $(INSTALL_DIR)/koreader/
$(SYMLINK) $(abspath $(APPIMAGE_DIR)/koreader.desktop) $(INSTALL_DIR)/koreader/
$(SYMLINK) $(abspath resources/koreader.png) $(INSTALL_DIR)/koreader/
sed -e 's/%%VERSION%%/$(VERSION)/' -e 's/%%DATE%%/$(RELEASE_DATE)/' $(APPIMAGE_DIR)/koreader.appdata.xml >$(INSTALL_DIR)/koreader/koreader.appdata.xml
sed -e 's/%%VERSION%%/$(VERSION)/' -e 's/%%DATE%%/$(RELEASE_DATE)/' $(PLATFORM_DIR)/common/koreader.metainfo.xml >$(INSTALL_DIR)/koreader/koreader.appdata.xml
# TODO at best this is DebUbuntu specific
$(SYMLINK) /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0 $(INSTALL_DIR)/koreader/libs/libSDL2.so
# required for our stock Ubuntu SDL even though we don't use sound

@ -8,10 +8,11 @@ update: all
$(INSTALL_DIR)/linux/bin \
$(INSTALL_DIR)/linux/lib \
$(INSTALL_DIR)/linux/share/pixmaps \
$(INSTALL_DIR)/linux/share/metainfo \
$(INSTALL_DIR)/linux/share/applications \
$(INSTALL_DIR)/linux/share/doc/koreader \
$(INSTALL_DIR)/linux/share/man/man1
sed -e 's/%%VERSION%%/$(VERSION)/' -e 's/%%DATE%%/$(RELEASE_DATE)/' $(PLATFORM_DIR)/appimage/koreader.appdata.xml >$(INSTALL_DIR)/linux/koreader.appdata.xml
sed -e 's/%%VERSION%%/$(VERSION)/g' -e 's/%%DATE%%/$(RELEASE_DATE)/' $(PLATFORM_DIR)/common/koreader.metainfo.xml >$(INSTALL_DIR)/linux/share/metainfo/koreader.metainfo.xml
cp -pv resources/koreader.png $(INSTALL_DIR)/linux/share/pixmaps
cp -pv $(LINUX_DIR)/koreader.desktop $(INSTALL_DIR)/linux/share/applications
cp -pv $(LINUX_DIR)/copyright COPYING $(INSTALL_DIR)/linux/share/doc/koreader

@ -1,14 +1,11 @@
* portable: runs on embedded devices (Cervantes, Kindle, Kobo, PocketBook), Android and Linux computers. Developers can run a KOReader emulator in Linux and MacOS.
* multi-format documents: supports fixed page formats (PDF, DjVu, CBT, CBZ) and reflowable e-book formats (EPUB, FB2, Mobi, DOC, CHM, TXT). Scanned PDF/DjVu documents can also be reflowed with the built-in K2pdfopt library.
* full-featured reading: multi-lingual user interface with a highly customizable reader view and many typesetting options. You can set arbitrary page margins, override line spacing and choose external fonts and styles. It has multi-lingual hyphenation dictionaries bundled into the application.
* integrated with calibre (search metadata, receive ebooks wirelessly, browse library via OPDS), Wallabag, Wikipedia, Google Translate and other content providers.
* optimized for e-ink devices: custom UI without animation, with paginated menus, adjustable text contrast, and easy zoom to fit content or page in paged media.
* extensible via plugins
* and much more: look up words with StarDict dictionaries / Wikipedia, add your own online OPDS catalogs and RSS feeds, online over-the-air software updates, an FTP client, an SSH server, …
<p>KOReader is an ebook reader optimized for e-ink screens. It can open many formats and provides advanced text adjustments.</p>
<p>See below for a selection of its many features:</p>
<ul>
<li>Supports both fixed page formats (PDF, DjVu, CBT, CBZ) and reflowable e-book formats (EPUB, FB2, Mobi, DOC, CHM, TXT, HTML). Scanned PDF&#47;DjVu documents can be reflowed. Special flow directions for reading double column PDFs and manga.</li>
<li>Multi-lingual user interface optimized for e-ink screens. Highly customizable reader view with complete typesetting options. Multi-lingual hyphenation dictionaries are bundled in.</li>
<li>Non-Latin script support for books, including the Hebrew, Arabic, Persian, Russian, Chinese, Japanese and Korean languages.</li>
<li>Unique Book Map and Page Browser features to navigate your book.</li>
<li>Special multi-page highlight mode with many local and online export options.</li>
<li>Can synchronize your reading progress across all your KOReader running devices.</li>
<li>Integrated with Calibre, Wallabag, Wikipedia, Google translate and other content providers.</li>
</ul>

@ -1 +1 @@
Ebook reader with support for many formats like PDF, DjVu, EPUB, FB2, CBZ.
Ebook reader

@ -1,55 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Do not edit this file. Edit "tools/update-metadata.lua" instead-->
<component type="desktop-application">
<id>rocks.koreader.KOReader</id>
<name>KOReader</name>
<summary>Ebook reader</summary>
<description>
<p>KOReader is an ebook reader optimized for e-ink screens. It can open many formats and provides advanced text adjustments.</p>
<p>See below for a selection of its many features:</p>
<ul>
<li>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.</li>
<li>Multi-lingual user interface optimized for e-ink screens. Highly customizable reader view with complete typesetting options. Multi-lingual hyphenation dictionaries are bundled in.</li>
<li>Non-Latin script support for books, including the Hebrew, Arabic, Persian, Russian, Chinese, Japanese and Korean languages.</li>
<li>Unique Book Map and Page Browser features to navigate your book.</li>
<li>Special multi-page highlight mode with many local and online export options.</li>
<li>Can synchronize your reading progress across all your KOReader running devices.</li>
<li>Integrated with Calibre, Wallabag, Wikipedia, Google translate and other content providers.</li>
</ul>
</description>
<screenshots>
<screenshot type="default">
<image>
https://github.com/koreader/koreader-artwork/raw/master/koreader-menu-framed.png</image>
</screenshot>
<screenshot>
<image>
https://github.com/koreader/koreader-artwork/raw/master/koreader-footnotes-framed.png</image>
</screenshot>
<screenshot>
<image>
https://github.com/koreader/koreader-artwork/raw/master/koreader-dictionary-framed.png</image>
</screenshot>
</screenshots>
<categories>
<category>Viewer</category>
<category>Literature</category>
</categories>
<developer_name>KOReader Community</developer_name>
<developer id="rocks.koreader">
<name>KOReader Community</name>
</developer>
<metadata_license>CC0-1.0</metadata_license>
<project_license>AGPL-3.0-only</project_license>
<url type="homepage">https://koreader.rocks/</url>
<url type="bugtracker">https://github.com/koreader/koreader/issues</url>
<url type="faq">https://github.com/koreader/koreader/wiki</url>
<url type="faq">https://koreader.rocks/user_guide</url>
<url type="translate">https://hosted.weblate.org/engage/koreader/</url>
<url type="vcs-browser">https://github.com/koreader/koreader</url>
<url type="contribute">https://koreader.rocks/doc/</url>
<url type="contribute">https://github.com/koreader/koreader</url>
<branding>
<color type="primary" scheme_preference="light">#ffffff</color>
@ -57,7 +24,6 @@
</branding>
<requires>
<memory>128</memory>
<display_length>360</display_length>
</requires>
@ -117,9 +83,57 @@
<launchable type="desktop-id">rocks.koreader.KOReader.desktop</launchable>
<releases>
<release version="%%VERSION%%" date="%%DATE%%"/>
</releases>
<categories>
<category>Office</category>
<category>Viewer</category>
<category>Literature</category>
</categories>
<content_rating type="oars-1.1"/>
<summary>Ebook reader</summary>
<description>
<p>KOReader is an ebook reader optimized for e-ink screens. It can open many formats and provides advanced text adjustments.</p>
<p>See below for a selection of its many features:</p>
<ul>
<li>Supports both fixed page formats (PDF, DjVu, CBT, CBZ) and reflowable e-book formats (EPUB, FB2, Mobi, DOC, CHM, TXT, HTML). Scanned PDF&#47;DjVu documents can be reflowed. Special flow directions for reading double column PDFs and manga.</li>
<li>Multi-lingual user interface optimized for e-ink screens. Highly customizable reader view with complete typesetting options. Multi-lingual hyphenation dictionaries are bundled in.</li>
<li>Non-Latin script support for books, including the Hebrew, Arabic, Persian, Russian, Chinese, Japanese and Korean languages.</li>
<li>Unique Book Map and Page Browser features to navigate your book.</li>
<li>Special multi-page highlight mode with many local and online export options.</li>
<li>Can synchronize your reading progress across all your KOReader running devices.</li>
<li>Integrated with Calibre, Wallabag, Wikipedia, Google translate and other content providers.</li>
</ul>
</description>
<screenshots>
<screenshot type="default">
<image>https://github.com/koreader/koreader-artwork/raw/master/koreader-menu-framed.png</image>
</screenshot>
<screenshot>
<image>https://github.com/koreader/koreader-artwork/raw/master/koreader-footnotes-framed.png</image>
</screenshot>
<screenshot>
<image>https://github.com/koreader/koreader-artwork/raw/master/koreader-dictionary-framed.png</image>
</screenshot>
</screenshots>
<keywords>
<keyword>reader</keyword>
<keyword>viewer</keyword>
<keyword>dictionary</keyword>
<keyword>wikipedia</keyword>
<keyword>wallabag</keyword>
<keyword>annotations</keyword>
<keyword>epub</keyword>
<keyword>fb2</keyword>
<keyword>pdf</keyword>
<keyword>djvu</keyword>
</keywords>
<releases>
<release version="%%VERSION%%" date="%%DATE%%">
<description>
<p>Release notes available on the link below</p>
</description>
<url>https://github.com/koreader/koreader/releases/tag/%%VERSION%%</url>
</release>
</releases>
</component>

@ -65,7 +65,7 @@ fi
mkdir -p tmp-debian/usr
chmod 0755 tmp-debian/usr
tar -xf "${1}" -C tmp-debian/usr
rm -f tmp-debian/usr/koreader.appdata.xml tmp-debian/usr/README.md
rm -f tmp-debian/usr/README.md
ARCH="$(echo "${1}" | cut -d '-' -f3)"
VERSION="$(cut -f2 -dv "tmp-debian/usr/lib/koreader/git-rev" | cut -f1,2 -d-)"
DEB_ARCH="$(uname_to_debian "${ARCH}")"

@ -1,46 +1,168 @@
#!/usr/bin/env luajit
-- tool to generate localized metadata
--
-- metadata is fetched by F-Droid on each tagged release and used to update
-- https://f-droid.org/packages/org.koreader.launcher.fdroid/
--
-- usage: ./tools/update_metadata.lua
--
-- NOTE: title and screenshots are not translated. These resources are located in metadata/en-US
--[[
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("[}{\">/<'&]", {
["&"] = "&amp;",
["<"] = "&lt;",
[">"] = "&gt;",
['"'] = "&quot;",
["'"] = "&#39;",
["/"] = "&#47;",
})
end
local metadata = {
["short_description.txt"] = _("Ebook reader with support for many formats like PDF, DjVu, EPUB, FB2, CBZ."),
["full_description.txt"] = _([[* portable: runs on embedded devices (Cervantes, Kindle, Kobo, PocketBook), Android and Linux computers. Developers can run a KOReader emulator in Linux and MacOS.
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",
},
* multi-format documents: supports fixed page formats (PDF, DjVu, CBT, CBZ) and reflowable e-book formats (EPUB, FB2, Mobi, DOC, CHM, TXT). Scanned PDF/DjVu documents can also be reflowed with the built-in K2pdfopt library.
-- appstream metadata that needs no translation
component = [[
<id>rocks.koreader.KOReader</id>
* full-featured reading: multi-lingual user interface with a highly customizable reader view and many typesetting options. You can set arbitrary page margins, override line spacing and choose external fonts and styles. It has multi-lingual hyphenation dictionaries bundled into the application.
<name>KOReader</name>
<developer id="rocks.koreader">
<name>KOReader Community</name>
</developer>
* integrated with calibre (search metadata, receive ebooks wirelessly, browse library via OPDS), Wallabag, Wikipedia, Google Translate and other content providers.
<metadata_license>CC0-1.0</metadata_license>
<project_license>AGPL-3.0-only</project_license>
* optimized for e-ink devices: custom UI without animation, with paginated menus, adjustable text contrast, and easy zoom to fit content or page in paged media.
<url type="homepage">https://koreader.rocks/</url>
<url type="bugtracker">https://github.com/koreader/koreader/issues</url>
<url type="faq">https://koreader.rocks/user_guide</url>
<url type="translate">https://hosted.weblate.org/engage/koreader/</url>
<url type="vcs-browser">https://github.com/koreader/koreader</url>
<url type="contribute">https://github.com/koreader/koreader</url>
* extensible via plugins
<branding>
<color type="primary" scheme_preference="light">#ffffff</color>
<color type="primary" scheme_preference="dark">#303030</color>
</branding>
* and much more: look up words with StarDict dictionaries / Wikipedia, add your own online OPDS catalogs and RSS feeds, online over-the-air software updates, an FTP client, an SSH server,
]]),
}
<requires>
<display_length>360</display_length>
</requires>
local function isFile(str)
local f = io.open(str, "r")
if f then
f:close()
return true
end
return false
end
<supports>
<control>pointing</control>
<control>keyboard</control>
<control>gamepad</control>
</supports>
<recommends>
<memory>1024</memory>
<display_length compare="ge">600</display_length>
<internet>always</internet>
<control>touch</control>
</recommends>
<provides>
<mediatype>application/epub+zip</mediatype>
<mediatype>application/fb2</mediatype>
<mediatype>application/fb3</mediatype>
<mediatype>application/msword</mediatype>
<mediatype>application/oxps</mediatype>
<mediatype>application/pdf</mediatype>
<mediatype>application/rtf</mediatype>
<mediatype>application/tcr</mediatype>
<mediatype>application/vnd.amazon.mobi8-ebook</mediatype>
<mediatype>application/vnd.comicbook+tar</mediatype>
<mediatype>application/vnd.comicbook+zip</mediatype>
<mediatype>application/vnd.ms-htmlhelp</mediatype>
<mediatype>application/vnd.openxmlformats-officedocument.wordprocessingml.document</mediatype>
<mediatype>application/vnd.palm</mediatype>
<mediatype>application/x-cbz</mediatype>
<mediatype>application/x-chm</mediatype>
<mediatype>application/x-fb2</mediatype>
<mediatype>application/x-fb3</mediatype>
<mediatype>application/x-mobipocket-ebook</mediatype>
<mediatype>application/x-tar</mediatype>
<mediatype>application/xhtml+xml</mediatype>
<mediatype>application/xml</mediatype>
<mediatype>application/zip</mediatype>
<mediatype>image/djvu</mediatype>
<mediatype>image/gif</mediatype>
<mediatype>image/jp2</mediatype>
<mediatype>image/jpeg</mediatype>
<mediatype>image/jxr</mediatype>
<mediatype>image/png</mediatype>
<mediatype>image/svg+xml</mediatype>
<mediatype>image/tiff</mediatype>
<mediatype>image/vnd.djvu</mediatype>
<mediatype>image/vnd.ms-photo</mediatype>
<mediatype>image/x-djvu</mediatype>
<mediatype>image/x-portable-arbitrarymap</mediatype>
<mediatype>image/x-portable-bitmap</mediatype>
<mediatype>text/html</mediatype>
<mediatype>text/plain</mediatype>
</provides>
<launchable type="desktop-id">rocks.koreader.KOReader.desktop</launchable>
<categories>
<category>Office</category>
<category>Viewer</category>
<category>Literature</category>
</categories>
<content_rating type="oars-1.1"/>
]],
}
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")
@ -65,38 +187,186 @@ local function getLocales()
end
end
output:close()
table.insert(locales, 1, "en")
return locales
end
----------------------------------------------------------------
print("updating metadata for " .. #getLocales() .. " languages")
for file, str in pairs(metadata) do
local count = { new = 0, updated = 0, not_translated = 0 }
local locales = getLocales()
-- update english
_.changeLang("en")
local source = _(str)
local metadata_file = "metadata/en-US/" .. file
writeFile(source, metadata_file)
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, "<p>" .. htmlEscape(_(v)) .. "</p>")
end
table.insert(t, "<ul>")
for i, v in ipairs(desc.highlights) do
table.insert(t, " <li>" .. htmlEscape(_(v)) .. "</li>")
end
table.insert(t, "</ul>")
return table.concat(t, "\n")
end
-- update translations
for __, lang in ipairs(getLocales()) do
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</%s>",
offset, element, str, element)
else
return string.format('%s<%s xml:lang="%s">%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, '<?xml version="1.0" encoding="UTF-8"?>')
table.insert(t, '<!--Do not edit this file. Edit "tools/update-metadata.lua" instead-->')
table.insert(t, '<component type="desktop-application">')
table.insert(t, metadata.component)
local orig, translated
_.changeLang("en")
orig = metadata.summary
for __, lang in ipairs(locales) do
_.changeLang(lang)
local translation = _(str)
if source ~= translation then
local metadata_dir = "metadata/" .. lang
metadata_file = metadata_dir .. "/" .. file
os.execute('mkdir -p ' .. metadata_dir)
if isFile(metadata_file) then
count.updated = count.updated + 1
else
count.new = count.new + 1
translated = _(metadata.summary)
if orig ~= translated or lang == "en" then
table.insert(t, tag("summary", lang, htmlEscape(translated), 2))
end
end
table.insert(t, ' <description>')
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, ' <ul>')
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
writeFile(translation, metadata_file)
end
end
table.insert(t, ' </ul>')
table.insert(t, ' </description>')
table.insert(t, ' <screenshots>')
for i, v in ipairs(metadata.screenshots) do
if v.default then
table.insert(t, ' <screenshot type="default">')
else
count.not_translated = count.not_translated + 1
table.insert(t, ' <screenshot>')
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, ' </screenshot>')
end
table.insert(t, ' </screenshots>')
table.insert(t, ' <keywords>')
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
print(string.format("%s: %d new | %d updated | %d not translated",
file, count.new, count.updated, count.not_translated))
table.insert(t, ' </keywords>')
table.insert(t, [[ <releases>
<release version="%%VERSION%%" date="%%DATE%%">
<description>]])
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, [[ </description>
<url>https://github.com/koreader/koreader/releases/tag/%%VERSION%%</url>
</release>
</releases>]])
table.insert(t, '</component>')
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"))

Loading…
Cancel
Save