[gnome-software/wip/rancell/ubuntu-xenial-rebase] merge with gnome-3-20



commit f861c9097ae6be376498c94db00ec0aab397ecf7
Author: Robert Ancell <robert ancell canonical com>
Date:   Tue May 17 09:56:36 2016 +1200

    merge with gnome-3-20

 RELEASE                                            |    6 +-
 configure.ac                                       |    4 +-
 data/Makefile.am                                   |    3 -
 data/appdata/org.gnome.Software.appdata.xml.in     |   11 +
 doc/kudos.md                                       |   42 +-
 doc/update-fedora-tagger.sh                        |    1 -
 po/LINGUAS                                         |    1 +
 po/POTFILES.in                                     |   13 +-
 po/fur.po                                          | 2814 ++++++++++++++++++++
 po/ja.po                                           |  655 +++--
 po/pt_BR.po                                        |   55 +-
 po/ru.po                                           |  130 +-
 po/sr.po                                           |   16 +-
 src/Makefile.am                                    |   23 +-
 src/gnome-software.gresource.xml                   |   18 +-
 src/gs-app-folder-dialog.c                         |    2 +-
 ...pp-folder-dialog.ui => gs-app-folder-dialog.ui} |    0
 src/gs-app-row.c                                   |   12 +-
 src/gs-app-tile.c                                  |    2 +-
 src/{app-tile.ui => gs-app-tile.ui}                |    0
 src/gs-app.c                                       |  399 ++--
 src/gs-app.h                                       |   19 +-
 src/gs-application.c                               |    4 +-
 src/gs-category-tile.c                             |    2 +-
 src/{category-tile.ui => gs-category-tile.ui}      |    0
 src/gs-category.c                                  |    3 +
 src/gs-cmd.c                                       |   30 +-
 src/gs-feature-tile.c                              |    2 +-
 src/{feature-tile.ui => gs-feature-tile.ui}        |    0
 src/{menus.ui => gs-menus.ui}                      |    0
 src/gs-page.c                                      |   28 +
 src/gs-plugin-loader-sync.c                        |    1 -
 src/gs-plugin-loader.c                             |  427 ++--
 src/gs-plugin-loader.h                             |   10 +-
 src/gs-plugin.c                                    |  137 +
 src/gs-plugin.h                                    |   62 +-
 src/gs-popular-tile.c                              |    2 +-
 src/{popular-tile.ui => gs-popular-tile.ui}        |    0
 src/gs-screenshot-image.c                          |   12 +-
 ...{screenshot-image.ui => gs-screenshot-image.ui} |    0
 src/gs-self-test.c                                 |  802 +++----
 src/gs-shell-details.c                             |   34 +-
 src/gs-shell-details.ui                            |    8 +-
 src/gs-shell-extras.c                              |    1 -
 src/gs-shell-installed.c                           |    9 +-
 src/gs-shell-moderate.c                            |    2 +-
 src/gs-shell-search.c                              |    2 +-
 src/gs-shell-updates.c                             |   57 +-
 src/gs-shell.c                                     |    1 +
 src/gs-update-dialog.c                             |   23 +-
 src/gs-update-monitor.c                            |    5 +-
 src/gs-upgrade-banner.c                            |   99 +-
 src/gs-upgrade-banner.h                            |    7 +-
 src/gs-upgrade-banner.ui                           |   20 +-
 src/gs-utils.c                                     |   74 +-
 src/gs-utils.h                                     |    3 +
 src/plugins/Makefile.am                            |   31 +-
 src/plugins/gs-appstream.c                         |   21 +-
 src/{ => plugins}/gs-markdown.c                    |    0
 src/{ => plugins}/gs-markdown.h                    |    0
 src/plugins/gs-plugin-appstream.c                  |  128 +-
 src/plugins/gs-plugin-apt.cc                       |    4 +-
 src/plugins/gs-plugin-dummy.c                      |  447 +++-
 src/plugins/gs-plugin-epiphany.c                   |   52 +-
 src/plugins/gs-plugin-fedora-distro-upgrades.c     |  153 +-
 src/plugins/gs-plugin-fedora-tagger-usage.c        |    4 +
 src/plugins/gs-plugin-fwupd.c                      |   90 +-
 src/plugins/gs-plugin-hardcoded-blacklist.c        |   32 +-
 src/plugins/gs-plugin-hardcoded-featured.c         |    1 +
 src/plugins/gs-plugin-icons.c                      |   51 +-
 src/plugins/gs-plugin-limba.c                      |   70 +-
 src/plugins/gs-plugin-menu-spec-refine.c           |   46 +-
 src/plugins/gs-plugin-moduleset.c                  |    4 +-
 ...s-plugin-xdg-app-reviews.c => gs-plugin-odrs.c} |  198 +-
 src/plugins/gs-plugin-packagekit-history.c         |   15 +-
 src/plugins/gs-plugin-packagekit-offline.c         |    2 +-
 src/plugins/gs-plugin-packagekit-origin.c          |   55 +-
 src/plugins/gs-plugin-packagekit-proxy.c           |   47 +-
 src/plugins/gs-plugin-packagekit-refine.c          |   77 +-
 src/plugins/gs-plugin-packagekit-refresh.c         |  105 +-
 src/plugins/gs-plugin-packagekit.c                 |   98 +-
 src/plugins/gs-plugin-provenance.c                 |   78 +-
 src/plugins/gs-plugin-self-test.c                  |   68 -
 src/plugins/gs-plugin-systemd-updates.c            |   56 +-
 src/plugins/gs-plugin-ubuntu-reviews.c             |   36 +-
 src/plugins/gs-plugin-xdg-app.c                    |  214 +-
 src/plugins/gs-self-test.c                         |  185 ++-
 src/plugins/menu-spec-common.c                     |  354 ++--
 src/plugins/menu-spec-common.h                     |    1 +
 src/plugins/packagekit-common.c                    |   74 +-
 src/plugins/packagekit-common.h                    |    1 +
 91 files changed, 6147 insertions(+), 2744 deletions(-)
---
diff --git a/RELEASE b/RELEASE
index 0cf6b0e..eaf941d 100644
--- a/RELEASE
+++ b/RELEASE
@@ -2,13 +2,13 @@ GNOME Software Release Notes
 
 1. Write release entries:
 
-git log --format="%s" GNOME_SOFTWARE_3_20_0.. | grep -i -v trivial | grep -v Merge | sort | uniq
+git log --format="%s" GNOME_SOFTWARE_3_20_1.. | grep -i -v trivial | grep -v Merge | sort | uniq
 Add any user visible changes into data/appdata/org.gnome.Software.appdata.xml.in
 
 3. Commit changes in gnome-software git:
 
-git commit -a -m "Release version 3.20.1"
-git tag -s GNOME_SOFTWARE_3_20_1 -m "==== Version 3.20.1 ===="
+git commit -a -m "Release version 3.20.2"
+git tag -s GNOME_SOFTWARE_3_20_2 -m "==== Version 3.20.2 ===="
 <enter password>
 git push --tags
 git push
diff --git a/configure.ac b/configure.ac
index b538a7f..736edb3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 # Copyright (C) 2010-2015 Richard Hughes <richard hughsie com>
 AC_PREREQ(2.63)
 
-AC_INIT([gnome-software],[3.20.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-software])
+AC_INIT([gnome-software],[3.20.2],[http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-software])
 AC_CONFIG_SRCDIR(src)
 AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar serial-tests foreign])
 AC_CONFIG_HEADERS([config.h])
@@ -90,7 +90,7 @@ AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
 AC_ARG_ENABLE(dogtail,
               [AS_HELP_STRING([--enable-dogtail],
                               [test using dogtail [default=yes]])],,
-              enable_dogtail=yes)
+              enable_dogtail=no)
 AM_CONDITIONAL(ENABLE_DOGTAIL, test "$enable_dogtail" != no)
 
 # PackageKit
diff --git a/data/Makefile.am b/data/Makefile.am
index 4158c3c..853fee1 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -23,9 +23,6 @@ dist_resources_DATA =                                 \
        featured-weather.png                            \
        featured-weather-bg.png
 
-generatedresourcesdir = $(datadir)/gnome-software
-generatedresources_DATA = featured.ini
-
 @GSETTINGS_RULES@
 gsettings_SCHEMAS = org.gnome.software.gschema.xml
 
diff --git a/data/appdata/org.gnome.Software.appdata.xml.in b/data/appdata/org.gnome.Software.appdata.xml.in
index 57f49c6..4cc06a8 100644
--- a/data/appdata/org.gnome.Software.appdata.xml.in
+++ b/data/appdata/org.gnome.Software.appdata.xml.in
@@ -30,6 +30,17 @@
    Validate with `appstream-util validate *.appdata.xml`
   -->
   <releases>
+    <release version="3.20.1" date="2016-04-11">
+      <description>
+        <p>This stable release fixes the following bugs:</p>
+        <ul>
+          <li>Do not make the ODRS functionality depend on xdg-app</li>
+          <li>Fix live installing firmware</li>
+          <li>Support unlocking fwupd devices</li>
+        </ul>
+        <p>This release also updates translations.</p>
+      </description>
+    </release>
     <release version="3.20.0" date="2016-03-21">
       <description>
         <p>
diff --git a/doc/kudos.md b/doc/kudos.md
index 4f84efa..bc535d8 100644
--- a/doc/kudos.md
+++ b/doc/kudos.md
@@ -1,33 +1,5 @@
-Star ratings used in Software
-=============================
-
-This document aims to explain the "star rating" given to applications.
-
-Introduction
-------------
-
-GNOME software used to show star ratings as *popularity* next to the application
-using the fedora-tagger application. This wasn't a good idea for several reasons:
-
- * People can't agree on a scale. Is an otherwise flawless application with one
-   translation issue 5 stars or 4? Is a useful computational fluid dynamics
-   application that crashes on startup but can be run manually on the command
-   line 1 star or 3 stars?
-
- * It only worked on Fedora, and there was no real policy on how to share data,
-   or the privacy implications of clicking a star.
-
- * People could *game* the ratings system, for example hardcore KDE users could
-   go through all the GNOME apps and give then one star. We then limited this
-   to only rate applications that you have installed, but it was really a cat
-   and mouse thing.
-
-So, lets go two steps back. What is the rating trying to convey to the user?
-When I look at a star rating, I want to see a proportional number of stars to
-how awesome it is to me. The rest of this blog tries to define **awesomeness**.
-
-Kudos
------
+Kudos used in Software
+======================
 
 As part of the AppStream generation process we explode various parts of the
 distro binary package and try to build metadata by merging various sources
@@ -62,9 +34,6 @@ GNOME Software. These include:
  * `Popular` — lots of people have downloaded this (only available on Fedora)
  * `RecentRelease` — there been an upstream release in the last year
 
-When added together, the number of stars will correspond roughly to the number
-of kudos the application has.
-
 You can verify the kudos your application is getting by doing something like:
 
     killall gnome-software
@@ -79,7 +48,6 @@ and then navigating to the details for an application you'll see on the console:
     kudo:            featured-recommended
     kudo:            has-screenshots
     kudo:            popular
-    kudo-percentage: 60
 
 Manually Adding Kudos
 ---------------------
@@ -94,11 +62,11 @@ To do this, just add something like:
     </kudos>
 
 Although, please bear in mind any application that is found cheating, i.e.
-adding kudos artificially just to get a higher star rating will have **all** the
-kudos manually removed with a blacklist rule in the AppStream builder.
+adding kudos artificially will have **all** the kudos manually removed
+with a blacklist rule in the AppStream builder.
 
 If you are a vendor, or a system distributor and just want to increase the
-number of stars for your pet proprietary application that's essential to
+number of kudos for your pet proprietary application that's essential to
 business function, a good kudo to manually add would be `FeaturedRecommended`,
 although, perhaps adding the desktop ID to the GSettings key
 `org.gnome.software.popular-overrides` would be a better idea.
diff --git a/po/LINGUAS b/po/LINGUAS
index cf12825..07e8ca0 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -14,6 +14,7 @@ es
 eu
 fi
 fr
+fur
 ga
 gd
 gl
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9aa136f..256342d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2,8 +2,8 @@
 # Please keep this file sorted alphabetically.
 data/appdata/org.gnome.Software.appdata.xml.in
 data/org.gnome.software.gschema.xml
-[type: gettext/glade]src/app-folder-dialog.ui
-[type: gettext/glade]src/app-tile.ui
+[type: gettext/glade]src/gs-app-folder-dialog.ui
+[type: gettext/glade]src/gs-app-tile.ui
 src/gnome-software-local-file.desktop.in
 [type: gettext/glade]src/gnome-software.ui
 src/gs-app-addon-row.c
@@ -55,15 +55,10 @@ src/gs-update-monitor.c
 src/gs-upgrade-banner.c
 [type: gettext/glade]src/gs-upgrade-banner.ui
 src/gs-utils.c
-[type: gettext/glade]src/menus.ui
+[type: gettext/glade]src/gs-menus.ui
 src/org.gnome.Software.desktop.in
-src/plugins/gs-plugin-appstream.c
-src/plugins/gs-plugin-epiphany.c
-src/plugins/gs-plugin-moduleset.c
-src/plugins/gs-plugin-packagekit.c
-src/plugins/gs-plugin-packagekit-refine.c
 src/plugins/gs-ubuntuone-dialog.c
 [type: gettext/glade]src/plugins/gs-ubuntuone-dialog.ui
 src/plugins/gs-plugin-snappy.c
 src/plugins/menu-spec-common.c
-[type: gettext/glade]src/popular-tile.ui
+[type: gettext/glade]src/gs-popular-tile.ui
diff --git a/po/fur.po b/po/fur.po
new file mode 100644
index 0000000..97ca66e
--- /dev/null
+++ b/po/fur.po
@@ -0,0 +1,2814 @@
+# Friulian translation for gnome-software.
+# Copyright (C) 2016 gnome-software's COPYRIGHT HOLDER
+# This file is distributed under the same license as the gnome-software package.
+# Fabio Tomat <f t public gmail com>, 2016.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gnome-software gnome-3-20\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-";
+"software&keywords=I18N+L10N&component=general\n"
+"POT-Creation-Date: 2016-04-15 12:56+0000\n"
+"PO-Revision-Date: 2016-04-18 22:53+0200\n"
+"Language-Team: Friulian <fur li org>\n"
+"Language: fur\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Last-Translator: Fabio Tomat <f t public gmail com>\n"
+"X-Generator: Poedit 1.8.5\n"
+
+#: ../data/appdata/org.gnome.Software.appdata.xml.in.h:1
+msgid "GNOME Software"
+msgstr "Software di GNOME"
+
+#: ../data/appdata/org.gnome.Software.appdata.xml.in.h:2
+msgid "Application manager for GNOME"
+msgstr "Gjestôr di aplicazions par GNOME"
+
+#: ../data/appdata/org.gnome.Software.appdata.xml.in.h:3
+msgid ""
+"Software allows you to find and install new applications and system "
+"extensions and remove existing installed applications."
+msgstr ""
+"Software al permet di cjatâ e instalâ gnovis aplicazions e estensions di "
+"sisteme e gjavâ aplicazions esistentis."
+
+#: ../data/appdata/org.gnome.Software.appdata.xml.in.h:4
+msgid ""
+"GNOME Software showcases featured and popular applications with useful "
+"descriptions and multiple screenshots per application. Applications can be "
+"found either through browsing the list of categories or by searching. It also "
+"allows you to update your system using an offline update."
+msgstr ""
+"GNOME Software al met in evidence te bacheche lis aplicazions popolârs cun "
+"descrizions utilis e tantis caturis di schermi par ogni aplicazion. Lis "
+"aplicazions a puedin jessi cjatadis sedial esplorant la liste des categoriis "
+"sedial doprant la ricercje. Al permet ancje di inzornâ il sisteme doprant un "
+"inzornament fûr rêt."
+
+#: ../data/org.gnome.software.gschema.xml.h:1
+msgid "A list of compatible projects"
+msgstr "Une liste di progjets compatibii"
+
+#: ../data/org.gnome.software.gschema.xml.h:2
+msgid ""
+"This is a list of compatible projects we should show such as GNOME, KDE and "
+"XFCE."
+msgstr ""
+"Cheste e je une liste di progjets compatibii che si varessin di mostrâ, come "
+"GNOME, KDE e XFCE."
+
+#: ../data/org.gnome.software.gschema.xml.h:3
+msgid "Whether to automatically download updates"
+msgstr "Indiche se discjariâ in automatic i inzornaments"
+
+#: ../data/org.gnome.software.gschema.xml.h:4
+msgid ""
+"If enabled, GNOME Software automatically downloads updates in the background "
+"and prompts the user to install them when ready."
+msgstr ""
+"Se abilitât, GNOME Software al discjarie in automatic i inzornaments in "
+"secont plan e al domande al utent di instalâju cuant che a son pronts."
+
+#: ../data/org.gnome.software.gschema.xml.h:5
+msgid "Whether it's the very first run of GNOME Software"
+msgstr "Indiche se e je la prime volte che si eseguìs GNOME Software"
+
+#: ../data/org.gnome.software.gschema.xml.h:6
+msgid "Show star ratings next to applications"
+msgstr "Mostre lis stelutis di valutazion in bande des aplicazions"
+
+#: ../data/org.gnome.software.gschema.xml.h:7
+msgid "Non-free applications show a warning dialog before install"
+msgstr ""
+"Prime di instalâlis, lis aplicazions no libaris a mostraran un dialic di "
+"avertiment"
+
+#: ../data/org.gnome.software.gschema.xml.h:8
+msgid ""
+"When non-free applications are installed a warning dialog can be shown. This "
+"controls if that dialog is suppressed."
+msgstr ""
+"Cuant che lis aplicazions no libaris a vegnin instalâts un dialic di "
+"avertiment al pues jessi mostrât. Chest al verifiche se chel barcon al è "
+"soprès."
+
+#: ../data/org.gnome.software.gschema.xml.h:9
+msgid "A list of popular applications"
+msgstr "Une liste di aplicazions popolârs"
+
+#: ../data/org.gnome.software.gschema.xml.h:10
+msgid "A list of applications to use, overriding the system defined ones."
+msgstr ""
+"Une liste di aplicazions di doprâ, passant parsore a chês definidis di "
+"sisteme."
+
+#: ../data/org.gnome.software.gschema.xml.h:11
+msgid "The list of extra sources that have been previously enabled"
+msgstr ""
+"La liste di sorzints suplementârs che a son stadis abilitadis tal imprin"
+
+#: ../data/org.gnome.software.gschema.xml.h:12
+msgid ""
+"The list of sources that have been previously enabled when installing third-"
+"party applications."
+msgstr ""
+"La liste di sorzints che a son stadis abilitadis tal imprin cuant che si "
+"instalave lis aplicazions di tiercis parts."
+
+#: ../data/org.gnome.software.gschema.xml.h:13
+msgid "The last update check timestamp"
+msgstr "La date dal control dal ultin inzornament"
+
+#: ../data/org.gnome.software.gschema.xml.h:14
+msgid "The timestamp of the first security update, cleared after update"
+msgstr "La date dal prin inzornament di sigurece, netât dopo l'inzornament"
+
+#: ../data/org.gnome.software.gschema.xml.h:15
+msgid "The last update timestamp"
+msgstr "La date dal ultin inzornament"
+
+#: ../data/org.gnome.software.gschema.xml.h:16
+msgid "The server to use for application reviews"
+msgstr "Il servidôr di doprâ pes recensions des aplicazions"
+
+#: ../data/org.gnome.software.gschema.xml.h:17
+msgid "The minimum karma score for reviews"
+msgstr "I ponts minims di karma pes recensions"
+
+#: ../data/org.gnome.software.gschema.xml.h:18
+msgid "Reviews with karma less than this number will not be shown."
+msgstr "Recensions cun karma inferiôr a chest numar no vegnaran mostradis."
+
+#: ../data/org.gnome.software.gschema.xml.h:19
+msgid "A list of official sources that should not be considered 3rd party"
+msgstr ""
+"Une liste di sorzints uficiâi che no varessin di jessi consideradis di "
+"tiercis parts"
+
+#: ../src/gs-app-folder-dialog.ui.h:1
+msgid "Add to Application Folder"
+msgstr "Zonte ae cartele aplicazions"
+
+#: ../src/gs-app-folder-dialog.ui.h:2 ../src/gs-app-folder-dialog.c:316
+#: ../src/gs-review-dialog.ui.h:3 ../src/gs-shell-details.c:305
+#: ../src/gs-shell-installed.c:514 ../src/gs-upgrade-banner.ui.h:4
+msgid "_Cancel"
+msgstr "_Anule"
+
+#: ../src/gs-app-folder-dialog.ui.h:3 ../src/gs-app-folder-dialog.c:321
+msgid "_Add"
+msgstr "_Zonte"
+
+#. TRANSLATORS: this is the small blue label on the tile
+#. * that tells the user the application is installed
+#: ../src/gs-app-tile.ui.h:1 ../src/gs-app-addon-row.c:97
+#: ../src/gs-app-tile.c:78 ../src/gs-app-tile.c:81 ../src/gs-feature-tile.c:68
+#: ../src/gs-popular-tile.c:74 ../src/gs-popular-tile.c:77
+#: ../src/gs-popular-tile.ui.h:1
+msgid "Installed"
+msgstr "Instalât"
+
+#: ../src/gnome-software-local-file.desktop.in.h:1
+msgid "Software Install"
+msgstr "Instale software"
+
+#: ../src/gnome-software-local-file.desktop.in.h:2
+msgid "Install selected software on the system"
+msgstr "Instale il software selezionât tal sisteme"
+
+#: ../src/gnome-software.ui.h:1
+msgid "Select All"
+msgstr "Selezione dut"
+
+#: ../src/gnome-software.ui.h:2
+msgid "Select None"
+msgstr "Nissune selezion"
+
+#. TRANSLATORS: this is the application name
+#. set the window title back to default
+#. TRANSLATORS: this is the main window title
+#: ../src/gnome-software.ui.h:3 ../src/gs-application.c:374
+#: ../src/gs-shell.c:253 ../src/org.gnome.Software.desktop.in.h:1
+msgid "Software"
+msgstr "Software"
+
+#. vim: set noexpandtab:
+#: ../src/gnome-software.ui.h:4 ../src/gs-sources-dialog.ui.h:2
+#: ../src/gs-update-dialog.ui.h:1
+msgid "Go back"
+msgstr "Torne indaûr"
+
+#. Translators: A label for a button to show all available software.
+#: ../src/gnome-software.ui.h:6
+msgid "_All"
+msgstr "_Dut"
+
+#. Translators: A label for a button to show only software which is already installed.
+#: ../src/gnome-software.ui.h:8
+msgid "_Installed"
+msgstr "_Instalât"
+
+#. Translators: A label for a button to show only updates which are available to install.
+#: ../src/gnome-software.ui.h:10
+msgid "_Updates"
+msgstr "_Inzornaments"
+
+#. TRANSLATORS: this is a label that describes an application
+#. * that has been queued for installation
+#: ../src/gs-app-addon-row.c:91 ../src/gs-app-row.c:266
+#: ../src/gs-shell-details.ui.h:4
+msgid "Pending"
+msgstr "In spiete"
+
+#. TRANSLATORS: this is a button next to the search results that
+#. * shows the status of an application being installed
+#. TRANSLATORS: this is the small blue label on the tile
+#. * that tells the user the application is being installed
+#: ../src/gs-app-addon-row.c:101 ../src/gs-app-row.c:304
+#: ../src/gs-app-tile.c:87 ../src/gs-app-tile.c:90
+msgid "Installing"
+msgstr "Instalazion"
+
+#. TRANSLATORS: this is a button next to the search results that
+#. * shows the status of an application being erased
+#. TRANSLATORS: this is the small blue label on the tile
+#. * that tells the user the application is being removed
+#: ../src/gs-app-addon-row.c:105 ../src/gs-app-row.c:313
+#: ../src/gs-app-tile.c:96 ../src/gs-app-tile.c:99
+msgid "Removing"
+msgstr "Rimozion"
+
+#. TRANSLATORS: This is how we join the licenses and can
+#. * be considered a "Conjunctive AND Operator" according
+#. * to the SPDX specification. For example:
+#. * "LGPL-2.1 and MIT and BSD-2-Clause"
+#. TRANSLATORS: separator for a list of items
+#: ../src/gs-app.c:1345 ../src/gs-shell-extras.c:145
+msgid " and "
+msgstr " e "
+
+#. TRANSLATORS: This is how we join the licenses and can
+#. * be considered a "Disjunctive OR Operator" according
+#. * to the SPDX specification. For example:
+#. * "LGPL-2.1 or MIT"
+#: ../src/gs-app.c:1353
+msgid " or "
+msgstr " o "
+
+#. TRANSLATORS: non-free app
+#: ../src/gs-app.c:1376
+msgid "Proprietary"
+msgstr "Proprietarie"
+
+#. TRANSLATORS: see the wikipedia page
+#: ../src/gs-app.c:1386
+msgid "Public domain"
+msgstr "Domini public"
+
+#: ../src/gs-app-folder-dialog.c:305
+msgid "Folder Name"
+msgstr "Non de cartele"
+
+#. TRANSLATORS: this is a command line option
+#: ../src/gs-application.c:97
+msgid "Start up mode: either ‘updates’, ‘updated’, ‘installed’ or ‘overview’"
+msgstr ""
+"Modalitât di inviament: al pues jessi ‘updates’, ‘updated’, ‘installed’ o "
+"‘overview’"
+
+#: ../src/gs-application.c:97
+msgid "MODE"
+msgstr "MODALITÂT"
+
+#: ../src/gs-application.c:99
+msgid "Search for applications"
+msgstr "Cîr aplicazions"
+
+#: ../src/gs-application.c:99
+msgid "SEARCH"
+msgstr "CÎR"
+
+#: ../src/gs-application.c:101
+msgid "Show application details"
+msgstr "Mostre detais aplicazions"
+
+#: ../src/gs-application.c:101
+msgid "ID"
+msgstr "ID"
+
+#: ../src/gs-application.c:103
+msgid "Open a local package file"
+msgstr "Vierç un file di pachet locâl"
+
+#: ../src/gs-application.c:103
+msgid "FILENAME"
+msgstr "NONFILE"
+
+#: ../src/gs-application.c:105
+msgid "Show verbose debugging information"
+msgstr "Mostre informazion detaiadis di debug"
+
+#: ../src/gs-application.c:107
+msgid "Show profiling information for the service"
+msgstr "Mostre lis informazions dal profîl pal servizi"
+
+#: ../src/gs-application.c:109
+msgid "Prefer local file sources to AppStream"
+msgstr "Preferìs lis sorzints di file locâi par AppStream"
+
+#: ../src/gs-application.c:111
+msgid "Show version number"
+msgstr "Mostre il numar di version"
+
+#: ../src/gs-application.c:367
+msgid "translator-credits"
+msgstr "Fabio Tomat <f t public gmail com>"
+
+#. TRANSLATORS: this is the title of the about window
+#: ../src/gs-application.c:371
+msgid "About Software"
+msgstr "Informazions su Software"
+
+#. TRANSLATORS: well, we seem to think so, anyway
+#: ../src/gs-application.c:377
+msgid "A nice way to manage the software on your system."
+msgstr "Un biel mût di ministrâ il software sul sisteme."
+
+#. TRANSLATORS: during the update the device
+#. * will restart into a special update-only mode
+#: ../src/gs-app-row.c:152
+msgid "Device cannot be used during update."
+msgstr "Il dispositîf nol pues jessi doprât intant che si inzorne."
+
+#. TRANSLATORS: this is a button next to the search results that
+#. * allows the application to be easily installed
+#: ../src/gs-app-row.c:250
+msgid "Visit website"
+msgstr "Visite il sît web"
+
+#. TRANSLATORS: this is a button next to the search results that
+#. * allows the application to be easily installed.
+#. * The ellipsis indicates that further steps are required
+#: ../src/gs-app-row.c:255
+msgid "Install…"
+msgstr "Instale..."
+
+#. TRANSLATORS: this is a button next to the search results that
+#. * allows to cancel a queued install of the application
+#: ../src/gs-app-row.c:263
+msgid "Cancel"
+msgstr "Anule"
+
+#. TRANSLATORS: this is a button next to the search results that
+#. * allows the application to be easily installed
+#. TRANSLATORS: this is a button in the updates panel
+#. * that allows the app to be easily updated live
+#. TRANSLATORS: this is button text to update the firware
+#. TRANSLATORS: button text
+#: ../src/gs-app-row.c:273 ../src/gs-app-row.c:280 ../src/gs-page.c:254
+#: ../src/gs-utils.c:317
+msgid "Install"
+msgstr "Instale"
+
+#. TRANSLATORS: this is a button next to the search results that
+#. * allows the application to be easily removed
+#. TRANSLATORS: this is button text to remove the application
+#: ../src/gs-app-row.c:284 ../src/gs-app-row.c:295 ../src/gs-page.c:322
+msgid "Remove"
+msgstr "Gjave"
+
+#. vim: set noexpandtab:
+#. This is shown in the search result row as a tag
+#: ../src/gs-app-row.ui.h:2 ../src/gs-shell-details.ui.h:31
+msgid "3rd party"
+msgstr "tiercis parts"
+
+#. This is shown in the search result row as a tag
+#: ../src/gs-app-row.ui.h:4 ../src/gs-shell-details.ui.h:32
+msgid "web app"
+msgstr "Aplicazion web"
+
+#. This is shown in the search result row as a tag
+#: ../src/gs-app-row.ui.h:6
+msgid "nonfree"
+msgstr "no libare"
+
+#. TRANSLATORS: this is where all applications that don't
+#. * fit in other groups are put
+#: ../src/gs-category.c:235
+msgid "Other"
+msgstr "Altri"
+
+#. TRANSLATORS: this is a subcategory matching all the
+#. * different apps in the parent category, e.g. "Games"
+#: ../src/gs-category.c:239
+msgid "All"
+msgstr "Dutis"
+
+#. TRANSLATORS: this is a subcategory of featured apps
+#: ../src/gs-category.c:242
+msgid "Featured"
+msgstr "In risalt"
+
+#. TRANSLATORS: this is a what we use in notifications if the app's name is unknown
+#: ../src/gs-dbus-helper.c:307
+msgid "An application"
+msgstr "Une aplicazion"
+
+#. TRANSLATORS: this is a notification displayed when an app needs additional MIME types.
+#: ../src/gs-dbus-helper.c:313
+#, c-format
+msgid "%s is requesting additional file format support."
+msgstr "%s al domande supuart pal formât di file adizionâl."
+
+#. TRANSLATORS: notification title
+#: ../src/gs-dbus-helper.c:315
+msgid "Additional MIME Types Required"
+msgstr "Gjenar di MIME adizionâi domandâts"
+
+#. TRANSLATORS: this is a notification displayed when an app needs additional fonts.
+#: ../src/gs-dbus-helper.c:319
+#, c-format
+msgid "%s is requesting additional fonts."
+msgstr "%s al domande caratars in plui."
+
+#. TRANSLATORS: notification title
+#: ../src/gs-dbus-helper.c:321
+msgid "Additional Fonts Required"
+msgstr "Caratars in plui domandâts"
+
+#. TRANSLATORS: this is a notification displayed when an app needs additional codecs.
+#: ../src/gs-dbus-helper.c:325
+#, c-format
+msgid "%s is requesting additional multimedia codecs."
+msgstr "%s al domande codec multimediâi in plui."
+
+#. TRANSLATORS: notification title
+#: ../src/gs-dbus-helper.c:327
+msgid "Additional Multimedia Codecs Required"
+msgstr "Codec multimediâi in plui domandâts"
+
+#. TRANSLATORS: this is a notification displayed when an app needs additional printer drivers.
+#: ../src/gs-dbus-helper.c:331
+#, c-format
+msgid "%s is requesting additional printer drivers."
+msgstr "%s al domande driver di stampant adizionâi."
+
+#. TRANSLATORS: notification title
+#: ../src/gs-dbus-helper.c:333
+msgid "Additional Printer Drivers Required"
+msgstr "Driver di stampant adizionâi domandâts"
+
+#. TRANSLATORS: this is a notification displayed when an app wants to install additional packages.
+#: ../src/gs-dbus-helper.c:337
+#, c-format
+msgid "%s is requesting additional packages."
+msgstr "%s al domande pachets in plui."
+
+#. TRANSLATORS: notification title
+#: ../src/gs-dbus-helper.c:339
+msgid "Additional Packages Required"
+msgstr "Pachets adizionâi domandâts"
+
+#. TRANSLATORS: this is a button that launches gnome-software
+#: ../src/gs-dbus-helper.c:348
+msgid "Find in Software"
+msgstr "Cjate in Software"
+
+#. vim: set noexpandtab:
+#: ../src/gs-first-run-dialog.ui.h:1
+msgid "Welcome"
+msgstr "Benvignûts"
+
+#: ../src/gs-first-run-dialog.ui.h:2
+msgid "Welcome to Software"
+msgstr "Benvignûts a Software"
+
+#: ../src/gs-first-run-dialog.ui.h:3
+msgid ""
+"Software lets you install all the software you need, all from one place. See "
+"our recommendations, browse the categories, or search for the applications "
+"you want."
+msgstr ""
+"Software ti fâs instalâ ducj i software che ti coventin, dut di un puest sôl. "
+"Bute un voli ai nestris conseis, esplore lis categoriis o cîr lis aplicazions "
+"che tu desideris."
+
+#: ../src/gs-first-run-dialog.ui.h:4
+msgid "_Let’s Go Shopping"
+msgstr "_Nin a fâ compris"
+
+#. TRANSLATORS: Here are 2 strings the same as in gtk/gtkbox.c
+#. in GTK+ project. Please use the same translation.
+#: ../src/gs-hiding-box.c:384
+msgid "Spacing"
+msgstr ""
+
+#: ../src/gs-hiding-box.c:385
+msgid "The amount of space between children"
+msgstr "La cuantitât di spazi tra i fîs"
+
+#. TRANSLATORS: this is the status in the history UI,
+#. * where we are showing the application was removed
+#: ../src/gs-history-dialog.c:83
+msgctxt "app status"
+msgid "Removed"
+msgstr "Gjavade"
+
+#. TRANSLATORS: this is the status in the history UI,
+#. * where we are showing the application was installed
+#: ../src/gs-history-dialog.c:89
+msgctxt "app status"
+msgid "Installed"
+msgstr "Instalade"
+
+#. TRANSLATORS: this is the status in the history UI,
+#. * where we are showing the application was updated
+#: ../src/gs-history-dialog.c:95
+msgctxt "app status"
+msgid "Updated"
+msgstr "Inzornade"
+
+#. TRANSLATORS: this is the status in the history UI,
+#. * where we are showing that something happened to the
+#. * application but we don't know what
+#: ../src/gs-history-dialog.c:101
+msgctxt "app status"
+msgid "Unknown"
+msgstr "No cognossude"
+
+#. vim: set noexpandtab:
+#: ../src/gs-history-dialog.ui.h:1
+msgid "History"
+msgstr "Cronologjie"
+
+#. TRANSLATORS: this is a prompt message, and
+#. * '%s' is an application summary, e.g. 'GNOME Clocks'
+#: ../src/gs-page.c:248
+#, c-format
+msgid "Prepare %s"
+msgstr "Preparâ %s"
+
+#. TRANSLATORS: this is a prompt message, and
+#. * '%s' is an application summary, e.g. 'GNOME Clocks'
+#: ../src/gs-page.c:313
+#, c-format
+msgid "Are you sure you want to remove %s?"
+msgstr "Sigûrs di gjavâ %s?"
+
+#. TRANSLATORS: longer dialog text
+#: ../src/gs-page.c:318
+#, c-format
+msgid "%s will be removed, and you will have to install it to use it again."
+msgstr "%s e vegnarà gjavade e par podêle doprâ di gnûf tu varâs di instalâle."
+
+#. TRANSLATORS: this is a group of updates that are not
+#. * packages and are not shown in the main list
+#: ../src/gs-plugin-loader.c:718
+msgid "OS Updates"
+msgstr "Inzornament dal SO"
+
+#. TRANSLATORS: this is a longer description of the
+#. * "OS Updates" string
+#: ../src/gs-plugin-loader.c:723
+msgid "Includes performance, stability and security improvements."
+msgstr "Al inclût mioraments di prestazion, stabilitât e sigurece."
+
+#. TRANSLATORS: this is when we know about an application or
+#. * addon, but it can't be listed for some reason
+#: ../src/gs-plugin-loader.c:1449 ../src/gs-shell-extras.c:386
+#, c-format
+msgid "No addon codecs are available for the %s format."
+msgstr "Nol è disponibil nissun codec pal formât %s."
+
+#: ../src/gs-plugin-loader.c:1452
+#, c-format
+msgid ""
+"Information about %s, as well as options for how to get a codec that can play "
+"this format can be found on the website."
+msgstr ""
+"Lis informazions su %s, cussì come lis opzions su ce mût otignî un codec par "
+"podê riprodusi chest formât, a puedin jessi cjatadis sul sît web."
+
+#. TRANSLATORS: lighthearted star rating description;
+#. *           A really bad application
+#: ../src/gs-review-dialog.c:93
+msgid "Hate it"
+msgstr "La odei"
+
+#. TRANSLATORS: lighthearted star rating description;
+#. *           Not a great application
+#: ../src/gs-review-dialog.c:97
+msgid "Don't like it"
+msgstr "No mi plâs"
+
+#. TRANSLATORS: lighthearted star rating description;
+#. *           A fairly-good application
+#: ../src/gs-review-dialog.c:101
+msgid "It's OK"
+msgstr "E je buine"
+
+#. TRANSLATORS: lighthearted star rating description;
+#. *           A good application
+#: ../src/gs-review-dialog.c:105
+msgid "Like it"
+msgstr "Mi plâs"
+
+#. TRANSLATORS: lighthearted star rating description;
+#. *           A really awesome application
+#: ../src/gs-review-dialog.c:109
+msgid "Love it"
+msgstr "Le adori"
+
+#. TRANSLATORS: the review can't just be copied and pasted
+#: ../src/gs-review-dialog.c:131
+msgid "Please take more time writing the review"
+msgstr "Cjapiti plui timp par scrivi une opinion"
+
+#. TRANSLATORS: the review is not acceptable
+#: ../src/gs-review-dialog.c:135
+msgid "Please choose a star rating"
+msgstr "Sielç une stele come valutazion"
+
+#. TRANSLATORS: the review is not acceptable
+#: ../src/gs-review-dialog.c:139
+msgid "The summary is too short"
+msgstr "Il struc al è masse curt"
+
+#. TRANSLATORS: the review is not acceptable
+#: ../src/gs-review-dialog.c:143
+msgid "The summary is too long"
+msgstr "Il struc al è masse lunc"
+
+#. TRANSLATORS: the review is not acceptable
+#: ../src/gs-review-dialog.c:147
+msgid "The description is too short"
+msgstr "La descrizion e je masse curte"
+
+#. TRANSLATORS: the review is not acceptable
+#: ../src/gs-review-dialog.c:151
+msgid "The description is too long"
+msgstr "La descrizion e je masse lungje"
+
+#. vim: set noexpandtab:
+#. Translators: Title of the dialog box where the users can write and publish their opinions about the apps.
+#: ../src/gs-review-dialog.ui.h:2
+msgid "Post Review"
+msgstr "Publiche recension"
+
+#. Translators: A button to publish the user's opinion about the app.
+#: ../src/gs-review-dialog.ui.h:5
+msgid "_Post"
+msgstr "_Publiche"
+
+#: ../src/gs-review-dialog.ui.h:6
+msgid "Rating"
+msgstr "Valutazion"
+
+#: ../src/gs-review-dialog.ui.h:7
+msgid "Summary"
+msgstr "Struc"
+
+#: ../src/gs-review-dialog.ui.h:8
+msgid ""
+"Give a short summary of your review, for example: “Great app, would "
+"recommend”."
+msgstr ""
+"Fâs un curt struc de tô recension, par esempli: \"Maraveose aplicazion, "
+"conseade\"."
+
+#. Translators: This is where the users enter their opinions about the apps.
+#: ../src/gs-review-dialog.ui.h:10
+msgctxt "app review"
+msgid "Review"
+msgstr "Recension"
+
+#: ../src/gs-review-dialog.ui.h:11
+msgid "What do you think of the app? Try to give reasons for your views."
+msgstr "Ce pensitu de aplicazion? Cîr di dâ motîfs aes tôs opinions."
+
+#: ../src/gs-review-histogram.ui.h:1
+msgid "Total"
+msgstr "Totâl"
+
+#. TRANSLATORS: we explain what the action is going to do
+#: ../src/gs-review-row.c:207
+msgid "You can report reviews for abusive, rude, or discriminatory behavior."
+msgstr ""
+"Al è pussibil segnalâ recensions compuartament ofensîf, maleducât o "
+"discriminatori."
+
+#. TRANSLATORS: we ask the user if they really want to do this
+#: ../src/gs-review-row.c:212
+msgid ""
+"Once reported, a review will be hidden until it has been checked by an "
+"administrator."
+msgstr ""
+"Une volte segnalade, une recension no vegnarà mostrade fintant che un "
+"aministradôr no le varà controlade."
+
+#. TRANSLATORS: window title when
+#. * reporting a user-submitted review
+#. * for moderation
+#: ../src/gs-review-row.c:226
+msgid "Report Review?"
+msgstr "Segnalâ recension?"
+
+#. TRANSLATORS: button text when
+#. * sending a review for moderation
+#: ../src/gs-review-row.c:230
+msgid "Report"
+msgstr "Segnale"
+
+#. vim: set noexpandtab:
+#. Translators: Users can express their opinions about other users' opinions about the apps.
+#: ../src/gs-review-row.ui.h:2
+msgid "Was this review useful to you?"
+msgstr "La recension ise stade utile?"
+
+#: ../src/gs-review-row.ui.h:3
+msgid "Yes"
+msgstr "Sì"
+
+#: ../src/gs-review-row.ui.h:4
+msgid "No"
+msgstr "No"
+
+#. Translators: Button text for indifference, only used when moderating
+#: ../src/gs-review-row.ui.h:6
+msgid "Meh"
+msgstr "Mah"
+
+#: ../src/gs-review-row.ui.h:7
+msgid "Report…"
+msgstr "Segnale..."
+
+#: ../src/gs-review-row.ui.h:8
+msgid "Remove…"
+msgstr "Gjave..."
+
+#. TRANSLATORS: this is when we try to download a screenshot and
+#. * we get back 404
+#: ../src/gs-screenshot-image.c:232
+msgid "Screenshot not found"
+msgstr "Cature di schermi no cjatade"
+
+#. TRANSLATORS: possibly image file corrupt or not an image
+#: ../src/gs-screenshot-image.c:248
+msgid "Failed to load image"
+msgstr "Cjariament de imagjin falît"
+
+#. TRANSLATORS: this is when we request a screenshot size that
+#. * the generator did not create or the parser did not add
+#: ../src/gs-screenshot-image.c:379
+msgid "Screenshot size not found"
+msgstr "Dimension de cature di schermi no cjatade"
+
+#. TRANSLATORS: this is when we try create the cache directory
+#. * but we were out of space or permission was denied
+#: ../src/gs-screenshot-image.c:405
+msgid "Could not create cache"
+msgstr "Impussibil cjariâ la cache"
+
+#. TRANSLATORS: this is when we try to download a screenshot
+#. * that was not a valid URL
+#: ../src/gs-screenshot-image.c:433
+msgid "Screenshot not valid"
+msgstr "Cature di schermi no valide"
+
+#. TRANSLATORS: this is when networking is not available
+#: ../src/gs-screenshot-image.c:449
+msgid "Screenshot not available"
+msgstr "Cature di schermi no disponibile"
+
+#: ../src/gs-screenshot-image.c:500
+msgid "Screenshot"
+msgstr "Cature"
+
+#. vim: set noexpandtab:
+#: ../src/gs-shell-category.ui.h:1
+msgid ""
+"Extensions are used at your own risk. If you have any system problems, it is "
+"recommended to disable them."
+msgstr ""
+"Lis estensions a son dopradis cun to pericul. Se tu âs cualsisei probleme di "
+"sisteme, al è conseât di disabilitâlis."
+
+#: ../src/gs-shell-category.ui.h:2
+msgid "Extension Settings"
+msgstr "Impostazions estensions"
+
+#. TRANSLATORS: button text in the header when an application
+#. * can be installed
+#. TRANSLATORS: button text in the header when firmware
+#. * can be live-installed
+#. TRANSLATORS: button text in the header when an application
+#. * can be live-updated
+#: ../src/gs-shell-details.c:201 ../src/gs-shell-details.c:227
+#: ../src/gs-shell-details.c:232 ../src/gs-shell-details.ui.h:2
+#: ../src/gs-upgrade-banner.ui.h:5
+msgid "_Install"
+msgstr "_Instale"
+
+#. TRANSLATORS: button text in the header when an application
+#. * is in the process of being installed
+#: ../src/gs-shell-details.c:212
+msgid "_Installing"
+msgstr "_Instalazion"
+
+#. TRANSLATORS: this is a button that allows the apps to
+#. * be installed.
+#. * The ellipsis indicates that further steps are required,
+#. * e.g. enabling software sources or the like
+#: ../src/gs-shell-details.c:245
+msgid "_Install…"
+msgstr "_Instale..."
+
+#. TRANSLATORS: button text in the header when an application can be erased
+#: ../src/gs-shell-details.c:292 ../src/gs-shell-details.ui.h:3
+msgid "_Remove"
+msgstr "_Gjave"
+
+#. TRANSLATORS: button text in the header when an application can be installed
+#: ../src/gs-shell-details.c:299
+msgid "_Removing"
+msgstr "_Rimozion"
+
+#. TRANSLATORS: this is where the license is not known
+#: ../src/gs-shell-details.c:669
+msgctxt "license"
+msgid "Unknown"
+msgstr "No cognossude"
+
+#. TRANSLATORS: this is where the version is not known
+#: ../src/gs-shell-details.c:682
+msgctxt "version"
+msgid "Unknown"
+msgstr "No cognossude"
+
+#. TRANSLATORS: this is where the size is being worked out
+#: ../src/gs-shell-details.c:688
+msgctxt "size"
+msgid "Calculating…"
+msgstr "Calcul in vore..."
+
+#. TRANSLATORS: this is where the size is not known
+#: ../src/gs-shell-details.c:691
+msgctxt "size"
+msgid "Unknown"
+msgstr "No cognossude"
+
+#. TRANSLATORS: this is where the updated date is not known
+#: ../src/gs-shell-details.c:703
+msgctxt "updated"
+msgid "Never"
+msgstr "Mai"
+
+#. TRANSLATORS: this is the application isn't in any
+#. * defined menu category
+#: ../src/gs-shell-details.c:717
+msgctxt "menu category"
+msgid "None"
+msgstr "Nissune"
+
+#. TRANSLATORS: this is where we don't know the origin of the
+#. * application
+#: ../src/gs-shell-details.c:734
+msgctxt "origin"
+msgid "Unknown"
+msgstr "No cognossude"
+
+#. TRANSLATORS: this is the warning box
+#: ../src/gs-shell-details.c:780
+msgid ""
+"This application can only be used when there is an active internet connection."
+msgstr ""
+"Cheste aplicazion e pues jessi doprade nome cuant che e je ative une "
+"conession internet."
+
+#. TRANSLATORS: this is the warning box
+#: ../src/gs-shell-details.c:791
+msgid "This software comes from a 3rd party."
+msgstr "Chest software al ven di tiercis parts."
+
+#. TRANSLATORS: this is the warning box
+#: ../src/gs-shell-details.c:800
+msgid ""
+"This software comes from a 3rd party and may contain non-free components."
+msgstr ""
+"Chest software al ven di une tierce part e e podarès contignî components no "
+"libars."
+
+#. TRANSLATORS: this is the warning box
+#: ../src/gs-shell-details.c:809
+msgid "This software may contain non-free components."
+msgstr "Chest software al podarès contignî components no libars."
+
+#: ../src/gs-shell-details.c:1135
+#, c-format
+msgid "Could not find '%s'"
+msgstr "Impussibil cjatâ '%s'"
+
+#: ../src/gs-shell-details.c:1195 ../src/gs-utils.c:166
+msgid "Sorry, this did not work"
+msgstr "Chest nol à funzionât"
+
+#. vim: set noexpandtab:
+#: ../src/gs-shell-details.ui.h:1
+msgid "Details page"
+msgstr "Pagjine di detais"
+
+#. Translators: A label for a button to execute the selected application.
+#: ../src/gs-shell-details.ui.h:6
+msgid "_Launch"
+msgstr "_Invie"
+
+#: ../src/gs-shell-details.ui.h:7
+msgid "Software Source Included"
+msgstr "Sorzint software includude"
+
+#: ../src/gs-shell-details.ui.h:8
+msgid ""
+"This application includes a software source which provides updates, as well "
+"as access to other software."
+msgstr ""
+"Cheste aplicazion e inclût une sorzint software che e furnìs inzornaments, "
+"cussì ancje l'acès a altri software."
+
+#: ../src/gs-shell-details.ui.h:9
+msgid "No Software Source Included"
+msgstr "Nissune sorzint software includude"
+
+#: ../src/gs-shell-details.ui.h:10
+msgid ""
+"This application does not include a software source. It will not be updated "
+"with new versions."
+msgstr ""
+"Cheste aplicazion no inclût une sorzint software. No vegnarà inzornade cun "
+"gnovis versions."
+
+#: ../src/gs-shell-details.ui.h:11
+msgid ""
+"This software is already provided by your distribution and should not be "
+"replaced."
+msgstr ""
+"Chest software al è za furnît de tô distribuzion e no varès di jessi "
+"sostituide."
+
+#. Translators: a repository file used for installing software has been discovered.
+#: ../src/gs-shell-details.ui.h:13
+msgid "Software Source Identified"
+msgstr "Sorzint software identificade"
+
+#: ../src/gs-shell-details.ui.h:14
+msgid ""
+"Adding this software source will give you access to additional software and "
+"upgrades."
+msgstr ""
+"Zontant cheste sorzint software tu varâs acès a software in plui e "
+"inzornaments."
+
+#: ../src/gs-shell-details.ui.h:15
+msgid "Only use software sources that you trust."
+msgstr "Dopre nome lis sorzints software che tu ti fidis."
+
+#: ../src/gs-shell-details.ui.h:16
+msgid "_Website"
+msgstr "Sît _web"
+
+#: ../src/gs-shell-details.ui.h:17
+msgid "_History"
+msgstr "_Cronologjie"
+
+#: ../src/gs-shell-details.ui.h:18 ../src/gs-update-monitor.c:557
+msgid "Details"
+msgstr "Detais"
+
+#: ../src/gs-shell-details.ui.h:19
+msgid "Localized in your Language"
+msgstr "Localizade te tô lenghe"
+
+#: ../src/gs-shell-details.ui.h:20
+msgid "Documentation"
+msgstr "Documentazion"
+
+#: ../src/gs-shell-details.ui.h:21
+msgid "Release Activity"
+msgstr "Ativitât di publicazion"
+
+#: ../src/gs-shell-details.ui.h:22
+msgid "System Integration"
+msgstr "Integrazion tal sisteme"
+
+#: ../src/gs-shell-details.ui.h:23 ../src/gs-sources-dialog.ui.h:8
+msgid "Version"
+msgstr "Version"
+
+#: ../src/gs-shell-details.ui.h:24
+msgid "Updated"
+msgstr "Inzornade"
+
+#: ../src/gs-shell-details.ui.h:25
+msgid "Category"
+msgstr "Categorie"
+
+#: ../src/gs-shell-details.ui.h:26
+msgid "Size"
+msgstr "Dimension"
+
+#: ../src/gs-shell-details.ui.h:27
+msgid "Source"
+msgstr "Sorzint"
+
+#: ../src/gs-shell-details.ui.h:28
+msgid "Developer"
+msgstr "Svilupadôr"
+
+#: ../src/gs-shell-details.ui.h:29
+msgid "License"
+msgstr "Licence"
+
+#: ../src/gs-shell-details.ui.h:30
+msgid "non-free"
+msgstr "no libare"
+
+#. TRANSLATORS: This is the header dividing the normal
+#. * applications and the addons
+#. TRANSLATORS: this is the main category for Add-ons
+#: ../src/gs-shell-details.ui.h:33 ../src/gs-shell-installed.c:432
+#: ../src/gs-update-list.c:129 ../src/plugins/menu-spec-common.c:210
+msgid "Add-ons"
+msgstr "Estensions"
+
+#: ../src/gs-shell-details.ui.h:34
+msgid "Selected add-ons will be installed with the application."
+msgstr "Lis estensions selezionadis a vegnaran instaladis cun la aplicazion."
+
+#. Translators: Header of the section with other users' opinions about the app.
+#: ../src/gs-shell-details.ui.h:36
+msgid "Reviews"
+msgstr "Recensions"
+
+#. Translators: Button opening a dialog where the users can write and publish their opinions about the apps.
+#: ../src/gs-shell-details.ui.h:38
+msgid "_Write a Review"
+msgstr "_Scrîf une recension"
+
+#. Translators: Button to return more application-submitted reviews.
+#: ../src/gs-shell-details.ui.h:40
+msgid "_Show More"
+msgstr "_Mostre altris"
+
+#. TRANSLATORS: separator for a list of items
+#: ../src/gs-shell-extras.c:148
+msgid ", "
+msgstr ", "
+
+#. TRANSLATORS: Application window title for fonts installation.
+#. %s will be replaced by name of the script we're searching for.
+#: ../src/gs-shell-extras.c:174
+#, c-format
+msgid "Available fonts for the %s script"
+msgid_plural "Available fonts for the %s scripts"
+msgstr[0] "Caratars disponibii pal script %s"
+msgstr[1] "Caratars disponibii pai script %s"
+
+#. TRANSLATORS: Application window title for codec installation.
+#. %s will be replaced by actual codec name(s)
+#: ../src/gs-shell-extras.c:182
+#, c-format
+msgid "Available software for %s"
+msgid_plural "Available software for %s"
+msgstr[0] "Software disponibil par %s"
+msgstr[1] "Software disponibii par %s"
+
+#: ../src/gs-shell-extras.c:224
+msgid "Unable to Find Requested Software"
+msgstr "Impussibil cjatâ il software domandât"
+
+#. TRANSLATORS: This string is used for codecs that weren't found
+#: ../src/gs-shell-extras.c:320
+#, c-format
+msgid "%s not found"
+msgstr "%s no cjatât"
+
+#. TRANSLATORS: hyperlink title
+#: ../src/gs-shell-extras.c:324
+msgid "on the website"
+msgstr "tal sît web"
+
+#. TRANSLATORS: this is when we know about an application or
+#. * addon, but it can't be listed for some reason
+#: ../src/gs-shell-extras.c:331
+#, c-format
+msgid "No applications are available that provide the file %s."
+msgstr "No je nissune aplicazion disponibile che e furnìs il file %s."
+
+#. TRANSLATORS: first %s is the codec name, and second %s is a
+#. * hyperlink with the "on the website" text
+#: ../src/gs-shell-extras.c:335 ../src/gs-shell-extras.c:346
+#: ../src/gs-shell-extras.c:357
+#, c-format
+msgid ""
+"Information about %s, as well as options for how to get missing applications "
+"might be found %s."
+msgstr ""
+"Lis informazion su %s, e cussì ancje lis opzions su ce mût vê lis aplicazions "
+"che a mancjin, a podaressin jessi cjatadis su %s."
+
+#. TRANSLATORS: this is when we know about an application or
+#. * addon, but it can't be listed for some reason
+#: ../src/gs-shell-extras.c:342 ../src/gs-shell-extras.c:364
+#, c-format
+msgid "No applications are available for %s support."
+msgstr "No je nissune aplicazion disponibile pal supuart di %s."
+
+#. TRANSLATORS: this is when we know about an application or
+#. * addon, but it can't be listed for some reason
+#: ../src/gs-shell-extras.c:353
+#, c-format
+msgid "%s is not available."
+msgstr "%s no je disponibile."
+
+#. TRANSLATORS: first %s is the codec name, and second %s is a
+#. * hyperlink with the "on the website" text
+#: ../src/gs-shell-extras.c:368
+#, c-format
+msgid ""
+"Information about %s, as well as options for how to get an application that "
+"can support this format might be found %s."
+msgstr ""
+"Lis informazion su %s, e cussì ancje lis opzions su ce mût vê une aplicazion "
+"che e supuarte chest formât, a podaressin jessi cjatadis su %s."
+
+#. TRANSLATORS: this is when we know about an application or
+#. * addon, but it can't be listed for some reason
+#: ../src/gs-shell-extras.c:375
+#, c-format
+msgid "No fonts are available for the %s script support."
+msgstr "No son disponibii caratars pal supuart dal script %s."
+
+#. TRANSLATORS: first %s is the codec name, and second %s is a
+#. * hyperlink with the "on the website" text
+#: ../src/gs-shell-extras.c:379
+#, c-format
+msgid ""
+"Information about %s, as well as options for how to get additional fonts "
+"might be found %s."
+msgstr ""
+"Lis informazion su %s, e cussì ancje lis opzions su ce mût vê caratars in "
+"plui, a podaressin jessi cjatadis su %s."
+
+#. TRANSLATORS: first %s is the codec name, and second %s is a
+#. * hyperlink with the "on the website" text
+#: ../src/gs-shell-extras.c:390
+#, c-format
+msgid ""
+"Information about %s, as well as options for how to get a codec that can play "
+"this format might be found %s."
+msgstr ""
+"Lis informazion su %s, e cussì ancje lis opzions su ce mût otignî un codec "
+"che al pues riprodusi chest formât, a podaressin jessi cjatadis su %s."
+
+#. TRANSLATORS: this is when we know about an application or
+#. * addon, but it can't be listed for some reason
+#: ../src/gs-shell-extras.c:397
+#, c-format
+msgid "No Plasma resources are available for %s support."
+msgstr "No je nissune risorse Plasma disponibil pal supuart di %s."
+
+#. TRANSLATORS: first %s is the codec name, and second %s is a
+#. * hyperlink with the "on the website" text
+#: ../src/gs-shell-extras.c:401
+#, c-format
+msgid ""
+"Information about %s, as well as options for how to get additional Plasma "
+"resources might be found %s."
+msgstr ""
+"Lis informazion su %s, e cussì ancje lis opzions su ce mût vê risorsis Plasma "
+"in plui, a podaressin jessi cjatadis su %s."
+
+#. TRANSLATORS: this is when we know about an application or
+#. * addon, but it can't be listed for some reason
+#: ../src/gs-shell-extras.c:408
+#, c-format
+msgid "No printer drivers are available for %s."
+msgstr "Nissun driver di stampant disponibil par %s."
+
+#. TRANSLATORS: first %s is the codec name, and second %s is a
+#. * hyperlink with the "on the website" text
+#: ../src/gs-shell-extras.c:412
+#, c-format
+msgid ""
+"Information about %s, as well as options for how to get a driver that "
+"supports this printer might be found %s."
+msgstr ""
+"Lis informazion su %s, e cussì ancje lis opzions su ce mût otignî un driver "
+"che al supuarte cheste stampant, a podaressin jessi cjatadis su %s."
+
+#: ../src/gs-shell-extras.c:458
+msgid "this website"
+msgstr "chest sît web"
+
+#. TRANSLATORS: no codecs were found. First %s will be replaced by actual codec name(s), second %s is a link 
titled "this website"
+#: ../src/gs-shell-extras.c:462
+#, c-format
+msgid ""
+"Unfortunately, the %s you were searching for could not be found. Please see "
+"%s for more information."
+msgid_plural ""
+"Unfortunately, the %s you were searching for could not be found. Please see "
+"%s for more information."
+msgstr[0] ""
+"Par sfortune, si stave cirint %s e nol è stât pussibil cjatâlu. Consultâ %s "
+"par vê plui informazions."
+msgstr[1] ""
+"Par sfortune, si stave cirint %s e nol è stât pussibil cjatâju. Consultâ %s "
+"par vê plui informazions."
+
+#: ../src/gs-shell-extras.c:542 ../src/gs-shell-extras.c:590
+#: ../src/gs-shell-extras.c:640
+msgid "Failed to find any search results"
+msgstr "Impussibil cjatâ risultâts de ricercje"
+
+#: ../src/gs-shell-extras.c:809
+#, c-format
+msgid "%s file format"
+msgstr "Formât di file %s"
+
+#. vim: set noexpandtab:
+#: ../src/gs-shell-extras.ui.h:1
+msgid "Codecs page"
+msgstr "Pagjine dai codec"
+
+#. TRANSLATORS: This is the header dividing the normal
+#. * applications and the system ones
+#: ../src/gs-shell-installed.c:422
+msgid "System Applications"
+msgstr "Aplicazions di sisteme"
+
+#: ../src/gs-shell-installed.c:522
+msgid "Click on items to select them"
+msgstr "Fâs clic sui elements par selezionâju"
+
+#: ../src/gs-shell-installed.c:713
+msgid "Select"
+msgstr "Selezione"
+
+#. vim: set noexpandtab:
+#: ../src/gs-shell-installed.ui.h:1
+msgid "Installed page"
+msgstr "Pagjine instalade"
+
+#: ../src/gs-shell-installed.ui.h:2
+msgid "_Add to Folder…"
+msgstr "_Zonte ae cartele..."
+
+#: ../src/gs-shell-installed.ui.h:3
+msgid "_Move to Folder…"
+msgstr "_Sposte te cartele..."
+
+#: ../src/gs-shell-installed.ui.h:4
+msgid "_Remove from Folder"
+msgstr "_Gjave de cartele"
+
+#: ../src/gs-shell-moderate.ui.h:1
+msgid "Moderate page"
+msgstr "Moderâ pagjine"
+
+#: ../src/gs-shell-moderate.ui.h:2
+msgid "There are no reviews to moderate"
+msgstr "No son recensions di moderâ"
+
+#. TRANSLATORS: this is a heading for audio applications which have been featured ('recommended') by the 
distribution
+#: ../src/gs-shell-overview.c:367
+msgid "Recommended Audio Applications"
+msgstr "Aplicazions audio conseadis"
+
+#. TRANSLATORS: this is a heading for games which have been featured ('recommended') by the distribution
+#: ../src/gs-shell-overview.c:372
+msgid "Recommended Games"
+msgstr "Zûcs conseâts"
+
+#. TRANSLATORS: this is a heading for graphics applications which have been featured ('recommended') by the 
distribution
+#: ../src/gs-shell-overview.c:377
+msgid "Recommended Graphics Applications"
+msgstr "Aplicazions di grafiche conseadis"
+
+#. TRANSLATORS: this is a heading for office applications which have been featured ('recommended') by the 
distribution
+#: ../src/gs-shell-overview.c:382
+msgid "Recommended Office Applications"
+msgstr "Aplicazions di ufici conseadis"
+
+#. vim: set noexpandtab:
+#: ../src/gs-shell-overview.ui.h:1
+msgid "Overview page"
+msgstr "Pagjine panoramiche"
+
+#: ../src/gs-shell-overview.ui.h:2
+msgid "Featured Application"
+msgstr "Aplicazions in risalt"
+
+#. Translators: This is a heading for software which has been featured ('picked') by the distribution.
+#: ../src/gs-shell-overview.ui.h:4
+msgid "Editor's Picks"
+msgstr "Selezionadis di noaltris"
+
+#: ../src/gs-shell-overview.ui.h:5
+msgid "Categories"
+msgstr "Categoriis"
+
+#: ../src/gs-shell-overview.ui.h:6
+msgid "No Application Data Found"
+msgstr "Dâts de aplicazion no cjatâts"
+
+#. vim: set noexpandtab:
+#: ../src/gs-shell-search.ui.h:1
+msgid "Search page"
+msgstr "Pagjine di ricercje"
+
+#: ../src/gs-shell-search.ui.h:2
+msgid "No Application Found"
+msgstr "Nissune aplicazion cjatade"
+
+#. TRANSLATORS: Time in 24h format
+#: ../src/gs-shell-updates.c:153
+msgid "%R"
+msgstr "%R"
+
+#. TRANSLATORS: Time in 12h format
+#: ../src/gs-shell-updates.c:156
+msgid "%l:%M %p"
+msgstr "%l:%M %p"
+
+#. TRANSLATORS: This is the word "Yesterday" followed by a
+#. time string in 24h format. i.e. "Yesterday, 14:30"
+#: ../src/gs-shell-updates.c:162
+msgid "Yesterday, %R"
+msgstr "Îr, %R"
+
+#. TRANSLATORS: This is the word "Yesterday" followed by a
+#. time string in 12h format. i.e. "Yesterday, 2:30 PM"
+#: ../src/gs-shell-updates.c:166
+msgid "Yesterday, %l:%M %p"
+msgstr "Îr, %l:%M %p"
+
+#: ../src/gs-shell-updates.c:169
+msgid "Two days ago"
+msgstr "Doi dîs indaûr"
+
+#: ../src/gs-shell-updates.c:171
+msgid "Three days ago"
+msgstr "Trê dîs indaûr"
+
+#: ../src/gs-shell-updates.c:173
+msgid "Four days ago"
+msgstr "Cuatri dîs indaûr"
+
+#: ../src/gs-shell-updates.c:175
+msgid "Five days ago"
+msgstr "Cinc dîs indaûr"
+
+#: ../src/gs-shell-updates.c:177
+msgid "Six days ago"
+msgstr "Sîs dîs indaûr"
+
+#: ../src/gs-shell-updates.c:179
+msgid "One week ago"
+msgstr "Une setemane indaûr"
+
+#: ../src/gs-shell-updates.c:181
+msgid "Two weeks ago"
+msgstr "Dôs setemanis indaûr"
+
+#. TRANSLATORS: This is the date string with: day number, month name, year.
+#. i.e. "25 May 2012"
+#: ../src/gs-shell-updates.c:185
+msgid "%e %B %Y"
+msgstr "%e di %B dal %Y"
+
+#. TRANSLATORS: the updates are being downloaded
+#: ../src/gs-shell-updates.c:201
+msgid "Downloading new updates…"
+msgstr "Daûr a discjariâ i gnûfs inzornaments..."
+
+#. TRANSLATORS: the update panel is doing *something* vague
+#: ../src/gs-shell-updates.c:205
+msgid "Looking for new updates…"
+msgstr "Daûr a cirî gnûfs inzornaments..."
+
+#. TRANSLATORS: the updates panel is starting up
+#: ../src/gs-shell-updates.c:246
+msgid "Setting up updates…"
+msgstr "Daûr a configurâ i inzornaments..."
+
+#. TRANSLATORS: the updates panel is starting up
+#: ../src/gs-shell-updates.c:247 ../src/gs-shell-updates.c:254
+msgid "(This could take a while)"
+msgstr "(Al podarès tirâle a dilunc)"
+
+#. TRANSLATORS: This is the time when we last checked for updates
+#: ../src/gs-shell-updates.c:421
+#, c-format
+msgid "Last checked: %s"
+msgstr "Ultin control: %s"
+
+#. TRANSLATORS: this is to explain that downloading updates may cost money
+#: ../src/gs-shell-updates.c:826
+msgid "Charges may apply"
+msgstr "Tu podaressis spindi bêçs"
+
+#. TRANSLATORS: we need network
+#. * to do the updates check
+#: ../src/gs-shell-updates.c:830
+msgid ""
+"Checking for updates while using mobile broadband could cause you to incur "
+"charges."
+msgstr ""
+"Controlâ inzornaments doprant la bande largje mobil al podarès fâti spindi "
+"bêçs."
+
+#. TRANSLATORS: this is a link to the
+#. * control-center network panel
+#: ../src/gs-shell-updates.c:834
+msgid "Check Anyway"
+msgstr "Controle distès"
+
+#. TRANSLATORS: can't do updates check
+#: ../src/gs-shell-updates.c:850
+msgid "No Network"
+msgstr "Nissune rêt"
+
+#. TRANSLATORS: we need network
+#. * to do the updates check
+#: ../src/gs-shell-updates.c:854
+msgid "Internet access is required to check for updates."
+msgstr "L'acès a internet al è necessari par controlâ i inzornaments."
+
+#. TRANSLATORS: this is a link to the
+#. * control-center network panel
+#: ../src/gs-shell-updates.c:858
+msgid "Network Settings"
+msgstr "Impostazions di rêt"
+
+#: ../src/gs-shell-updates.c:1192
+msgid "Restart & _Install"
+msgstr "Torne invie e _instale"
+
+#: ../src/gs-shell-updates.c:1209
+msgid "Check for updates"
+msgstr "Control inzornaments"
+
+#. vim: set noexpandtab:
+#: ../src/gs-shell-updates.ui.h:1
+msgid "Updates page"
+msgstr "Pagjine inzornaments"
+
+#: ../src/gs-shell-updates.ui.h:2
+msgid "Other Updates"
+msgstr "Altris inzornaments"
+
+#: ../src/gs-shell-updates.ui.h:3
+msgid "Software is up to date"
+msgstr "Il software al è inzornât"
+
+#: ../src/gs-shell-updates.ui.h:4
+msgid ""
+"Checking for updates when using mobile broadband could cause you to incur "
+"charges"
+msgstr ""
+"Controlâ i inzornaments intant che si dopre la bande largje mobil a podarès "
+"causâ spesis in plui"
+
+#: ../src/gs-shell-updates.ui.h:5
+msgid "_Check Anyway"
+msgstr "_Controle distès"
+
+#: ../src/gs-shell-updates.ui.h:6
+msgid "Go online to check for updates"
+msgstr "Va in rêt par controlâ i inzornaments"
+
+#: ../src/gs-shell-updates.ui.h:7
+msgid "_Network Settings"
+msgstr "Impostazions di _rêt"
+
+#: ../src/gs-shell-updates.ui.h:8
+msgid "Updates are automatically managed"
+msgstr "I inzornaments a son gjestîts in automatic"
+
+#. TRANSLATORS: This string describes a software source that
+#. has no software installed from it.
+#: ../src/gs-sources-dialog.c:94
+msgid "No applications or addons installed; other software might still be"
+msgstr ""
+"Nissune aplicazion o estension instalade; al è pussibil che lu sedi altri "
+"software"
+
+#. TRANSLATORS: This string is used to construct the 'X applications
+#. installed' sentence, describing a software source.
+#: ../src/gs-sources-dialog.c:98
+#, c-format
+msgid "%i application installed"
+msgid_plural "%i applications installed"
+msgstr[0] "%i aplicazion instalade"
+msgstr[1] "%i aplicazions instaladis"
+
+#. TRANSLATORS: This string is used to construct the 'X add-ons
+#. installed' sentence, describing a software source.
+#: ../src/gs-sources-dialog.c:104
+#, c-format
+msgid "%i add-on installed"
+msgid_plural "%i add-ons installed"
+msgstr[0] "%i estension instalade"
+msgstr[1] "%i estensions instaladis"
+
+#. TRANSLATORS: This string is used to construct the 'X applications
+#. and y add-ons installed' sentence, describing a software source.
+#. The correct form here depends on the number of applications.
+#: ../src/gs-sources-dialog.c:111
+#, c-format
+msgid "%i application"
+msgid_plural "%i applications"
+msgstr[0] "%i aplicazion"
+msgstr[1] "%i aplicazions"
+
+#. TRANSLATORS: This string is used to construct the 'X applications
+#. and y add-ons installed' sentence, describing a software source.
+#. The correct form here depends on the number of add-ons.
+#: ../src/gs-sources-dialog.c:117
+#, c-format
+msgid "%i add-on"
+msgid_plural "%i add-ons"
+msgstr[0] "%i estension"
+msgstr[1] "%i estensions"
+
+#. TRANSLATORS: This string is used to construct the 'X applications
+#. and y add-ons installed' sentence, describing a software source.
+#. The correct form here depends on the total number of
+#. applications and add-ons.
+#: ../src/gs-sources-dialog.c:124
+#, c-format
+msgid "%s and %s installed"
+msgid_plural "%s and %s installed"
+msgstr[0] "%s e %s instaladis"
+msgstr[1] "%s e %s instaladis"
+
+#: ../src/gs-sources-dialog.c:322 ../src/gs-sources-dialog.ui.h:12
+msgid "Remove Source"
+msgstr "Gjave sorzint"
+
+#: ../src/gs-sources-dialog.c:336
+msgid "Removing…"
+msgstr "Daûr a gjavâ..."
+
+#. TRANSLATORS: this is the fallback text we use if we can't
+#. figure out the name of the operating system
+#: ../src/gs-sources-dialog.c:402
+msgid "the operating system"
+msgstr "il sisteme operatîf"
+
+#. TRANSLATORS: This is the text displayed in the Software Sources
+#. dialog when no OS-provided software sources are enabled. %s gets
+#. replaced by the name of the actual distro, e.g. Fedora.
+#: ../src/gs-sources-dialog.c:473
+#, c-format
+msgid ""
+"Software sources can be downloaded from the internet. They give you access to "
+"additional software that is not provided by %s."
+msgstr ""
+"Lis sorzints software a puedin jessi scjariadis di internet. A ti puedin ufrî "
+"l'acès a software adizionâi che no son furnîts di %s."
+
+#. vim: set noexpandtab:
+#: ../src/gs-sources-dialog.ui.h:1
+msgid "Software Sources"
+msgstr "Sorzints software"
+
+#: ../src/gs-sources-dialog.ui.h:3
+msgid "Software sources give you access to additional software."
+msgstr "Lis sorzints software ti furnissin l'acès a software adizionâi."
+
+#: ../src/gs-sources-dialog.ui.h:4
+msgid ""
+"Removing a source will also remove any software you have installed from it."
+msgstr ""
+"Gjavant une sorzint tu gjavarâs ancje ducj i software che tu âs instalât di "
+"jê."
+
+#: ../src/gs-sources-dialog.ui.h:5
+msgid "No software installed from this source"
+msgstr "Nissun software instalât di cheste sorzint"
+
+#: ../src/gs-sources-dialog.ui.h:6
+msgid "Installed from this Source"
+msgstr "Instalât di cheste sorzint"
+
+#: ../src/gs-sources-dialog.ui.h:7
+msgid "Source Details"
+msgstr "Detais sorzint"
+
+#: ../src/gs-sources-dialog.ui.h:9
+msgid "Last Checked"
+msgstr "Ultin control"
+
+#: ../src/gs-sources-dialog.ui.h:10
+msgid "Added"
+msgstr "Zontade"
+
+#: ../src/gs-sources-dialog.ui.h:11
+msgid "Website"
+msgstr "Sît web"
+
+#: ../src/gs-star-widget.ui.h:1
+msgid "One Star"
+msgstr "Une stele"
+
+#: ../src/gs-star-widget.ui.h:2
+msgid "Two Stars"
+msgstr "Dôs stelis"
+
+#: ../src/gs-star-widget.ui.h:3
+msgid "Three Stars"
+msgstr "Trê stelis"
+
+#: ../src/gs-star-widget.ui.h:4
+msgid "Four Stars"
+msgstr "Cuatri stelis"
+
+#: ../src/gs-star-widget.ui.h:5
+msgid "Five Stars"
+msgstr "Cinc stelis"
+
+#. TRANSLATORS: this is where the packager did not write
+#. * a description for the update
+#: ../src/gs-update-dialog.c:121
+msgid "No update description available."
+msgstr ""
+
+#. TRANSLATORS: this is the subtitle of the installed updates dialog window.
+#. %s will be replaced by the date when the updates were installed.
+#. The date format is defined by the locale's preferred date representation
+#. ("%x" in strftime.)
+#: ../src/gs-update-dialog.c:215
+#, c-format
+msgid "Installed on %s"
+msgstr ""
+
+#. TRANSLATORS: this is the title of the installed updates dialog window
+#: ../src/gs-update-dialog.c:235
+msgid "Installed Updates"
+msgstr ""
+
+#: ../src/gs-update-dialog.ui.h:2
+msgid "No updates have been installed on this system."
+msgstr ""
+
+#: ../src/gs-update-monitor.c:89
+msgid "Security Updates Pending"
+msgstr ""
+
+#: ../src/gs-update-monitor.c:90
+msgid "It is recommended that you install important updates now"
+msgstr ""
+
+#: ../src/gs-update-monitor.c:93
+msgid "Restart & Install"
+msgstr ""
+
+#: ../src/gs-update-monitor.c:97
+msgid "Software Updates Available"
+msgstr ""
+
+#: ../src/gs-update-monitor.c:98
+msgid "Important OS and application updates are ready to be installed"
+msgstr ""
+
+#: ../src/gs-update-monitor.c:101
+msgid "Not Now"
+msgstr ""
+
+#: ../src/gs-update-monitor.c:102
+msgid "View"
+msgstr ""
+
+#. TRANSLATORS: this is a distro upgrade, the replacement would be the
+#. * distro name, e.g. 'Fedora'
+#: ../src/gs-update-monitor.c:230
+#, c-format
+msgid "A new version of %s is available to install"
+msgstr ""
+
+#. TRANSLATORS: this is a distro upgrade
+#: ../src/gs-update-monitor.c:234
+msgid "Software Upgrade Available"
+msgstr ""
+
+#. TRANSLATORS: title when we offline updates have failed
+#: ../src/gs-update-monitor.c:429
+msgid "Software Updates Failed"
+msgstr ""
+
+#. TRANSLATORS: message when we offline updates have failed
+#: ../src/gs-update-monitor.c:431
+msgid "An important OS update failed to be installed."
+msgstr ""
+
+#: ../src/gs-update-monitor.c:433
+msgid "Show Details"
+msgstr ""
+
+#. TRANSLATORS: title when we've done offline updates
+#: ../src/gs-update-monitor.c:448
+msgid "Software Update Installed"
+msgid_plural "Software Updates Installed"
+msgstr[0] ""
+msgstr[1] ""
+
+#. TRANSLATORS: message when we've done offline updates
+#: ../src/gs-update-monitor.c:452
+msgid "An important OS update has been installed."
+msgid_plural "Important OS updates have been installed."
+msgstr[0] ""
+msgstr[1] ""
+
+#. TRANSLATORS: Button to look at the updates that were installed.
+#. * Note that it has nothing to do with the application reviews, the
+#. * users can't express their opinions here. In some languages
+#. * "Review (evaluate) something" is a different translation than
+#. * "Review (browse) something."
+#: ../src/gs-update-monitor.c:463
+msgctxt "updates"
+msgid "Review"
+msgstr ""
+
+#. TRANSLATORS: these are show_detailed_error messages from the
+#. * package manager no mortal is supposed to understand,
+#. * but google might know what they mean
+#: ../src/gs-update-monitor.c:538
+msgid "Detailed errors from the package manager follow:"
+msgstr ""
+
+#. TRANSLATORS: this is when the offline update failed
+#: ../src/gs-update-monitor.c:599
+msgid "Failed To Update"
+msgstr ""
+
+#. TRANSLATORS: the user must have updated manually after
+#. * the updates were prepared
+#: ../src/gs-update-monitor.c:605
+msgid "The system was already up to date."
+msgstr ""
+
+#. TRANSLATORS: the user aborted the update manually
+#: ../src/gs-update-monitor.c:610
+msgid "The update was cancelled."
+msgstr ""
+
+#. TRANSLATORS: the package manager needed to download
+#. * something with no network available
+#: ../src/gs-update-monitor.c:616
+msgid ""
+"Internet access was required but wasn’t available. Please make sure that you "
+"have internet access and try again."
+msgstr ""
+
+#. TRANSLATORS: if the package is not signed correctly
+#: ../src/gs-update-monitor.c:622
+msgid ""
+"There were security issues with the update. Please consult your software "
+"provider for more details."
+msgstr ""
+
+#. TRANSLATORS: we ran out of disk space
+#: ../src/gs-update-monitor.c:628
+msgid "There wasn’t enough disk space. Please free up some space and try again."
+msgstr ""
+
+#. TRANSLATORS: We didn't handle the error type
+#: ../src/gs-update-monitor.c:633
+msgid ""
+"We’re sorry: the update failed to install. Please wait for another update and "
+"try again. If the problem persists, contact your software provider."
+msgstr ""
+
+#. TRANSLATORS: This is the text displayed when a distro
+#. * upgrade is available. First %s is the distro name and the
+#. * 2nd %s is the version, e.g. "Fedora 23 Now Available"
+#: ../src/gs-upgrade-banner.c:83
+#, c-format
+msgid "%s %s Now Available"
+msgstr ""
+
+#. TRANSLATORS: This is the text displayed while downloading a
+#. * distro upgrade. First %s is the distro name and the 2nd %s
+#. * is the version, e.g. "Downloading Fedora 23"
+#: ../src/gs-upgrade-banner.c:93
+#, c-format
+msgid "Downloading %s %s"
+msgstr ""
+
+#. TRANSLATORS: This is the text displayed when a distro
+#. * upgrade has been downloaded and is ready to be installed.
+#. * First %s is the distro name and the 2nd %s is the version,
+#. * e.g. "Fedora 23 Ready to be Installed"
+#: ../src/gs-upgrade-banner.c:104
+#, c-format
+msgid "%s %s Ready to be Installed"
+msgstr ""
+
+#. vim: set noexpandtab:
+#: ../src/gs-upgrade-banner.ui.h:1
+msgid "A major upgrade, with new features and added polish."
+msgstr ""
+
+#: ../src/gs-upgrade-banner.ui.h:2
+msgid "_Learn More"
+msgstr ""
+
+#: ../src/gs-upgrade-banner.ui.h:3
+msgid "_Download"
+msgstr ""
+
+#: ../src/gs-upgrade-banner.ui.h:6
+msgid "It is recommended that you back up your data and files before upgrading."
+msgstr ""
+
+#. TRANSLATORS: this is the summary of a notification that an application
+#. * has been successfully installed
+#: ../src/gs-utils.c:140
+#, c-format
+msgid "%s is now installed"
+msgstr ""
+
+#. TRANSLATORS: this is button that opens the newly installed application
+#: ../src/gs-utils.c:144
+msgid "Launch"
+msgstr ""
+
+#. TRANSLATORS: this is when the install fails
+#: ../src/gs-utils.c:170
+#, c-format
+msgid "Installation of %s failed."
+msgstr ""
+
+#. TRANSLATORS: this is when the remove fails
+#: ../src/gs-utils.c:175
+#, c-format
+msgid "Removal of %s failed."
+msgstr ""
+
+#. TRANSLATORS: window title
+#: ../src/gs-utils.c:248
+msgid "Install Third-Party Software?"
+msgstr ""
+
+#. TRANSLATORS: window title
+#: ../src/gs-utils.c:252
+msgid "Enable Third-Party Software Source?"
+msgstr ""
+
+#. TRANSLATORS: the replacements are as follows:
+#. * 1. Application name, e.g. "Firefox"
+#. * 2. Software source name, e.g. fedora-optional
+#.
+#: ../src/gs-utils.c:270
+#, c-format
+msgid ""
+"%s is not <a href=\"https://en.wikipedia.org/wiki/Free_and_open-";
+"source_software\">free and open source software</a>, and is provided by “%s”."
+msgstr ""
+
+#. TRANSLATORS: the replacements are as follows:
+#. * 1. Application name, e.g. "Firefox"
+#. * 2. Software source name, e.g. fedora-optional
+#: ../src/gs-utils.c:280
+#, c-format
+msgid "%s is provided by “%s”."
+msgstr ""
+
+#. TRANSLATORS: a software source is a repo
+#: ../src/gs-utils.c:290
+msgid "This software source must be enabled to continue installation."
+msgstr ""
+
+#. TRANSLATORS: Laws are geographical, urgh...
+#: ../src/gs-utils.c:300
+#, c-format
+msgid "It may be illegal to install or use %s in some countries."
+msgstr ""
+
+#. TRANSLATORS: Laws are geographical, urgh...
+#: ../src/gs-utils.c:306
+msgid "It may be illegal to install or use this codec in some countries."
+msgstr ""
+
+#. TRANSLATORS: this is button text to not ask about non-free content again
+#: ../src/gs-utils.c:313
+msgid "Don't Warn Again"
+msgstr ""
+
+#. TRANSLATORS: button text
+#: ../src/gs-utils.c:322
+msgid "Enable and Install"
+msgstr ""
+
+#. vim: set noexpandtab:
+#: ../src/gs-menus.ui.h:1
+msgid "_Software Sources"
+msgstr ""
+
+#: ../src/gs-menus.ui.h:2
+msgid "_About"
+msgstr ""
+
+#: ../src/gs-menus.ui.h:3
+msgid "_Quit"
+msgstr ""
+
+#: ../src/org.gnome.Software.desktop.in.h:2
+msgid "Add, remove or update software on this computer"
+msgstr ""
+
+#: ../src/org.gnome.Software.desktop.in.h:3
+msgid ""
+"Updates;Upgrade;Sources;Repositories;Preferences;Install;Uninstall;Program;"
+"Software;App;Store;"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for Audio
+#: ../src/plugins/menu-spec-common.c:30
+msgid "Audio"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:31
+msgctxt "Menu subcategory of Audio"
+msgid "Editing"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:32
+msgctxt "Menu subcategory of Audio"
+msgid "Databases"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:33
+msgctxt "Menu subcategory of Audio"
+msgid "Disc Burning"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:34
+msgctxt "Menu subcategory of Audio"
+msgid "Ham Radio"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:35
+msgctxt "Menu subcategory of Audio"
+msgid "MIDI"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:36
+msgctxt "Menu subcategory of Audio"
+msgid "Mixer"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:37
+msgctxt "Menu subcategory of Audio"
+msgid "Music"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:38
+msgctxt "Menu subcategory of Audio"
+msgid "Players"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:39
+msgctxt "Menu subcategory of Audio"
+msgid "Recorders"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:40
+msgctxt "Menu subcategory of Audio"
+msgid "Sequencers"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:41
+msgctxt "Menu subcategory of Audio"
+msgid "Tuners"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for Development
+#: ../src/plugins/menu-spec-common.c:43
+msgid "Development Tools"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:44
+msgctxt "Menu subcategory of Development Tools"
+msgid "Building"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:45
+msgctxt "Menu subcategory of Development Tools"
+msgid "Databases"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:46
+msgctxt "Menu subcategory of Development Tools"
+msgid "Debuggers"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:47
+msgctxt "Menu subcategory of Development Tools"
+msgid "GUI Designers"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:48
+msgctxt "Menu subcategory of Development Tools"
+msgid "IDE"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:49
+msgctxt "Menu subcategory of Development Tools"
+msgid "Profiling"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:50
+msgctxt "Menu subcategory of Development Tools"
+msgid "Project Management"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:51
+msgctxt "Menu subcategory of Development Tools"
+msgid "Revision Control"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:52
+msgctxt "Menu subcategory of Development Tools"
+msgid "Translation"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:53
+msgctxt "Menu subcategory of Development Tools"
+msgid "Web Development"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for Education
+#: ../src/plugins/menu-spec-common.c:55
+msgid "Education"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:56
+msgctxt "Menu subcategory of Education"
+msgid "Art"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:57
+msgctxt "Menu subcategory of Education"
+msgid "Artificial Intelligence"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:58
+msgctxt "Menu subcategory of Education"
+msgid "Astronomy"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:59
+msgctxt "Menu subcategory of Education"
+msgid "Biology"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:60
+msgctxt "Menu subcategory of Education"
+msgid "Chemistry"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:61
+msgctxt "Menu subcategory of Education"
+msgid "Computer Science"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:62
+msgctxt "Menu subcategory of Education"
+msgid "Construction"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:63
+msgctxt "Menu subcategory of Education"
+msgid "Data Visualization"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:64
+msgctxt "Menu subcategory of Education"
+msgid "Economy"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:65
+msgctxt "Menu subcategory of Education"
+msgid "Electricity"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:66
+msgctxt "Menu subcategory of Education"
+msgid "Electronics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:67
+msgctxt "Menu subcategory of Education"
+msgid "Engineering"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:68
+msgctxt "Menu subcategory of Education"
+msgid "Geography"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:69
+msgctxt "Menu subcategory of Education"
+msgid "Geology"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:70
+msgctxt "Menu subcategory of Education"
+msgid "Geoscience"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:71
+msgctxt "Menu subcategory of Education"
+msgid "History"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:72
+msgctxt "Menu subcategory of Education"
+msgid "Humanities"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:73
+msgctxt "Menu subcategory of Education"
+msgid "Image Processing"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:74
+msgctxt "Menu subcategory of Education"
+msgid "Languages"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:75
+msgctxt "Menu subcategory of Education"
+msgid "Literature"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:76
+msgctxt "Menu subcategory of Education"
+msgid "Maps"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:77
+msgctxt "Menu subcategory of Education"
+msgid "Math"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:78
+msgctxt "Menu subcategory of Education"
+msgid "Medical"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:79
+msgctxt "Menu subcategory of Education"
+msgid "Music"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:80
+msgctxt "Menu subcategory of Education"
+msgid "Numerical Analysis"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:81
+msgctxt "Menu subcategory of Education"
+msgid "Parallel Computing"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:82
+msgctxt "Menu subcategory of Education"
+msgid "Physics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:83
+msgctxt "Menu subcategory of Education"
+msgid "Robotics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:84
+msgctxt "Menu subcategory of Education"
+msgid "Spirituality"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:85
+msgctxt "Menu subcategory of Education"
+msgid "Sports"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for Games
+#: ../src/plugins/menu-spec-common.c:87
+msgid "Games"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:88
+msgctxt "Menu subcategory of Games"
+msgid "Action"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:89
+msgctxt "Menu subcategory of Games"
+msgid "Adventure"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:90
+msgctxt "Menu subcategory of Games"
+msgid "Arcade"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:91
+msgctxt "Menu subcategory of Games"
+msgid "Blocks"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:92
+msgctxt "Menu subcategory of Games"
+msgid "Board"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:93
+msgctxt "Menu subcategory of Games"
+msgid "Card"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:94
+msgctxt "Menu subcategory of Games"
+msgid "Emulators"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:95
+msgctxt "Menu subcategory of Games"
+msgid "Kids"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:96
+msgctxt "Menu subcategory of Games"
+msgid "Logic"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:97
+msgctxt "Menu subcategory of Games"
+msgid "Role Playing"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:98
+msgctxt "Menu subcategory of Games"
+msgid "Shooter"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:99
+msgctxt "Menu subcategory of Games"
+msgid "Simulation"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:100
+msgctxt "Menu subcategory of Games"
+msgid "Sports"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:101
+msgctxt "Menu subcategory of Games"
+msgid "Strategy"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for Graphics
+#: ../src/plugins/menu-spec-common.c:103
+msgid "Graphics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:104
+msgctxt "Menu subcategory of Graphics"
+msgid "2D Graphics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:105
+msgctxt "Menu subcategory of Graphics"
+msgid "3D Graphics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:106
+msgctxt "Menu subcategory of Graphics"
+msgid "OCR"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:107
+msgctxt "Menu subcategory of Graphics"
+msgid "Photography"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:108
+msgctxt "Menu subcategory of Graphics"
+msgid "Publishing"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:109
+msgctxt "Menu subcategory of Graphics"
+msgid "Raster Graphics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:110
+msgctxt "Menu subcategory of Graphics"
+msgid "Scanning"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:111
+msgctxt "Menu subcategory of Graphics"
+msgid "Vector Graphics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:112
+msgctxt "Menu subcategory of Graphics"
+msgid "Viewer"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for Network
+#: ../src/plugins/menu-spec-common.c:114
+msgid "Internet"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:115
+msgctxt "Menu subcategory of Internet"
+msgid "Chat"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:116
+msgctxt "Menu subcategory of Internet"
+msgid "Dialup"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:117
+msgctxt "Menu subcategory of Internet"
+msgid "Email"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:118
+msgctxt "Menu subcategory of Internet"
+msgid "Feed"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:119
+msgctxt "Menu subcategory of Internet"
+msgid "File Transfer"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:120
+msgctxt "Menu subcategory of Internet"
+msgid "Ham Radio"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:121
+msgctxt "Menu subcategory of Internet"
+msgid "Instant Messaging"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:122
+msgctxt "Menu subcategory of Internet"
+msgid "IRC Clients"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:123
+msgctxt "Menu subcategory of Internet"
+msgid "Monitor"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:124
+msgctxt "Menu subcategory of Internet"
+msgid "News"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:125
+msgctxt "Menu subcategory of Internet"
+msgid "P2P"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:126
+msgctxt "Menu subcategory of Internet"
+msgid "Remote Access"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:127
+msgctxt "Menu subcategory of Internet"
+msgid "Telephony"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:128
+msgctxt "Menu subcategory of Internet"
+msgid "Video Conference"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:129
+msgctxt "Menu subcategory of Internet"
+msgid "Web Browser"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:130
+msgctxt "Menu subcategory of Internet"
+msgid "Web Development"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for Office
+#: ../src/plugins/menu-spec-common.c:132
+msgid "Office"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:133
+msgctxt "Menu subcategory of Office"
+msgid "Calendar"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:134
+msgctxt "Menu subcategory of Office"
+msgid "Chart"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:135
+msgctxt "Menu subcategory of Office"
+msgid "Contact Management"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:136
+msgctxt "Menu subcategory of Office"
+msgid "Database"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:137
+msgctxt "Menu subcategory of Office"
+msgid "Dictionary"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:138
+msgctxt "Menu subcategory of Office"
+msgid "Email"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:139
+msgctxt "Menu subcategory of Office"
+msgid "Finance"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:140
+msgctxt "Menu subcategory of Office"
+msgid "Flow Chart"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:141
+msgctxt "Menu subcategory of Office"
+msgid "PDA"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:142
+msgctxt "Menu subcategory of Office"
+msgid "Photography"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:143
+msgctxt "Menu subcategory of Office"
+msgid "Presentation"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:144
+msgctxt "Menu subcategory of Office"
+msgid "Project Management"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:145
+msgctxt "Menu subcategory of Office"
+msgid "Publishing"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:146
+msgctxt "Menu subcategory of Office"
+msgid "Spreadsheet"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:147
+msgctxt "Menu subcategory of Office"
+msgid "Viewer"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:148
+msgctxt "Menu subcategory of Office"
+msgid "Word Processor"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for Science
+#: ../src/plugins/menu-spec-common.c:150
+msgid "Science"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:151
+msgctxt "Menu subcategory of Science"
+msgid "Art"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:152
+msgctxt "Menu subcategory of Science"
+msgid "Artificial Intelligence"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:153
+msgctxt "Menu subcategory of Science"
+msgid "Astronomy"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:154
+msgctxt "Menu subcategory of Science"
+msgid "Biology"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:155
+msgctxt "Menu subcategory of Science"
+msgid "Chemistry"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:156
+msgctxt "Menu subcategory of Science"
+msgid "Computer Science"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:157
+msgctxt "Menu subcategory of Science"
+msgid "Construction"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:158
+msgctxt "Menu subcategory of Science"
+msgid "Data Visualization"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:159
+msgctxt "Menu subcategory of Science"
+msgid "Economy"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:160
+msgctxt "Menu subcategory of Science"
+msgid "Electricity"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:161
+msgctxt "Menu subcategory of Science"
+msgid "Electronics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:162
+msgctxt "Menu subcategory of Science"
+msgid "Engineering"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:163
+msgctxt "Menu subcategory of Science"
+msgid "Geography"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:164
+msgctxt "Menu subcategory of Science"
+msgid "Geology"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:165
+msgctxt "Menu subcategory of Science"
+msgid "Geoscience"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:166
+msgctxt "Menu subcategory of Science"
+msgid "History"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:167
+msgctxt "Menu subcategory of Science"
+msgid "Humanities"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:168
+msgctxt "Menu subcategory of Science"
+msgid "Image Processing"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:169
+msgctxt "Menu subcategory of Science"
+msgid "Languages"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:170
+msgctxt "Menu subcategory of Science"
+msgid "Literature"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:171
+msgctxt "Menu subcategory of Science"
+msgid "Maps"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:172
+msgctxt "Menu subcategory of Science"
+msgid "Math"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:173
+msgctxt "Menu subcategory of Science"
+msgid "Medical"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:174
+msgctxt "Menu subcategory of Science"
+msgid "Numerical Analysis"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:175
+msgctxt "Menu subcategory of Science"
+msgid "Parallel Computing"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:176
+msgctxt "Menu subcategory of Science"
+msgid "Physics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:177
+msgctxt "Menu subcategory of Science"
+msgid "Robotics"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:178
+msgctxt "Menu subcategory of Science"
+msgid "Spirituality"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:179
+msgctxt "Menu subcategory of Science"
+msgid "Sports"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for System
+#: ../src/plugins/menu-spec-common.c:181
+msgid "System"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:182
+msgctxt "Menu subcategory of System"
+msgid "Emulator"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:183
+msgctxt "Menu subcategory of System"
+msgid "File Manager"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:184
+msgctxt "Menu subcategory of System"
+msgid "File System"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:185
+msgctxt "Menu subcategory of System"
+msgid "File Tools"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:186
+msgctxt "Menu subcategory of System"
+msgid "Monitor"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:187
+msgctxt "Menu subcategory of System"
+msgid "Security"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:188
+msgctxt "Menu subcategory of System"
+msgid "Terminal Emulator"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for Utility
+#: ../src/plugins/menu-spec-common.c:190
+msgid "Utilities"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:191
+msgctxt "Menu subcategory of Utilities"
+msgid "Accessibility"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:192
+msgctxt "Menu subcategory of Utilities"
+msgid "Archiving"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:193
+msgctxt "Menu subcategory of Utilities"
+msgid "Calculator"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:194
+msgctxt "Menu subcategory of Utilities"
+msgid "Clock"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:195
+msgctxt "Menu subcategory of Utilities"
+msgid "Compression"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:196
+msgctxt "Menu subcategory of Utilities"
+msgid "File Tools"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:197
+msgctxt "Menu subcategory of Utilities"
+msgid "Maps"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:198
+msgctxt "Menu subcategory of Utilities"
+msgid "Spirituality"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:199
+msgctxt "Menu subcategory of Utilities"
+msgid "Telephony Tools"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:200
+msgctxt "Menu subcategory of Utilities"
+msgid "Text Editor"
+msgstr ""
+
+#. TRANSLATORS: this is the menu spec main category for Video
+#: ../src/plugins/menu-spec-common.c:202
+msgid "Video"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:203
+msgctxt "Menu subcategory of Video"
+msgid "Editing"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:204
+msgctxt "Menu subcategory of Video"
+msgid "Database"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:205
+msgctxt "Menu subcategory of Video"
+msgid "Disc Burning"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:206
+msgctxt "Menu subcategory of Video"
+msgid "Players"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:207
+msgctxt "Menu subcategory of Video"
+msgid "Recorders"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:208
+msgctxt "Menu subcategory of Video"
+msgid "TV"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:211
+msgctxt "Menu subcategory of Add-ons"
+msgid "Fonts"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:212
+msgctxt "Menu subcategory of Add-ons"
+msgid "Codecs"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:213
+msgctxt "Menu subcategory of Add-ons"
+msgid "Input Sources"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:214
+msgctxt "Menu subcategory of Add-ons"
+msgid "Language Packs"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:215
+msgctxt "Menu subcategory of Add-ons"
+msgid "Shell Extensions"
+msgstr ""
+
+#: ../src/plugins/menu-spec-common.c:216
+msgctxt "Menu subcategory of Add-ons"
+msgid "Localization"
+msgstr ""
diff --git a/po/ja.po b/po/ja.po
index 1cfc563..df4ee2d 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -8,9 +8,10 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: gnome-software master\n"
-"Report-Msgid-Bugs-To: 
http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-software&keywords=I18N+L10N&component=general\n";
-"POT-Creation-Date: 2016-03-19 22:23+0000\n"
-"PO-Revision-Date: 2016-03-21 13:09+0900\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-";
+"software&keywords=I18N+L10N&component=general\n"
+"POT-Creation-Date: 2016-04-16 21:44+0000\n"
+"PO-Revision-Date: 2016-04-17 18:11+0900\n"
 "Last-Translator: Jiro Matsuzawa <jmatsuzawa gnome org>\n"
 "Language-Team: Japanese <gnome-translation gnome gr jp>\n"
 "Language: ja\n"
@@ -18,6 +19,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Poedit 1.8.4\n"
 
 #: ../data/appdata/org.gnome.Software.appdata.xml.in.h:1
 msgid "GNOME Software"
@@ -28,111 +30,140 @@ msgid "Application manager for GNOME"
 msgstr "GNOME 用アプリケーションマネージャー"
 
 #: ../data/appdata/org.gnome.Software.appdata.xml.in.h:3
-msgid "Software allows you to find and install new applications and system extensions and remove existing 
installed applications."
-msgstr "GNOME ソフトウェアでは、新しいアプリケーションやシステム拡張の検索、インストールができます。また、インストール済みアプリケーションの削除も可能です。"
+msgid ""
+"Software allows you to find and install new applications and system "
+"extensions and remove existing installed applications."
+msgstr ""
+"GNOME ソフトウェアでは、新しいアプリケーションやシステム拡張の検索、インス"
+"トールができます。また、インストール済みアプリケーションの削除も可能です。"
 
 #: ../data/appdata/org.gnome.Software.appdata.xml.in.h:4
-msgid "GNOME Software showcases featured and popular applications with useful descriptions and multiple 
screenshots per application. Applications can be found either through browsing the list of categories or by 
searching. It also allows you to update your system using an offline update."
-msgstr "GNOME 
ソフトウェアでは、注目アプリケーションやよく使用されるアプリケーションを、役立つ説明や豊富なスクリーンショットとともにわかりやすく紹介しています。お探しのアプリケーションを探すのに適した、カテゴリーリストや検索機能も備えています。また、オフラインアップデートによるシステムの更新も可能です。"
+msgid ""
+"GNOME Software showcases featured and popular applications with useful "
+"descriptions and multiple screenshots per application. Applications can be "
+"found either through browsing the list of categories or by searching. It "
+"also allows you to update your system using an offline update."
+msgstr ""
+"GNOME ソフトウェアでは、注目アプリケーションやよく使用されるアプリケーション"
+"を、役立つ説明や豊富なスクリーンショットとともにわかりやすく紹介しています。"
+"お探しのアプリケーションを探すのに適した、カテゴリーリストや検索機能も備えて"
+"います。また、オフラインアップデートによるシステムの更新も可能です。"
 
 #: ../data/org.gnome.software.gschema.xml.h:1
 msgid "A list of compatible projects"
-msgstr ""
+msgstr "互換性のあるプロジェクトの一覧"
 
 #: ../data/org.gnome.software.gschema.xml.h:2
-msgid "This is a list of compatible projects we should show such as GNOME, KDE and XFCE."
-msgstr ""
+msgid ""
+"This is a list of compatible projects we should show such as GNOME, KDE and "
+"XFCE."
+msgstr "これは GNOME、KDE、XFCE など互換性のあるプロジェクトの一覧です。"
 
 #: ../data/org.gnome.software.gschema.xml.h:3
 msgid "Whether to automatically download updates"
-msgstr ""
+msgstr "アップデートを自動的にダウンロードする"
 
 #: ../data/org.gnome.software.gschema.xml.h:4
-msgid "If enabled, GNOME Software automatically downloads updates in the background and prompts the user to 
install them when ready."
+msgid ""
+"If enabled, GNOME Software automatically downloads updates in the background "
+"and prompts the user to install them when ready."
 msgstr ""
+"有効化されている場合、GNOME Software はバックグラウンドでアップデートを自動的"
+"にダウンロードし、準備ができたらユーザーにインストールを促します。"
 
 #: ../data/org.gnome.software.gschema.xml.h:5
 msgid "Whether it's the very first run of GNOME Software"
-msgstr ""
+msgstr "GNOME Software の初めての実行かどうか"
 
 #: ../data/org.gnome.software.gschema.xml.h:6
 msgid "Show star ratings next to applications"
-msgstr ""
+msgstr "アプリケーションの隣に評価点を星で表示する"
 
 #: ../data/org.gnome.software.gschema.xml.h:7
 msgid "Non-free applications show a warning dialog before install"
 msgstr ""
+"ノンフリーのアプリケーションをインストールする前に警告ダイアログを表示する"
 
 #: ../data/org.gnome.software.gschema.xml.h:8
-msgid "When non-free applications are installed a warning dialog can be shown. This controls if that dialog 
is suppressed."
+msgid ""
+"When non-free applications are installed a warning dialog can be shown. This "
+"controls if that dialog is suppressed."
 msgstr ""
+"ノンフリーのライセンスのアプリケーションをインストールする前に警告ダイアログ"
+"を表示することができます。ダイアログを表示するかどうかを、この設定で制御でき"
+"ます。"
 
 #: ../data/org.gnome.software.gschema.xml.h:9
-#, fuzzy
-#| msgid "Search for applications"
 msgid "A list of popular applications"
-msgstr "アプリケーションを検索する"
+msgstr "人気のあるアプリケーションの一覧"
 
 #: ../data/org.gnome.software.gschema.xml.h:10
 msgid "A list of applications to use, overriding the system defined ones."
 msgstr ""
+"おすすめとして表示するアプリケーションの一覧。システムで定義されている一覧よ"
+"りも優先します。"
 
 #: ../data/org.gnome.software.gschema.xml.h:11
 msgid "The list of extra sources that have been previously enabled"
-msgstr ""
+msgstr "以前に有効化された追加ソースの一覧"
 
 #: ../data/org.gnome.software.gschema.xml.h:12
-msgid "The list of sources that have been previously enabled when installing third-party applications."
+msgid ""
+"The list of sources that have been previously enabled when installing third-"
+"party applications."
 msgstr ""
+"サードパーティーのアプリケーションをインストールする時に有効化したソースのリ"
+"ストです。"
 
 #: ../data/org.gnome.software.gschema.xml.h:13
 msgid "The last update check timestamp"
-msgstr ""
+msgstr "最後にアップデートを確認した時のタイムスタンプ"
 
 #: ../data/org.gnome.software.gschema.xml.h:14
 msgid "The timestamp of the first security update, cleared after update"
 msgstr ""
+"セキュリティアップデートのタイムスタンプ (アップデート後にクリアされる)"
 
 #: ../data/org.gnome.software.gschema.xml.h:15
 msgid "The last update timestamp"
-msgstr ""
+msgstr "最終アップデートのタイムスタンプ"
 
 #: ../data/org.gnome.software.gschema.xml.h:16
 msgid "The server to use for application reviews"
-msgstr ""
+msgstr "アプリケーションのレビューに使用されるサーバー"
 
 #: ../data/org.gnome.software.gschema.xml.h:17
 msgid "The minimum karma score for reviews"
-msgstr ""
+msgstr "レビューを表示する最低カルマスコア"
 
 #: ../data/org.gnome.software.gschema.xml.h:18
 msgid "Reviews with karma less than this number will not be shown."
-msgstr ""
+msgstr "カルマがこの数値に達しないレビューは表示されません。"
 
 #: ../data/org.gnome.software.gschema.xml.h:19
 msgid "A list of official sources that should not be considered 3rd party"
-msgstr ""
+msgstr "サードパーティーのものとして取り扱うべきでないオフィシャルソースの一覧"
 
-#: ../src/app-folder-dialog.ui.h:1
+#: ../src/gs-app-folder-dialog.ui.h:1
 msgid "Add to Application Folder"
 msgstr "アプリケーションフォルダーに追加"
 
-#: ../src/app-folder-dialog.ui.h:2 ../src/gs-app-folder-dialog.c:316
-#: ../src/gs-review-dialog.ui.h:3 ../src/gs-shell-details.c:288
-#: ../src/gs-shell-installed.c:514
+#: ../src/gs-app-folder-dialog.ui.h:2 ../src/gs-app-folder-dialog.c:316
+#: ../src/gs-review-dialog.ui.h:3 ../src/gs-shell-details.c:305
+#: ../src/gs-shell-installed.c:514 ../src/gs-upgrade-banner.ui.h:4
 msgid "_Cancel"
 msgstr "キャンセル(_C)"
 
-#: ../src/app-folder-dialog.ui.h:3 ../src/gs-app-folder-dialog.c:321
+#: ../src/gs-app-folder-dialog.ui.h:3 ../src/gs-app-folder-dialog.c:321
 msgid "_Add"
 msgstr "追加(_A)"
 
 #. TRANSLATORS: this is the small blue label on the tile
 #. * that tells the user the application is installed
-#: ../src/app-tile.ui.h:1 ../src/gs-app-addon-row.c:97 ../src/gs-app-tile.c:78
-#: ../src/gs-app-tile.c:81 ../src/gs-feature-tile.c:68
+#: ../src/gs-app-tile.ui.h:1 ../src/gs-app-addon-row.c:97
+#: ../src/gs-app-tile.c:78 ../src/gs-app-tile.c:81 ../src/gs-feature-tile.c:68
 #: ../src/gs-popular-tile.c:74 ../src/gs-popular-tile.c:77
-#: ../src/popular-tile.ui.h:1
+#: ../src/gs-popular-tile.ui.h:1
 msgid "Installed"
 msgstr "インストール済み"
 
@@ -183,7 +214,7 @@ msgstr "更新(_U)"
 
 #. TRANSLATORS: this is a label that describes an application
 #. * that has been queued for installation
-#: ../src/gs-app-addon-row.c:91 ../src/gs-app-row.c:274
+#: ../src/gs-app-addon-row.c:91 ../src/gs-app-row.c:266
 #: ../src/gs-shell-details.ui.h:4
 msgid "Pending"
 msgstr "保留"
@@ -192,7 +223,7 @@ msgstr "保留"
 #. * shows the status of an application being installed
 #. TRANSLATORS: this is the small blue label on the tile
 #. * that tells the user the application is being installed
-#: ../src/gs-app-addon-row.c:101 ../src/gs-app-row.c:312
+#: ../src/gs-app-addon-row.c:101 ../src/gs-app-row.c:304
 #: ../src/gs-app-tile.c:87 ../src/gs-app-tile.c:90
 msgid "Installing"
 msgstr "インストール中"
@@ -201,35 +232,35 @@ msgstr "インストール中"
 #. * shows the status of an application being erased
 #. TRANSLATORS: this is the small blue label on the tile
 #. * that tells the user the application is being removed
-#: ../src/gs-app-addon-row.c:105 ../src/gs-app-row.c:321
+#: ../src/gs-app-addon-row.c:105 ../src/gs-app-row.c:313
 #: ../src/gs-app-tile.c:96 ../src/gs-app-tile.c:99
 msgid "Removing"
 msgstr "削除中"
 
-#. TRANSLATORS: This is how we join the licences and can
+#. TRANSLATORS: This is how we join the licenses and can
 #. * be considered a "Conjunctive AND Operator" according
 #. * to the SPDX specification. For example:
 #. * "LGPL-2.1 and MIT and BSD-2-Clause"
 #. TRANSLATORS: separator for a list of items
-#: ../src/gs-app.c:1315 ../src/gs-shell-extras.c:146
+#: ../src/gs-app.c:1345 ../src/gs-shell-extras.c:145
 msgid " and "
 msgstr " および "
 
-#. TRANSLATORS: This is how we join the licences and can
+#. TRANSLATORS: This is how we join the licenses and can
 #. * be considered a "Disjunctive OR Operator" according
 #. * to the SPDX specification. For example:
 #. * "LGPL-2.1 or MIT"
-#: ../src/gs-app.c:1323
+#: ../src/gs-app.c:1353
 msgid " or "
 msgstr " または "
 
 #. TRANSLATORS: non-free app
-#: ../src/gs-app.c:1346
+#: ../src/gs-app.c:1376
 msgid "Proprietary"
-msgstr "プロパティ"
+msgstr "プロプライエタリ"
 
 #. TRANSLATORS: see the wikipedia page
-#: ../src/gs-app.c:1356
+#: ../src/gs-app.c:1386
 msgid "Public domain"
 msgstr "パブリックドメイン"
 
@@ -240,7 +271,8 @@ msgstr "フォルダー名"
 #. TRANSLATORS: this is a command line option
 #: ../src/gs-application.c:97
 msgid "Start up mode: either ‘updates’, ‘updated’, ‘installed’ or ‘overview’"
-msgstr "起動モード 指定可能な値: ‘updates’, ‘updated’, ‘installed’ or ‘overview’"
+msgstr ""
+"起動モード 指定可能な値: ‘updates’, ‘updated’, ‘installed’ or ‘overview’"
 
 #: ../src/gs-application.c:97
 msgid "MODE"
@@ -304,26 +336,26 @@ msgstr "システムのソフトウェア管理に役立ちます"
 
 #. TRANSLATORS: during the update the device
 #. * will restart into a special update-only mode
-#: ../src/gs-app-row.c:160
+#: ../src/gs-app-row.c:152
 msgid "Device cannot be used during update."
 msgstr "更新中はデバイスを使用できません。"
 
 #. TRANSLATORS: this is a button next to the search results that
 #. * allows the application to be easily installed
-#: ../src/gs-app-row.c:258
+#: ../src/gs-app-row.c:250
 msgid "Visit website"
 msgstr "ウェブサイトへアクセス"
 
 #. TRANSLATORS: this is a button next to the search results that
 #. * allows the application to be easily installed.
 #. * The ellipsis indicates that further steps are required
-#: ../src/gs-app-row.c:263
+#: ../src/gs-app-row.c:255
 msgid "Install…"
 msgstr "インストール…"
 
 #. TRANSLATORS: this is a button next to the search results that
 #. * allows to cancel a queued install of the application
-#: ../src/gs-app-row.c:271
+#: ../src/gs-app-row.c:263
 msgid "Cancel"
 msgstr "キャンセル"
 
@@ -333,7 +365,7 @@ msgstr "キャンセル"
 #. * that allows the app to be easily updated live
 #. TRANSLATORS: this is button text to update the firware
 #. TRANSLATORS: button text
-#: ../src/gs-app-row.c:281 ../src/gs-app-row.c:288 ../src/gs-page.c:254
+#: ../src/gs-app-row.c:273 ../src/gs-app-row.c:280 ../src/gs-page.c:254
 #: ../src/gs-utils.c:317
 msgid "Install"
 msgstr "インストール"
@@ -341,7 +373,7 @@ msgstr "インストール"
 #. TRANSLATORS: this is a button next to the search results that
 #. * allows the application to be easily removed
 #. TRANSLATORS: this is button text to remove the application
-#: ../src/gs-app-row.c:292 ../src/gs-app-row.c:303 ../src/gs-page.c:322
+#: ../src/gs-app-row.c:284 ../src/gs-app-row.c:295 ../src/gs-page.c:322
 msgid "Remove"
 msgstr "削除"
 
@@ -373,6 +405,11 @@ msgstr "その他"
 msgid "All"
 msgstr "すべて"
 
+#. TRANSLATORS: this is a subcategory of featured apps
+#: ../src/gs-category.c:242
+msgid "Featured"
+msgstr "注目ソフト"
+
 #. TRANSLATORS: this is a what we use in notifications if the app's name is unknown
 #: ../src/gs-dbus-helper.c:307
 msgid "An application"
@@ -448,8 +485,14 @@ msgid "Welcome to Software"
 msgstr "ようこそソフトウェアへ"
 
 #: ../src/gs-first-run-dialog.ui.h:3
-msgid "Software lets you install all the software you need, all from one place. See our recommendations, 
browse the categories, or search for the applications you want."
-msgstr 
"ソフトウェアを使って、必要なアプリケーションをすべてインストールすることができます。おすすめのアプリケーションをチェックしたり、カテゴリーから探してみてください。欲しいアプリケーションを検索することもできます。"
+msgid ""
+"Software lets you install all the software you need, all from one place. See "
+"our recommendations, browse the categories, or search for the applications "
+"you want."
+msgstr ""
+"ソフトウェアを使って、必要なアプリケーションをすべてインストールすることがで"
+"きます。おすすめのアプリケーションをチェックしたり、カテゴリーから探してみて"
+"ください。欲しいアプリケーションを検索することもできます。"
 
 #: ../src/gs-first-run-dialog.ui.h:4
 msgid "_Let’s Go Shopping"
@@ -504,7 +547,7 @@ msgstr "履歴"
 #: ../src/gs-page.c:248
 #, c-format
 msgid "Prepare %s"
-msgstr ""
+msgstr "%s を準備"
 
 #. TRANSLATORS: this is a prompt message, and
 #. * '%s' is an application summary, e.g. 'GNOME Clocks'
@@ -521,87 +564,91 @@ msgstr "%s は削除されます。再び使用するにはインストールし
 
 #. TRANSLATORS: this is a group of updates that are not
 #. * packages and are not shown in the main list
-#: ../src/gs-plugin-loader.c:689
+#: ../src/gs-plugin-loader.c:718
 msgid "OS Updates"
 msgstr "OS の更新"
 
 #. TRANSLATORS: this is a longer description of the
 #. * "OS Updates" string
-#: ../src/gs-plugin-loader.c:694
+#: ../src/gs-plugin-loader.c:723
 msgid "Includes performance, stability and security improvements."
 msgstr "この更新には性能、安定性、およびセキュリティの向上が含まれています。"
 
 #. TRANSLATORS: this is when we know about an application or
 #. * addon, but it can't be listed for some reason
-#: ../src/gs-plugin-loader.c:1420 ../src/gs-shell-extras.c:387
+#: ../src/gs-plugin-loader.c:1449 ../src/gs-shell-extras.c:386
 #, c-format
 msgid "No addon codecs are available for the %s format."
 msgstr "%s フォーマットが利用可能なコーデックのアドオンはありません。"
 
-#: ../src/gs-plugin-loader.c:1423
+#: ../src/gs-plugin-loader.c:1452
 #, c-format
-msgid "Information about %s, as well as options for how to get a codec that can play this format can be 
found on the website."
-msgstr "%s についての情報および、このフォーマットを再生できるコーデックの入手方法はウェブサイト上で確認できます。"
+msgid ""
+"Information about %s, as well as options for how to get a codec that can "
+"play this format can be found on the website."
+msgstr ""
+"%s についての情報および、このフォーマットを再生できるコーデックの入手方法は"
+"ウェブサイト上で確認できます。"
 
 #. TRANSLATORS: lighthearted star rating description;
 #. *           A really bad application
 #: ../src/gs-review-dialog.c:93
 msgid "Hate it"
-msgstr ""
+msgstr "嫌い"
 
 #. TRANSLATORS: lighthearted star rating description;
 #. *           Not a great application
 #: ../src/gs-review-dialog.c:97
 msgid "Don't like it"
-msgstr ""
+msgstr "好きではない"
 
 #. TRANSLATORS: lighthearted star rating description;
 #. *           A fairly-good application
 #: ../src/gs-review-dialog.c:101
 msgid "It's OK"
-msgstr ""
+msgstr "まあまあ"
 
 #. TRANSLATORS: lighthearted star rating description;
 #. *           A good application
 #: ../src/gs-review-dialog.c:105
 msgid "Like it"
-msgstr ""
+msgstr "気に入った"
 
 #. TRANSLATORS: lighthearted star rating description;
 #. *           A really awesome application
 #: ../src/gs-review-dialog.c:109
 msgid "Love it"
-msgstr ""
+msgstr "とても気に入った"
 
 #. TRANSLATORS: the review can't just be copied and pasted
 #: ../src/gs-review-dialog.c:131
 msgid "Please take more time writing the review"
-msgstr ""
+msgstr "もう少し時間を掛けてレビューを書いてください"
 
 #. TRANSLATORS: the review is not acceptable
 #: ../src/gs-review-dialog.c:135
 msgid "Please choose a star rating"
-msgstr ""
+msgstr "評価の点数を選択してください"
 
 #. TRANSLATORS: the review is not acceptable
 #: ../src/gs-review-dialog.c:139
 msgid "The summary is too short"
-msgstr ""
+msgstr "サマリーが短すぎます"
 
 #. TRANSLATORS: the review is not acceptable
 #: ../src/gs-review-dialog.c:143
 msgid "The summary is too long"
-msgstr ""
+msgstr "サマリーが長すぎます"
 
 #. TRANSLATORS: the review is not acceptable
 #: ../src/gs-review-dialog.c:147
 msgid "The description is too short"
-msgstr ""
+msgstr "レビュー内容が短すぎます"
 
 #. TRANSLATORS: the review is not acceptable
 #: ../src/gs-review-dialog.c:151
 msgid "The description is too long"
-msgstr ""
+msgstr "レビュー内容が長すぎます"
 
 #. vim: set noexpandtab:
 #. Translators: Title of the dialog box where the users can write and publish their opinions about the apps.
@@ -615,19 +662,20 @@ msgid "_Post"
 msgstr "投稿(_P)"
 
 #: ../src/gs-review-dialog.ui.h:6
-#, fuzzy
-#| msgctxt "Menu subcategory of Audio"
-#| msgid "Editing"
 msgid "Rating"
-msgstr "編集"
+msgstr "評価"
 
 #: ../src/gs-review-dialog.ui.h:7
 msgid "Summary"
-msgstr ""
+msgstr "サマリー"
 
 #: ../src/gs-review-dialog.ui.h:8
-msgid "Give a short summary of your review, for example: “Great app, would recommend”."
+msgid ""
+"Give a short summary of your review, for example: “Great app, would "
+"recommend”."
 msgstr ""
+"レビューの短い要約を書いてください(例:「すばらしいアプリです。おすすめしま"
+"す」)。"
 
 #. Translators: This is where the users enter their opinions about the apps.
 #: ../src/gs-review-dialog.ui.h:10
@@ -638,70 +686,64 @@ msgstr "レビュー"
 #: ../src/gs-review-dialog.ui.h:11
 msgid "What do you think of the app? Try to give reasons for your views."
 msgstr ""
+"このアプリケーションについてどう思いますか。できれば理由もあわせて書いてくだ"
+"さい。"
 
 #: ../src/gs-review-histogram.ui.h:1
 msgid "Total"
-msgstr ""
+msgstr "合計"
 
 #. TRANSLATORS: we explain what the action is going to do
 #: ../src/gs-review-row.c:207
 msgid "You can report reviews for abusive, rude, or discriminatory behavior."
-msgstr ""
+msgstr "侮蔑的、暴言、差別的なレビューを報告することができます。"
 
 #. TRANSLATORS: we ask the user if they really want to do this
 #: ../src/gs-review-row.c:212
-msgid "Once reported, a review will be hidden until it has been checked by an administrator."
-msgstr ""
+msgid ""
+"Once reported, a review will be hidden until it has been checked by an "
+"administrator."
+msgstr "一度報告すると、レビューは管理者が確認するまで隠されます。"
 
 #. TRANSLATORS: window title when
 #. * reporting a user-submitted review
 #. * for moderation
 #: ../src/gs-review-row.c:226
-#, fuzzy
-#| msgid "Review"
 msgid "Report Review?"
-msgstr "レビュー"
+msgstr "レビューを報告しますか?"
 
 #. TRANSLATORS: button text when
 #. * sending a review for moderation
 #: ../src/gs-review-row.c:230
-#, fuzzy
-#| msgctxt "Menu subcategory of Education"
-#| msgid "Sports"
 msgid "Report"
-msgstr "スポーツ"
+msgstr "報告"
 
 #. vim: set noexpandtab:
 #. Translators: Users can express their opinions about other users' opinions about the apps.
 #: ../src/gs-review-row.ui.h:2
 msgid "Was this review useful to you?"
-msgstr ""
+msgstr "このレビューは役に立ちましたか?"
 
 #: ../src/gs-review-row.ui.h:3
 msgid "Yes"
-msgstr ""
+msgstr "はい"
 
 #: ../src/gs-review-row.ui.h:4
-#, fuzzy
-#| msgctxt "menu category"
-#| msgid "None"
 msgid "No"
-msgstr "カテゴリなし"
+msgstr "いいえ"
 
 #. Translators: Button text for indifference, only used when moderating
 #: ../src/gs-review-row.ui.h:6
 msgid "Meh"
-msgstr ""
+msgstr "どうでもいい"
 
 #: ../src/gs-review-row.ui.h:7
 msgid "Report…"
-msgstr ""
+msgstr "報告する…"
 
 #: ../src/gs-review-row.ui.h:8
-#, fuzzy
-#| msgid "Remove"
 msgid "Remove…"
-msgstr "削除"
+msgstr "削除する…"
 
 #. TRANSLATORS: this is when we try to download a screenshot and
 #. * we get back 404
@@ -722,46 +764,53 @@ msgstr "スクリーンショットサイズの画像がありません"
 
 #. TRANSLATORS: this is when we try create the cache directory
 #. * but we were out of space or permission was denied
-#: ../src/gs-screenshot-image.c:395
+#: ../src/gs-screenshot-image.c:405
 msgid "Could not create cache"
 msgstr "キャッシュを作成できませんでした"
 
 #. TRANSLATORS: this is when we try to download a screenshot
 #. * that was not a valid URL
-#: ../src/gs-screenshot-image.c:423
+#: ../src/gs-screenshot-image.c:433
 msgid "Screenshot not valid"
 msgstr "スクリーンショットは無効です"
 
 #. TRANSLATORS: this is when networking is not available
-#: ../src/gs-screenshot-image.c:439
+#: ../src/gs-screenshot-image.c:449
 msgid "Screenshot not available"
 msgstr "スクリーンショットは利用できません"
 
-#: ../src/gs-screenshot-image.c:490
+#: ../src/gs-screenshot-image.c:500
 msgid "Screenshot"
 msgstr "スクリーンショット"
 
 #. vim: set noexpandtab:
 #: ../src/gs-shell-category.ui.h:1
-msgid "Extensions are used at your own risk. If you have any system problems, it is recommended to disable 
them."
+msgid ""
+"Extensions are used at your own risk. If you have any system problems, it is "
+"recommended to disable them."
 msgstr ""
+"拡張機能はユーザー自身のリスクで使用してください。システムに何らかの問題が発"
+"生した場合、拡張機能を無効化することが推奨されます。"
 
 #: ../src/gs-shell-category.ui.h:2
-#, fuzzy
-#| msgid "Network Settings"
 msgid "Extension Settings"
-msgstr "ネットワーク設定"
+msgstr "拡張機能の設定"
 
 #. TRANSLATORS: button text in the header when an application
 #. * can be installed
-#: ../src/gs-shell-details.c:200 ../src/gs-shell-details.ui.h:2
-#: ../src/gs-upgrade-banner.ui.h:4
+#. TRANSLATORS: button text in the header when firmware
+#. * can be live-installed
+#. TRANSLATORS: button text in the header when an application
+#. * can be live-updated
+#: ../src/gs-shell-details.c:201 ../src/gs-shell-details.c:227
+#: ../src/gs-shell-details.c:232 ../src/gs-shell-details.ui.h:2
+#: ../src/gs-upgrade-banner.ui.h:5
 msgid "_Install"
 msgstr "インストール(_I)"
 
 #. TRANSLATORS: button text in the header when an application
 #. * is in the process of being installed
-#: ../src/gs-shell-details.c:211
+#: ../src/gs-shell-details.c:212
 msgid "_Installing"
 msgstr "インストール中(_I)"
 
@@ -769,90 +818,98 @@ msgstr "インストール中(_I)"
 #. * be installed.
 #. * The ellipsis indicates that further steps are required,
 #. * e.g. enabling software sources or the like
-#: ../src/gs-shell-details.c:229
+#: ../src/gs-shell-details.c:245
 msgid "_Install…"
 msgstr "インストール(_I)…"
 
 #. TRANSLATORS: button text in the header when an application can be erased
-#: ../src/gs-shell-details.c:275 ../src/gs-shell-details.ui.h:3
+#: ../src/gs-shell-details.c:292 ../src/gs-shell-details.ui.h:3
 msgid "_Remove"
 msgstr "削除(_R)"
 
 #. TRANSLATORS: button text in the header when an application can be installed
-#: ../src/gs-shell-details.c:282
+#: ../src/gs-shell-details.c:299
 msgid "_Removing"
 msgstr "削除中(_R)"
 
-#. TRANSLATORS: this is where the licence is not known
-#: ../src/gs-shell-details.c:652
+#. TRANSLATORS: this is where the license is not known
+#: ../src/gs-shell-details.c:669
 msgctxt "license"
 msgid "Unknown"
 msgstr "不明"
 
 #. TRANSLATORS: this is where the version is not known
-#: ../src/gs-shell-details.c:665
+#: ../src/gs-shell-details.c:682
 msgctxt "version"
 msgid "Unknown"
 msgstr "不明"
 
 #. TRANSLATORS: this is where the size is being worked out
-#: ../src/gs-shell-details.c:671
+#: ../src/gs-shell-details.c:688
 msgctxt "size"
 msgid "Calculating…"
 msgstr "計算中…"
 
 #. TRANSLATORS: this is where the size is not known
-#: ../src/gs-shell-details.c:674
+#: ../src/gs-shell-details.c:691
 msgctxt "size"
 msgid "Unknown"
 msgstr "不明"
 
 #. TRANSLATORS: this is where the updated date is not known
-#: ../src/gs-shell-details.c:686
+#: ../src/gs-shell-details.c:703
 msgctxt "updated"
 msgid "Never"
 msgstr "なし"
 
 #. TRANSLATORS: this is the application isn't in any
 #. * defined menu category
-#: ../src/gs-shell-details.c:700
+#: ../src/gs-shell-details.c:717
 msgctxt "menu category"
 msgid "None"
 msgstr "カテゴリなし"
 
 #. TRANSLATORS: this is where we don't know the origin of the
 #. * application
-#: ../src/gs-shell-details.c:717
+#: ../src/gs-shell-details.c:734
 msgctxt "origin"
 msgid "Unknown"
 msgstr "不明"
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:763
-msgid "This application can only be used when there is an active internet connection."
-msgstr "このアプリケーションはインターネットに接続していなければ使用できません。"
+#: ../src/gs-shell-details.c:780
+msgid ""
+"This application can only be used when there is an active internet "
+"connection."
+msgstr ""
+"このアプリケーションはインターネットに接続していなければ使用できません。"
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:774
+#: ../src/gs-shell-details.c:791
 msgid "This software comes from a 3rd party."
-msgstr ""
+msgstr "このソフトウェアはサードパーティーのものです。"
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:783
-msgid "This software comes from a 3rd party and may contain non-free components."
+#: ../src/gs-shell-details.c:800
+msgid ""
+"This software comes from a 3rd party and may contain non-free components."
 msgstr ""
+"このソフトウェアはサードパーティーからのもので、ノンフリーのライセンスである"
+"コンポーネントを含んでいる可能性があります。"
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:792
+#: ../src/gs-shell-details.c:809
 msgid "This software may contain non-free components."
 msgstr ""
+"このソフトウェアはノンフリーのライセンスであるコンポーネントを含んでいる可能"
+"性があります。"
 
-#: ../src/gs-shell-details.c:1114
+#: ../src/gs-shell-details.c:1135
 #, c-format
 msgid "Could not find '%s'"
-msgstr ""
+msgstr "'%s' が見つかりませんでした"
 
-#: ../src/gs-shell-details.c:1174 ../src/gs-utils.c:166
+#: ../src/gs-shell-details.c:1195 ../src/gs-utils.c:166
 msgid "Sorry, this did not work"
 msgstr "動作しませんでした"
 
@@ -871,20 +928,32 @@ msgid "Software Source Included"
 msgstr "ソフトウェアソースあり"
 
 #: ../src/gs-shell-details.ui.h:8
-msgid "This application includes a software source which provides updates, as well as access to other 
software."
-msgstr "このアプリケーションには更新や他のソフトウェアを利用できるようになるソフトウェアソースが含まれています。"
+msgid ""
+"This application includes a software source which provides updates, as well "
+"as access to other software."
+msgstr ""
+"このアプリケーションには更新や他のソフトウェアを利用できるようになるソフト"
+"ウェアソースが含まれています。"
 
 #: ../src/gs-shell-details.ui.h:9
 msgid "No Software Source Included"
 msgstr "ソフトウェアソースなし"
 
 #: ../src/gs-shell-details.ui.h:10
-msgid "This application does not include a software source. It will not be updated with new versions."
-msgstr "このアプリケーションはソフトウェアソースが含まれていません。新しいバージョンのアップデートは行われません。"
+msgid ""
+"This application does not include a software source. It will not be updated "
+"with new versions."
+msgstr ""
+"このアプリケーションはソフトウェアソースが含まれていません。新しいバージョン"
+"のアップデートは行われません。"
 
 #: ../src/gs-shell-details.ui.h:11
-msgid "This software is already provided by your distribution and should not be replaced."
-msgstr "このソフトウェアはお使いのディストリビューションで既に提供されているため、置き換えないほうがよいでしょう。"
+msgid ""
+"This software is already provided by your distribution and should not be "
+"replaced."
+msgstr ""
+"このソフトウェアはお使いのディストリビューションで既に提供されているため、置"
+"き換えないほうがよいでしょう。"
 
 #. Translators: a repository file used for installing software has been discovered.
 #: ../src/gs-shell-details.ui.h:13
@@ -892,8 +961,12 @@ msgid "Software Source Identified"
 msgstr "ソフトウェアソースを特定"
 
 #: ../src/gs-shell-details.ui.h:14
-msgid "Adding this software source will give you access to additional software and upgrades."
-msgstr "このソフトウェアソースを追加することで、他のソフトウェアやアップグレードを利用できるようになります。"
+msgid ""
+"Adding this software source will give you access to additional software and "
+"upgrades."
+msgstr ""
+"このソフトウェアソースを追加することで、他のソフトウェアやアップグレードを利"
+"用できるようになります。"
 
 #: ../src/gs-shell-details.ui.h:15
 msgid "Only use software sources that you trust."
@@ -907,7 +980,7 @@ msgstr "ウェブサイト(_W)"
 msgid "_History"
 msgstr "履歴(_H)"
 
-#: ../src/gs-shell-details.ui.h:18 ../src/gs-update-monitor.c:556
+#: ../src/gs-shell-details.ui.h:18 ../src/gs-update-monitor.c:557
 msgid "Details"
 msgstr "詳細"
 
@@ -957,7 +1030,7 @@ msgstr "ライセンス"
 
 #: ../src/gs-shell-details.ui.h:30
 msgid "non-free"
-msgstr ""
+msgstr "ノンフリー"
 
 #. TRANSLATORS: This is the header dividing the normal
 #. * applications and the addons
@@ -987,13 +1060,13 @@ msgid "_Show More"
 msgstr "もっと表示(_S)"
 
 #. TRANSLATORS: separator for a list of items
-#: ../src/gs-shell-extras.c:149
+#: ../src/gs-shell-extras.c:148
 msgid ", "
 msgstr ", "
 
 #. TRANSLATORS: Application window title for fonts installation.
 #. %s will be replaced by name of the script we're searching for.
-#: ../src/gs-shell-extras.c:175
+#: ../src/gs-shell-extras.c:174
 #, c-format
 msgid "Available fonts for the %s script"
 msgid_plural "Available fonts for the %s scripts"
@@ -1001,130 +1074,159 @@ msgstr[0] "%s 用の利用可能なフォント"
 
 #. TRANSLATORS: Application window title for codec installation.
 #. %s will be replaced by actual codec name(s)
-#: ../src/gs-shell-extras.c:183
+#: ../src/gs-shell-extras.c:182
 #, c-format
 msgid "Available software for %s"
 msgid_plural "Available software for %s"
 msgstr[0] "%s 用の利用可能なソフトウェア"
 
-#: ../src/gs-shell-extras.c:225
+#: ../src/gs-shell-extras.c:224
 msgid "Unable to Find Requested Software"
 msgstr "要求されたソフトウェアが見つかりません"
 
 #. TRANSLATORS: This string is used for codecs that weren't found
-#: ../src/gs-shell-extras.c:321
+#: ../src/gs-shell-extras.c:320
 #, c-format
 msgid "%s not found"
 msgstr "%sは見つかりませんでした"
 
 #. TRANSLATORS: hyperlink title
-#: ../src/gs-shell-extras.c:325
+#: ../src/gs-shell-extras.c:324
 msgid "on the website"
 msgstr "ウェブサイト"
 
 #. TRANSLATORS: this is when we know about an application or
 #. * addon, but it can't be listed for some reason
-#: ../src/gs-shell-extras.c:332
+#: ../src/gs-shell-extras.c:331
 #, c-format
 msgid "No applications are available that provide the file %s."
 msgstr "ファイル %s を提供するアプリケーションはありません。"
 
 #. TRANSLATORS: first %s is the codec name, and second %s is a
 #. * hyperlink with the "on the website" text
-#: ../src/gs-shell-extras.c:336 ../src/gs-shell-extras.c:347
-#: ../src/gs-shell-extras.c:358
+#: ../src/gs-shell-extras.c:335 ../src/gs-shell-extras.c:346
+#: ../src/gs-shell-extras.c:357
 #, c-format
-msgid "Information about %s, as well as options for how to get missing applications might be found %s."
-msgstr "%s についての情報や、見つからないアプリケーションの入手方法は %s で確認できるかもしれません。"
+msgid ""
+"Information about %s, as well as options for how to get missing applications "
+"might be found %s."
+msgstr ""
+"%s についての情報や、見つからないアプリケーションの入手方法は %s で確認できる"
+"かもしれません。"
 
 #. TRANSLATORS: this is when we know about an application or
 #. * addon, but it can't be listed for some reason
-#: ../src/gs-shell-extras.c:343 ../src/gs-shell-extras.c:365
+#: ../src/gs-shell-extras.c:342 ../src/gs-shell-extras.c:364
 #, c-format
 msgid "No applications are available for %s support."
 msgstr "%sをサポートする利用可能なアプリケーションはありません。"
 
 #. TRANSLATORS: this is when we know about an application or
 #. * addon, but it can't be listed for some reason
-#: ../src/gs-shell-extras.c:354
+#: ../src/gs-shell-extras.c:353
 #, c-format
 msgid "%s is not available."
 msgstr "%sは利用できません。"
 
 #. TRANSLATORS: first %s is the codec name, and second %s is a
 #. * hyperlink with the "on the website" text
-#: ../src/gs-shell-extras.c:369
+#: ../src/gs-shell-extras.c:368
 #, c-format
-msgid "Information about %s, as well as options for how to get an application that can support this format 
might be found %s."
-msgstr "%s についての情報および、このフォーマットをサポートするアプリケーションの入手方法は %s で確認できるかもしれません。"
+msgid ""
+"Information about %s, as well as options for how to get an application that "
+"can support this format might be found %s."
+msgstr ""
+"%s についての情報および、このフォーマットをサポートするアプリケーションの入手"
+"方法は %s で確認できるかもしれません。"
 
 #. TRANSLATORS: this is when we know about an application or
 #. * addon, but it can't be listed for some reason
-#: ../src/gs-shell-extras.c:376
-#, fuzzy, c-format
-#| msgid "No addon fonts are available for %s support."
+#: ../src/gs-shell-extras.c:375
+#, c-format
 msgid "No fonts are available for the %s script support."
-msgstr "%sをサポートする利用可能なアドオンはありません。"
+msgstr "%sスクリプトをサポートする利用可能なフォントがありません。"
 
 #. TRANSLATORS: first %s is the codec name, and second %s is a
 #. * hyperlink with the "on the website" text
-#: ../src/gs-shell-extras.c:380
+#: ../src/gs-shell-extras.c:379
 #, c-format
-msgid "Information about %s, as well as options for how to get additional fonts might be found %s."
-msgstr "%s についての情報および、追加フォントの入手方法は %s で確認できるかもしれません。"
+msgid ""
+"Information about %s, as well as options for how to get additional fonts "
+"might be found %s."
+msgstr ""
+"%s についての情報および、追加フォントの入手方法は %s で確認できるかもしれませ"
+"ん。"
 
 #. TRANSLATORS: first %s is the codec name, and second %s is a
 #. * hyperlink with the "on the website" text
-#: ../src/gs-shell-extras.c:391
+#: ../src/gs-shell-extras.c:390
 #, c-format
-msgid "Information about %s, as well as options for how to get a codec that can play this format might be 
found %s."
-msgstr "%s についての情報および、このフォーマットを再生可能なコーデックの入手方法は %s で確認できるかもしれません。"
+msgid ""
+"Information about %s, as well as options for how to get a codec that can "
+"play this format might be found %s."
+msgstr ""
+"%s についての情報および、このフォーマットを再生可能なコーデックの入手方法は "
+"%s で確認できるかもしれません。"
 
 #. TRANSLATORS: this is when we know about an application or
 #. * addon, but it can't be listed for some reason
-#: ../src/gs-shell-extras.c:398
+#: ../src/gs-shell-extras.c:397
 #, c-format
 msgid "No Plasma resources are available for %s support."
 msgstr "%s をサポートする利用可能なPlasmaリソースはありません。"
 
 #. TRANSLATORS: first %s is the codec name, and second %s is a
 #. * hyperlink with the "on the website" text
-#: ../src/gs-shell-extras.c:402
+#: ../src/gs-shell-extras.c:401
 #, c-format
-msgid "Information about %s, as well as options for how to get additional Plasma resources might be found 
%s."
-msgstr "%s についての情報および、追加のPlasmaリソースの入手方法は %s で確認できるかもしれません。"
+msgid ""
+"Information about %s, as well as options for how to get additional Plasma "
+"resources might be found %s."
+msgstr ""
+"%s についての情報および、追加のPlasmaリソースの入手方法は %s で確認できるかも"
+"しれません。"
 
 #. TRANSLATORS: this is when we know about an application or
 #. * addon, but it can't be listed for some reason
-#: ../src/gs-shell-extras.c:409
+#: ../src/gs-shell-extras.c:408
 #, c-format
 msgid "No printer drivers are available for %s."
 msgstr "%sを利用可能なプリンタードライバーはありません。"
 
 #. TRANSLATORS: first %s is the codec name, and second %s is a
 #. * hyperlink with the "on the website" text
-#: ../src/gs-shell-extras.c:413
+#: ../src/gs-shell-extras.c:412
 #, c-format
-msgid "Information about %s, as well as options for how to get a driver that supports this printer might be 
found %s."
-msgstr "%s についての情報および、このプリンターをサポートするドライバーの入手方法は %s で確認できるかもしれません。"
+msgid ""
+"Information about %s, as well as options for how to get a driver that "
+"supports this printer might be found %s."
+msgstr ""
+"%s についての情報および、このプリンターをサポートするドライバーの入手方法は "
+"%s で確認できるかもしれません。"
 
-#: ../src/gs-shell-extras.c:459
+#: ../src/gs-shell-extras.c:458
 msgid "this website"
 msgstr "このウェブサイト"
 
 #. TRANSLATORS: no codecs were found. First %s will be replaced by actual codec name(s), second %s is a link 
titled "this website"
-#: ../src/gs-shell-extras.c:463
+#: ../src/gs-shell-extras.c:462
 #, c-format
-msgid "Unfortunately, the %s you were searching for could not be found. Please see %s for more information."
-msgid_plural "Unfortunately, the %s you were searching for could not be found. Please see %s for more 
information."
-msgstr[0] "残念ながら、お探しの %s は見つかりませんでした。詳しくは %s を参照してください。"
-
-#: ../src/gs-shell-extras.c:543 ../src/gs-shell-extras.c:591
-#: ../src/gs-shell-extras.c:641
+msgid ""
+"Unfortunately, the %s you were searching for could not be found. Please see "
+"%s for more information."
+msgid_plural ""
+"Unfortunately, the %s you were searching for could not be found. Please see "
+"%s for more information."
+msgstr[0] ""
+"残念ながら、お探しの %s は見つかりませんでした。詳しくは %s を参照してくださ"
+"い。"
+
+#: ../src/gs-shell-extras.c:542 ../src/gs-shell-extras.c:590
+#: ../src/gs-shell-extras.c:640
 msgid "Failed to find any search results"
 msgstr "何も見つかりませんでした"
 
-#: ../src/gs-shell-extras.c:810
+#: ../src/gs-shell-extras.c:809
 #, c-format
 msgid "%s file format"
 msgstr "%s ファイルフォーマット"
@@ -1166,14 +1268,12 @@ msgid "_Remove from Folder"
 msgstr "フォルダーから削除(_R)"
 
 #: ../src/gs-shell-moderate.ui.h:1
-#, fuzzy
-#| msgid "Updates page"
 msgid "Moderate page"
-msgstr "更新ページ"
+msgstr "審査ページ"
 
 #: ../src/gs-shell-moderate.ui.h:2
 msgid "There are no reviews to moderate"
-msgstr ""
+msgstr "審査するレビューはありません"
 
 #. TRANSLATORS: this is a heading for audio applications which have been featured ('recommended') by the 
distribution
 #: ../src/gs-shell-overview.c:367
@@ -1309,44 +1409,46 @@ msgid "Last checked: %s"
 msgstr "最終確認: %s"
 
 #. TRANSLATORS: this is to explain that downloading updates may cost money
-#: ../src/gs-shell-updates.c:825
+#: ../src/gs-shell-updates.c:826
 msgid "Charges may apply"
 msgstr "料金が掛かる可能性があります"
 
 #. TRANSLATORS: we need network
 #. * to do the updates check
-#: ../src/gs-shell-updates.c:829
-msgid "Checking for updates while using mobile broadband could cause you to incur charges."
+#: ../src/gs-shell-updates.c:830
+msgid ""
+"Checking for updates while using mobile broadband could cause you to incur "
+"charges."
 msgstr "モバイル接続を利用した更新の確認は費用が発生する場合があります。"
 
 #. TRANSLATORS: this is a link to the
 #. * control-center network panel
-#: ../src/gs-shell-updates.c:833
+#: ../src/gs-shell-updates.c:834
 msgid "Check Anyway"
 msgstr "確認する"
 
 #. TRANSLATORS: can't do updates check
-#: ../src/gs-shell-updates.c:849
+#: ../src/gs-shell-updates.c:850
 msgid "No Network"
 msgstr "ネットワークがありません"
 
 #. TRANSLATORS: we need network
 #. * to do the updates check
-#: ../src/gs-shell-updates.c:853
+#: ../src/gs-shell-updates.c:854
 msgid "Internet access is required to check for updates."
 msgstr "更新を確認するにはインターネットにアクセスする必要があります。"
 
 #. TRANSLATORS: this is a link to the
 #. * control-center network panel
-#: ../src/gs-shell-updates.c:857
+#: ../src/gs-shell-updates.c:858
 msgid "Network Settings"
 msgstr "ネットワーク設定"
 
-#: ../src/gs-shell-updates.c:1157
+#: ../src/gs-shell-updates.c:1192
 msgid "Restart & _Install"
 msgstr "再起動してインストール(_I)"
 
-#: ../src/gs-shell-updates.c:1174
+#: ../src/gs-shell-updates.c:1209
 msgid "Check for updates"
 msgstr "更新を確認する"
 
@@ -1364,7 +1466,9 @@ msgid "Software is up to date"
 msgstr "ソフトウェアは最新です"
 
 #: ../src/gs-shell-updates.ui.h:4
-msgid "Checking for updates when using mobile broadband could cause you to incur charges"
+msgid ""
+"Checking for updates when using mobile broadband could cause you to incur "
+"charges"
 msgstr "モバイル接続を利用した更新の確認は費用が発生する場合があります"
 
 #: ../src/gs-shell-updates.ui.h:5
@@ -1381,13 +1485,15 @@ msgstr "ネットワーク設定(_N)"
 
 #: ../src/gs-shell-updates.ui.h:8
 msgid "Updates are automatically managed"
-msgstr ""
+msgstr "アップデートは自動的に管理されます"
 
 #. TRANSLATORS: This string describes a software source that
 #. has no software installed from it.
 #: ../src/gs-sources-dialog.c:94
 msgid "No applications or addons installed; other software might still be"
 msgstr ""
+"アプリケーションやアドオンはインストールされていません。他のソフトウェアもま"
+"だそうかもしれません"
 
 #. TRANSLATORS: This string is used to construct the 'X applications
 #. installed' sentence, describing a software source.
@@ -1452,8 +1558,12 @@ msgstr "オペレーティングシステム"
 #. replaced by the name of the actual distro, e.g. Fedora.
 #: ../src/gs-sources-dialog.c:473
 #, c-format
-msgid "Software sources can be downloaded from the internet. They give you access to additional software 
that is not provided by %s."
+msgid ""
+"Software sources can be downloaded from the internet. They give you access "
+"to additional software that is not provided by %s."
 msgstr ""
+"ソフトウェアソースはインターネットからダウンロードできます。ソフトウェアソー"
+"スを追加すると、%s で提供されていないソフトウェアも利用できるようになります。"
 
 #. vim: set noexpandtab:
 #: ../src/gs-sources-dialog.ui.h:1
@@ -1462,11 +1572,15 @@ msgstr "ソフトウェアソース"
 
 #: ../src/gs-sources-dialog.ui.h:3
 msgid "Software sources give you access to additional software."
-msgstr "ソフトウェアソースにより、追加のソフトウェアが利用できるようになります。"
+msgstr ""
+"ソフトウェアソースにより、追加のソフトウェアが利用できるようになります。"
 
 #: ../src/gs-sources-dialog.ui.h:4
-msgid "Removing a source will also remove any software you have installed from it."
-msgstr "ソースを削除すると、そのソースからインストールしたソフトウェアもすべて削除することになります。"
+msgid ""
+"Removing a source will also remove any software you have installed from it."
+msgstr ""
+"ソースを削除すると、そのソースからインストールしたソフトウェアもすべて削除す"
+"ることになります。"
 
 #: ../src/gs-sources-dialog.ui.h:5
 msgid "No software installed from this source"
@@ -1512,10 +1626,9 @@ msgstr "4つ星"
 msgid "Five Stars"
 msgstr "5つ星"
 
-#. TRANSLATORS: this is where the
-#. * packager did not write a
-#. * description for the update
-#: ../src/gs-update-dialog.c:123
+#. TRANSLATORS: this is where the packager did not write
+#. * a description for the update
+#: ../src/gs-update-dialog.c:121
 msgid "No update description available."
 msgstr "更新の説明がありません。"
 
@@ -1523,21 +1636,19 @@ msgstr "更新の説明がありません。"
 #. %s will be replaced by the date when the updates were installed.
 #. The date format is defined by the locale's preferred date representation
 #. ("%x" in strftime.)
-#: ../src/gs-update-dialog.c:230
+#: ../src/gs-update-dialog.c:215
 #, c-format
 msgid "Installed on %s"
 msgstr "%s にインストール済み"
 
 #. TRANSLATORS: this is the title of the installed updates dialog window
-#: ../src/gs-update-dialog.c:250
+#: ../src/gs-update-dialog.c:235
 msgid "Installed Updates"
 msgstr "インストール済みの更新"
 
 #: ../src/gs-update-dialog.ui.h:2
-#, fuzzy
-#| msgid "No software installed from this source"
 msgid "No updates have been installed on this system."
-msgstr "このソースからインストールしたソフトウェアはありません"
+msgstr "このシステムにインストールされたアップデートはありません。"
 
 #: ../src/gs-update-monitor.c:89
 msgid "Security Updates Pending"
@@ -1580,27 +1691,27 @@ msgid "Software Upgrade Available"
 msgstr "アップグレードが利用可能"
 
 #. TRANSLATORS: title when we offline updates have failed
-#: ../src/gs-update-monitor.c:428
+#: ../src/gs-update-monitor.c:429
 msgid "Software Updates Failed"
 msgstr "ソフトウェアの更新に失敗しました"
 
 #. TRANSLATORS: message when we offline updates have failed
-#: ../src/gs-update-monitor.c:430
+#: ../src/gs-update-monitor.c:431
 msgid "An important OS update failed to be installed."
 msgstr "重要なOSアップデートのインストールに失敗しました。"
 
-#: ../src/gs-update-monitor.c:432
+#: ../src/gs-update-monitor.c:433
 msgid "Show Details"
 msgstr "詳細を表示"
 
 #. TRANSLATORS: title when we've done offline updates
-#: ../src/gs-update-monitor.c:447
+#: ../src/gs-update-monitor.c:448
 msgid "Software Update Installed"
 msgid_plural "Software Updates Installed"
 msgstr[0] "ソフトウェアの更新をインストールしました"
 
 #. TRANSLATORS: message when we've done offline updates
-#: ../src/gs-update-monitor.c:451
+#: ../src/gs-update-monitor.c:452
 msgid "An important OS update has been installed."
 msgid_plural "Important OS updates have been installed."
 msgstr[0] "重要なOSアップデートがインストールされました。"
@@ -1610,7 +1721,7 @@ msgstr[0] "重要なOSアップデートがインストールされました。"
 #. * users can't express their opinions here. In some languages
 #. * "Review (evaluate) something" is a different translation than
 #. * "Review (browse) something."
-#: ../src/gs-update-monitor.c:462
+#: ../src/gs-update-monitor.c:463
 msgctxt "updates"
 msgid "Review"
 msgstr "確認"
@@ -1618,51 +1729,66 @@ msgstr "確認"
 #. TRANSLATORS: these are show_detailed_error messages from the
 #. * package manager no mortal is supposed to understand,
 #. * but google might know what they mean
-#: ../src/gs-update-monitor.c:537
+#: ../src/gs-update-monitor.c:538
 msgid "Detailed errors from the package manager follow:"
 msgstr "パッケージマネージャーからのエラーの詳細:"
 
 #. TRANSLATORS: this is when the offline update failed
-#: ../src/gs-update-monitor.c:598
+#: ../src/gs-update-monitor.c:599
 msgid "Failed To Update"
 msgstr "アップデートに失敗"
 
 #. TRANSLATORS: the user must have updated manually after
 #. * the updates were prepared
-#: ../src/gs-update-monitor.c:604
+#: ../src/gs-update-monitor.c:605
 msgid "The system was already up to date."
 msgstr "システムは最新です。"
 
 #. TRANSLATORS: the user aborted the update manually
-#: ../src/gs-update-monitor.c:609
+#: ../src/gs-update-monitor.c:610
 msgid "The update was cancelled."
 msgstr "この更新はキャンセルされました。"
 
 #. TRANSLATORS: the package manager needed to download
 #. * something with no network available
-#: ../src/gs-update-monitor.c:615
-msgid "Internet access was required but wasn’t available. Please make sure that you have internet access and 
try again."
-msgstr "必要なインターネットアクセスが利用できませんでした。インターネットに接続できることを確認して再実行してください。"
+#: ../src/gs-update-monitor.c:616
+msgid ""
+"Internet access was required but wasn’t available. Please make sure that you "
+"have internet access and try again."
+msgstr ""
+"必要なインターネットアクセスが利用できませんでした。インターネットに接続でき"
+"ることを確認して再実行してください。"
 
 #. TRANSLATORS: if the package is not signed correctly
-#: ../src/gs-update-monitor.c:621
-msgid "There were security issues with the update. Please consult your software provider for more details."
-msgstr "更新中にセキュリティ上の問題に遭遇しました。詳細についてソフトウェアの提供元に問い合わせてください。"
+#: ../src/gs-update-monitor.c:622
+msgid ""
+"There were security issues with the update. Please consult your software "
+"provider for more details."
+msgstr ""
+"更新中にセキュリティ上の問題に遭遇しました。詳細についてソフトウェアの提供元"
+"に問い合わせてください。"
 
 #. TRANSLATORS: we ran out of disk space
-#: ../src/gs-update-monitor.c:627
-msgid "There wasn’t enough disk space. Please free up some space and try again."
-msgstr "充分なディスク領域がありませんでした。空き領域を確保して再実行してください。"
+#: ../src/gs-update-monitor.c:628
+msgid ""
+"There wasn’t enough disk space. Please free up some space and try again."
+msgstr ""
+"充分なディスク領域がありませんでした。空き領域を確保して再実行してください。"
 
 #. TRANSLATORS: We didn't handle the error type
-#: ../src/gs-update-monitor.c:632
-msgid "We’re sorry: the update failed to install. Please wait for another update and try again. If the 
problem persists, contact your software provider."
-msgstr "残念ながら、更新の適用に失敗しました。次のアップデートを待って再度試してください。それでも問題が解決しない場合、ソフトウェアの提供元に問い合わせてください。"
+#: ../src/gs-update-monitor.c:633
+msgid ""
+"We’re sorry: the update failed to install. Please wait for another update "
+"and try again. If the problem persists, contact your software provider."
+msgstr ""
+"残念ながら、更新の適用に失敗しました。次のアップデートを待って再度試してくだ"
+"さい。それでも問題が解決しない場合、ソフトウェアの提供元に問い合わせてくださ"
+"い。"
 
 #. TRANSLATORS: This is the text displayed when a distro
 #. * upgrade is available. First %s is the distro name and the
 #. * 2nd %s is the version, e.g. "Fedora 23 Now Available"
-#: ../src/gs-upgrade-banner.c:75
+#: ../src/gs-upgrade-banner.c:83
 #, c-format
 msgid "%s %s Now Available"
 msgstr "%s %s が利用可能"
@@ -1670,7 +1796,7 @@ msgstr "%s %s が利用可能"
 #. TRANSLATORS: This is the text displayed while downloading a
 #. * distro upgrade. First %s is the distro name and the 2nd %s
 #. * is the version, e.g. "Downloading Fedora 23"
-#: ../src/gs-upgrade-banner.c:88
+#: ../src/gs-upgrade-banner.c:93
 #, c-format
 msgid "Downloading %s %s"
 msgstr "%s %s のダウンロード中"
@@ -1679,7 +1805,7 @@ msgstr "%s %s のダウンロード中"
 #. * upgrade has been downloaded and is ready to be installed.
 #. * First %s is the distro name and the 2nd %s is the version,
 #. * e.g. "Fedora 23 Ready to be Installed"
-#: ../src/gs-upgrade-banner.c:102
+#: ../src/gs-upgrade-banner.c:104
 #, c-format
 msgid "%s %s Ready to be Installed"
 msgstr "%s %s のインストール準備完了"
@@ -1697,9 +1823,12 @@ msgstr "詳細(_L)"
 msgid "_Download"
 msgstr "ダウンロード(_D)"
 
-#: ../src/gs-upgrade-banner.ui.h:5
-msgid "It is recommended that you back up your data and files before upgrading."
-msgstr "アップグレードの前に必要なデータやファイルのバックアップを取っておくことをお勧めします。"
+#: ../src/gs-upgrade-banner.ui.h:6
+msgid ""
+"It is recommended that you back up your data and files before upgrading."
+msgstr ""
+"アップグレードの前に必要なデータやファイルのバックアップを取っておくことをお"
+"勧めします。"
 
 #. TRANSLATORS: this is the summary of a notification that an application
 #. * has been successfully installed
@@ -1741,8 +1870,12 @@ msgstr "サードパーティーのソフトウェアソースを有効にしま
 #.
 #: ../src/gs-utils.c:270
 #, c-format
-msgid "%s is not <a href=\"https://en.wikipedia.org/wiki/Free_and_open-source_software\";>free and open 
source software</a>, and is provided by “%s”."
-msgstr "%s は<a 
href=\"https://en.wikipedia.org/wiki/Free_and_open-source_software\";>自由でオープンソースのソフトウェア</a>ではなく、“%s”で提供されます"
+msgid ""
+"%s is not <a href=\"https://en.wikipedia.org/wiki/Free_and_open-";
+"source_software\">free and open source software</a>, and is provided by “%s”."
+msgstr ""
+"%s は<a href=\"https://en.wikipedia.org/wiki/Free_and_open-source_software\";>"
+"自由でオープンソースのソフトウェア</a>ではなく、“%s”で提供されます"
 
 #. TRANSLATORS: the replacements are as follows:
 #. * 1. Application name, e.g. "Firefox"
@@ -1755,7 +1888,9 @@ msgstr "%s は“%s”で提供されています。"
 #. TRANSLATORS: a software source is a repo
 #: ../src/gs-utils.c:290
 msgid "This software source must be enabled to continue installation."
-msgstr "インストールを続行するには、このソフトウェアソースを有効にする必要があります。"
+msgstr ""
+"インストールを続行するには、このソフトウェアソースを有効にする必要がありま"
+"す。"
 
 #. TRANSLATORS: Laws are geographical, urgh...
 #: ../src/gs-utils.c:300
@@ -1779,15 +1914,15 @@ msgid "Enable and Install"
 msgstr "有効にしてインストール"
 
 #. vim: set noexpandtab:
-#: ../src/menus.ui.h:1
+#: ../src/gs-menus.ui.h:1
 msgid "_Software Sources"
 msgstr "ソフトウェアソース(_S)"
 
-#: ../src/menus.ui.h:2
+#: ../src/gs-menus.ui.h:2
 msgid "_About"
 msgstr "このアプリケーションについて(_A)"
 
-#: ../src/menus.ui.h:3
+#: ../src/gs-menus.ui.h:3
 msgid "_Quit"
 msgstr "終了(_Q)"
 
@@ -1796,17 +1931,14 @@ msgid "Add, remove or update software on this computer"
 msgstr "このコンピューターでソフトウェアの追加、削除、更新を行います"
 
 #: ../src/org.gnome.Software.desktop.in.h:3
-msgid "Updates;Upgrade;Sources;Repositories;Preferences;Install;Uninstall;Program;Software;App;Store;"
-msgstr 
"Updates;Upgrade;Sources;Repositories;Preferences;Install;Uninstall;Program;Software;App;Store;更新;アップデート;アップグレード;ソース;リポジトリ;レポジトリ;設定;インストール;アンインストール;プログラム;ソフトウェア;アプリケーション;ストア;"
-
-#: ../src/plugins/gs-plugin-appstream.c:199
-#, c-format
-msgid "No AppStream data found"
-msgstr "AppStreamデータが見つかりません"
-
-#: ../src/plugins/gs-plugin-moduleset.c:153
-msgid "Featured"
-msgstr "注目ソフト"
+msgid ""
+"Updates;Upgrade;Sources;Repositories;Preferences;Install;Uninstall;Program;"
+"Software;App;Store;"
+msgstr ""
+"Updates;Upgrade;Sources;Repositories;Preferences;Install;Uninstall;Program;"
+"Software;App;Store;更新;アップデート;アップグレード;ソース;リポジトリ;レポジ"
+"トリ;設定;インストール;アンインストール;プログラム;ソフトウェア;アプリケー"
+"ション;ストア;"
 
 #. TRANSLATORS: this is the menu spec main category for Audio
 #: ../src/plugins/menu-spec-common.c:30
@@ -2683,6 +2815,9 @@ msgctxt "Menu subcategory of Add-ons"
 msgid "Localization"
 msgstr "ローカライゼーション"
 
+#~ msgid "No AppStream data found"
+#~ msgstr "AppStreamデータが見つかりません"
+
 #~ msgid "A previous update was unfinished."
 #~ msgstr "前回の更新が完了していません。"
 
@@ -2708,7 +2843,9 @@ msgstr "ローカライゼーション"
 #~ msgstr "この更新は完了できませんでした。"
 
 #~ msgid "An offline update was requested but no packages required updating."
-#~ msgstr "オフラインアップデートが要求されましたが、アップデートが必要なパッケージはありません。"
+#~ msgstr ""
+#~ "オフラインアップデートが要求されましたが、アップデートが必要なパッケージは"
+#~ "ありません。"
 
 #~ msgid "No space was left on the drive."
 #~ msgstr "ドライブに空き容量がありません。"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index f784ee4..d039838 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -8,22 +8,22 @@
 # Rafael Fontenelle <rffontenelle gmail com>, 2013, 2014, 2015, 2016.
 # Artur de Aquino Morais <artur morais93 outlook com>, 2016.
 # Fábio Nogueira <fnogueira gnome org>, 2015, 2016.
-#
+# Rafael Fontenelle <rafaelff gnome org>, 2016.
 msgid ""
 msgstr ""
 "Project-Id-Version: gnome-software\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-";
 "software&keywords=I18N+L10N&component=general\n"
-"POT-Creation-Date: 2016-03-16 10:23+0000\n"
-"PO-Revision-Date: 2016-03-15 13:29-0300\n"
-"Last-Translator: Enrico Nicoletto <liverig gmail com>\n"
+"POT-Creation-Date: 2016-04-13 09:49+0000\n"
+"PO-Revision-Date: 2016-04-13 12:05-0200\n"
+"Last-Translator: Rafael Fontenelle <rafaelff gnome org>\n"
 "Language-Team: Brazilian Portuguese <gnome-pt_br-list gnome org>\n"
 "Language: pt_BR\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
-"X-Generator: Poedit 1.7.3\n"
+"X-Generator: Virtaal 0.7.1\n"
 "X-Project-Style: gnome\n"
 
 #: ../data/appdata/org.gnome.Software.appdata.xml.in.h:1
@@ -160,7 +160,7 @@ msgid "Add to Application Folder"
 msgstr "Adicionar à pasta de aplicativo"
 
 #: ../src/app-folder-dialog.ui.h:2 ../src/gs-app-folder-dialog.c:316
-#: ../src/gs-review-dialog.ui.h:3 ../src/gs-shell-details.c:284
+#: ../src/gs-review-dialog.ui.h:3 ../src/gs-shell-details.c:305
 #: ../src/gs-shell-installed.c:514
 msgid "_Cancel"
 msgstr "_Cancelar"
@@ -811,14 +811,19 @@ msgstr "Configurações de extensão"
 
 #. TRANSLATORS: button text in the header when an application
 #. * can be installed
-#: ../src/gs-shell-details.c:196 ../src/gs-shell-details.ui.h:2
+#. TRANSLATORS: button text in the header when firmware
+#. * can be live-installed
+#. TRANSLATORS: button text in the header when an application
+#. * can be live-updated
+#: ../src/gs-shell-details.c:201 ../src/gs-shell-details.c:227
+#: ../src/gs-shell-details.c:232 ../src/gs-shell-details.ui.h:2
 #: ../src/gs-upgrade-banner.ui.h:4
 msgid "_Install"
 msgstr "_Instalar"
 
 #. TRANSLATORS: button text in the header when an application
 #. * is in the process of being installed
-#: ../src/gs-shell-details.c:207
+#: ../src/gs-shell-details.c:212
 msgid "_Installing"
 msgstr "_Instalando"
 
@@ -826,66 +831,66 @@ msgstr "_Instalando"
 #. * be installed.
 #. * The ellipsis indicates that further steps are required,
 #. * e.g. enabling software sources or the like
-#: ../src/gs-shell-details.c:225
+#: ../src/gs-shell-details.c:245
 msgid "_Install…"
 msgstr "_Instalar…"
 
 #. TRANSLATORS: button text in the header when an application can be erased
-#: ../src/gs-shell-details.c:271 ../src/gs-shell-details.ui.h:3
+#: ../src/gs-shell-details.c:292 ../src/gs-shell-details.ui.h:3
 msgid "_Remove"
 msgstr "_Remover"
 
 #. TRANSLATORS: button text in the header when an application can be installed
-#: ../src/gs-shell-details.c:278
+#: ../src/gs-shell-details.c:299
 msgid "_Removing"
 msgstr "_Removendo"
 
 #. TRANSLATORS: this is where the licence is not known
-#: ../src/gs-shell-details.c:648
+#: ../src/gs-shell-details.c:669
 msgctxt "license"
 msgid "Unknown"
 msgstr "Desconhecido"
 
 #. TRANSLATORS: this is where the version is not known
-#: ../src/gs-shell-details.c:661
+#: ../src/gs-shell-details.c:682
 msgctxt "version"
 msgid "Unknown"
 msgstr "Desconhecido"
 
 #. TRANSLATORS: this is where the size is being worked out
-#: ../src/gs-shell-details.c:667
+#: ../src/gs-shell-details.c:688
 msgctxt "size"
 msgid "Calculating…"
 msgstr "Calculando…"
 
 #. TRANSLATORS: this is where the size is not known
-#: ../src/gs-shell-details.c:670
+#: ../src/gs-shell-details.c:691
 msgctxt "size"
 msgid "Unknown"
 msgstr "Desconhecido"
 
 #. TRANSLATORS: this is where the updated date is not known
-#: ../src/gs-shell-details.c:682
+#: ../src/gs-shell-details.c:703
 msgctxt "updated"
 msgid "Never"
 msgstr "Nunca"
 
 #. TRANSLATORS: this is the application isn't in any
 #. * defined menu category
-#: ../src/gs-shell-details.c:696
+#: ../src/gs-shell-details.c:717
 msgctxt "menu category"
 msgid "None"
 msgstr "Nenhuma"
 
 #. TRANSLATORS: this is where we don't know the origin of the
 #. * application
-#: ../src/gs-shell-details.c:713
+#: ../src/gs-shell-details.c:734
 msgctxt "origin"
 msgid "Unknown"
 msgstr "Desconhecido"
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:759
+#: ../src/gs-shell-details.c:780
 msgid ""
 "This application can only be used when there is an active internet "
 "connection."
@@ -893,27 +898,27 @@ msgstr ""
 "Este aplicativo só pode ser usado quando há uma conexão ativa com a Internet."
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:770
+#: ../src/gs-shell-details.c:791
 msgid "This software comes from a 3rd party."
 msgstr "Este programa veio de terceiros"
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:779
+#: ../src/gs-shell-details.c:800
 msgid ""
 "This software comes from a 3rd party and may contain non-free components."
 msgstr "Este programa veio de terceiros e pode conter componentes não livres."
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:788
+#: ../src/gs-shell-details.c:809
 msgid "This software may contain non-free components."
 msgstr "Este programa pode conter componentes não livres."
 
-#: ../src/gs-shell-details.c:1110
+#: ../src/gs-shell-details.c:1131
 #, c-format
 msgid "Could not find '%s'"
 msgstr "Não foi possível localizar \"%s\""
 
-#: ../src/gs-shell-details.c:1158 ../src/gs-utils.c:166
+#: ../src/gs-shell-details.c:1191 ../src/gs-utils.c:166
 msgid "Sorry, this did not work"
 msgstr "Desculpe, isto não funcionou"
 
@@ -1317,7 +1322,7 @@ msgstr "Aplicativo em destaque"
 #. Translators: This is a heading for software which has been featured ('picked') by the distribution.
 #: ../src/gs-shell-overview.ui.h:4
 msgid "Editor's Picks"
-msgstr "Os preferidos da edição"
+msgstr "Escolha do editor"
 
 #: ../src/gs-shell-overview.ui.h:5
 msgid "Categories"
diff --git a/po/ru.po b/po/ru.po
index 7c5888e..6204db4 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -10,8 +10,8 @@ msgstr ""
 "Project-Id-Version: gnome-software master\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-";
 "software&keywords=I18N+L10N&component=general\n"
-"POT-Creation-Date: 2016-03-17 12:52+0000\n"
-"PO-Revision-Date: 2016-03-17 21:33+0300\n"
+"POT-Creation-Date: 2016-04-14 09:45+0000\n"
+"PO-Revision-Date: 2016-04-14 15:48+0300\n"
 "Last-Translator: Yuri Myasoedov <ymyasoedov yandex ru>\n"
 "Language-Team: Русский <gnome-cyr gnome org>\n"
 "Language: ru\n"
@@ -25,7 +25,7 @@ msgstr ""
 #  перевод по аналогии с ubuntu software - центр приложений ubuntu
 #: ../data/appdata/org.gnome.Software.appdata.xml.in.h:1
 msgid "GNOME Software"
-msgstr "Менеджер приложений GNOME"
+msgstr "Программы GNOME"
 
 #: ../data/appdata/org.gnome.Software.appdata.xml.in.h:2
 msgid "Application manager for GNOME"
@@ -36,8 +36,8 @@ msgid ""
 "Software allows you to find and install new applications and system "
 "extensions and remove existing installed applications."
 msgstr ""
-"Менеджер приложений позволяет находить и устанавливать новые приложения и "
-"расширения системы, а также удалять уже установленные приложения."
+"«Программы» позволяют находить и устанавливать новые приложения и расширения "
+"системы, а также удалять уже установленные."
 
 #: ../data/appdata/org.gnome.Software.appdata.xml.in.h:4
 msgid ""
@@ -46,10 +46,10 @@ msgid ""
 "found either through browsing the list of categories or by searching. It "
 "also allows you to update your system using an offline update."
 msgstr ""
-"Менеджер приложений GNOME представляет рекомендуемые и популярные приложения "
-"с описанием и несколькими картинками к ним. Приложения можно находить "
-"просматривая список категорий или с помощью функции поиска. Также менеджер "
-"приложений позволяет обновлять систему с помощью отложенных обновлений."
+"«Программы GNOME» показывают рекомендуемые и популярные приложения с "
+"описаниями и снимками экрана. Приложения можно находить, просматривая список "
+"категорий, или при помощи строки поиска. Также «Программы GNOME» позволяют "
+"обновлять систему посредством автономных обновлений."
 
 #: ../data/org.gnome.software.gschema.xml.h:1
 msgid "A list of compatible projects"
@@ -149,7 +149,7 @@ msgid "Add to Application Folder"
 msgstr "Добавить в папку приложения"
 
 #: ../src/app-folder-dialog.ui.h:2 ../src/gs-app-folder-dialog.c:316
-#: ../src/gs-review-dialog.ui.h:3 ../src/gs-shell-details.c:288
+#: ../src/gs-review-dialog.ui.h:3 ../src/gs-shell-details.c:305
 #: ../src/gs-shell-installed.c:514
 msgid "_Cancel"
 msgstr "О_тменить"
@@ -173,7 +173,7 @@ msgstr "Установка приложений"
 
 #: ../src/gnome-software-local-file.desktop.in.h:2
 msgid "Install selected software on the system"
-msgstr "Установить выбранное программное обеспечение"
+msgstr "Установить выбранное приложение"
 
 #: ../src/gnome-software.ui.h:1
 msgid "Select All"
@@ -190,7 +190,7 @@ msgstr "Снять выделение"
 #: ../src/gnome-software.ui.h:3 ../src/gs-application.c:374
 #: ../src/gs-shell.c:253 ../src/org.gnome.Software.desktop.in.h:1
 msgid "Software"
-msgstr "Менеджер приложений"
+msgstr "Программы"
 
 #. vim: set noexpandtab:
 #: ../src/gnome-software.ui.h:4 ../src/gs-sources-dialog.ui.h:2
@@ -323,8 +323,8 @@ msgstr "Показать номер версии"
 #: ../src/gs-application.c:367
 msgid "translator-credits"
 msgstr ""
-"Stas Solovey <whats_up tut by>, 2013-2016.\n"
-"Юрий Мясоедов <ymyasoedov yandex ru>, 2014."
+"Стас Соловей <whats_up tut by>, 2013-2016.\n"
+"Юрий Мясоедов <ymyasoedov yandex ru>, 2014-2016."
 
 #. TRANSLATORS: this is the title of the about window
 #: ../src/gs-application.c:371
@@ -334,7 +334,7 @@ msgstr "О приложении"
 #. TRANSLATORS: well, we seem to think so, anyway
 #: ../src/gs-application.c:377
 msgid "A nice way to manage the software on your system."
-msgstr "Удобная программа управления программным обеспечением в системе."
+msgstr "Отличное средство для управления приложениями в системе."
 
 #. TRANSLATORS: during the update the device
 #. * will restart into a special update-only mode
@@ -472,7 +472,7 @@ msgstr "Требуются дополнительные пакеты"
 #. TRANSLATORS: this is a button that launches gnome-software
 #: ../src/gs-dbus-helper.c:348
 msgid "Find in Software"
-msgstr "Найти в приложениях"
+msgstr "Найти в «Программах»"
 
 #. vim: set noexpandtab:
 #: ../src/gs-first-run-dialog.ui.h:1
@@ -481,7 +481,7 @@ msgstr "Добро пожаловать"
 
 #: ../src/gs-first-run-dialog.ui.h:2
 msgid "Welcome to Software"
-msgstr "Добро пожаловать в менеджер приложений"
+msgstr "Добро пожаловать в «Программы»"
 
 #: ../src/gs-first-run-dialog.ui.h:3
 msgid ""
@@ -489,23 +489,23 @@ msgid ""
 "our recommendations, browse the categories, or search for the applications "
 "you want."
 msgstr ""
-"Менеджер приложений — это программа для централизованного управления "
-"программным обеспечением. Смотрите категории и рекомендации или найдите "
-"интересующие вас приложения."
+"Из «Программ» можно устанавливать любые интересующие вас приложения. "
+"Просматривайте рекомендации и категории или найдите нужное приложение по его "
+"названию."
 
 #: ../src/gs-first-run-dialog.ui.h:4
 msgid "_Let’s Go Shopping"
-msgstr "_Отправляемся за покупками"
+msgstr "_Идём смотреть"
 
 #. TRANSLATORS: Here are 2 strings the same as in gtk/gtkbox.c
 #. in GTK+ project. Please use the same translation.
 #: ../src/gs-hiding-box.c:384
 msgid "Spacing"
-msgstr "Отступы"
+msgstr "Отступ"
 
 #: ../src/gs-hiding-box.c:385
 msgid "The amount of space between children"
-msgstr "Объем пространства между дочерними элементами"
+msgstr "Расстояние между дочерними элементами"
 
 #. TRANSLATORS: this is the status in the history UI,
 #. * where we are showing the application was removed
@@ -799,14 +799,19 @@ msgstr "Параметры расширения"
 
 #. TRANSLATORS: button text in the header when an application
 #. * can be installed
-#: ../src/gs-shell-details.c:200 ../src/gs-shell-details.ui.h:2
+#. TRANSLATORS: button text in the header when firmware
+#. * can be live-installed
+#. TRANSLATORS: button text in the header when an application
+#. * can be live-updated
+#: ../src/gs-shell-details.c:201 ../src/gs-shell-details.c:227
+#: ../src/gs-shell-details.c:232 ../src/gs-shell-details.ui.h:2
 #: ../src/gs-upgrade-banner.ui.h:4
 msgid "_Install"
 msgstr "_Установить"
 
 #. TRANSLATORS: button text in the header when an application
 #. * is in the process of being installed
-#: ../src/gs-shell-details.c:211
+#: ../src/gs-shell-details.c:212
 msgid "_Installing"
 msgstr "У_становка"
 
@@ -814,80 +819,79 @@ msgstr "У_становка"
 #. * be installed.
 #. * The ellipsis indicates that further steps are required,
 #. * e.g. enabling software sources or the like
-#: ../src/gs-shell-details.c:229
+#: ../src/gs-shell-details.c:245
 msgid "_Install…"
 msgstr "Ус_тановить…"
 
 #. TRANSLATORS: button text in the header when an application can be erased
-#: ../src/gs-shell-details.c:275 ../src/gs-shell-details.ui.h:3
+#: ../src/gs-shell-details.c:292 ../src/gs-shell-details.ui.h:3
 msgid "_Remove"
 msgstr "У_далить"
 
 #. TRANSLATORS: button text in the header when an application can be installed
-#: ../src/gs-shell-details.c:282
+#: ../src/gs-shell-details.c:299
 msgid "_Removing"
 msgstr "У_даление"
 
 #. TRANSLATORS: this is where the licence is not known
-#: ../src/gs-shell-details.c:652
+#: ../src/gs-shell-details.c:669
 msgctxt "license"
 msgid "Unknown"
 msgstr "Неизвестная"
 
 #. TRANSLATORS: this is where the version is not known
-#: ../src/gs-shell-details.c:665
+#: ../src/gs-shell-details.c:682
 msgctxt "version"
 msgid "Unknown"
 msgstr "Неизвестная"
 
 #. TRANSLATORS: this is where the size is being worked out
-#: ../src/gs-shell-details.c:671
+#: ../src/gs-shell-details.c:688
 msgctxt "size"
 msgid "Calculating…"
 msgstr "Подсчёт…"
 
 #. TRANSLATORS: this is where the size is not known
-#: ../src/gs-shell-details.c:674
+#: ../src/gs-shell-details.c:691
 msgctxt "size"
 msgid "Unknown"
 msgstr "Неизвестно"
 
 #. TRANSLATORS: this is where the updated date is not known
-#: ../src/gs-shell-details.c:686
+#: ../src/gs-shell-details.c:703
 msgctxt "updated"
 msgid "Never"
 msgstr "Никогда"
 
 #. TRANSLATORS: this is the application isn't in any
 #. * defined menu category
-#: ../src/gs-shell-details.c:700
+#: ../src/gs-shell-details.c:717
 msgctxt "menu category"
 msgid "None"
 msgstr "Нет"
 
 #. TRANSLATORS: this is where we don't know the origin of the
 #. * application
-#: ../src/gs-shell-details.c:717
+#: ../src/gs-shell-details.c:734
 msgctxt "origin"
 msgid "Unknown"
 msgstr "Неизвестно"
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:763
+#: ../src/gs-shell-details.c:780
 msgid ""
 "This application can only be used when there is an active internet "
 "connection."
 msgstr ""
-"Этим приложением можно пользоваться только при наличии активного Интернет-"
-"подключения."
+"Этим приложением можно пользоваться только при наличии Интернет-подключения."
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:774
+#: ../src/gs-shell-details.c:791
 msgid "This software comes from a 3rd party."
 msgstr "Это — стороннее программное обеспечение."
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:783
+#: ../src/gs-shell-details.c:800
 msgid ""
 "This software comes from a 3rd party and may contain non-free components."
 msgstr ""
@@ -895,16 +899,16 @@ msgstr ""
 "компоненты."
 
 #. TRANSLATORS: this is the warning box
-#: ../src/gs-shell-details.c:792
+#: ../src/gs-shell-details.c:809
 msgid "This software may contain non-free components."
 msgstr "Это программное обеспечение может содержать несвободные компоненты."
 
-#: ../src/gs-shell-details.c:1114
+#: ../src/gs-shell-details.c:1131
 #, c-format
 msgid "Could not find '%s'"
 msgstr "Не удалось найти «%s»"
 
-#: ../src/gs-shell-details.c:1174 ../src/gs-utils.c:166
+#: ../src/gs-shell-details.c:1191 ../src/gs-utils.c:166
 msgid "Sorry, this did not work"
 msgstr "Не сработало"
 
@@ -920,28 +924,27 @@ msgstr "_Запустить"
 
 #: ../src/gs-shell-details.ui.h:7
 msgid "Software Source Included"
-msgstr "Содержит источник программного обеспечения"
+msgstr "Содержит источник программ"
 
 #: ../src/gs-shell-details.ui.h:8
 msgid ""
 "This application includes a software source which provides updates, as well "
 "as access to other software."
 msgstr ""
-"Это приложение содержит источник программного обеспечения, который "
-"предоставляет обновления приложения, а также доступ к другому программному "
-"обеспечению."
+"Это приложение содержит источник программ, который предоставляет обновления, "
+"а также доступ к другим приложениям."
 
 #: ../src/gs-shell-details.ui.h:9
 msgid "No Software Source Included"
-msgstr "Без источника программного обеспечения"
+msgstr "Без источника программ"
 
 #: ../src/gs-shell-details.ui.h:10
 msgid ""
 "This application does not include a software source. It will not be updated "
 "with new versions."
 msgstr ""
-"Приложение не содержит источник программного обеспечения. Оно не будет "
-"обновляться при выходе новых версий."
+"Приложение не содержит источника программ. Оно не будет обновляться при "
+"выпуске новых версий."
 
 #: ../src/gs-shell-details.ui.h:11
 msgid ""
@@ -954,20 +957,19 @@ msgstr ""
 #. Translators: a repository file used for installing software has been discovered.
 #: ../src/gs-shell-details.ui.h:13
 msgid "Software Source Identified"
-msgstr "Найден источник программного обеспечения"
+msgstr "Найден источник программ"
 
 #: ../src/gs-shell-details.ui.h:14
 msgid ""
 "Adding this software source will give you access to additional software and "
 "upgrades."
 msgstr ""
-"Добавление этого источника программного обеспечения предоставит доступ к "
-"дополнительным приложениям и обновлениям."
+"Добавление этого источника программ предоставит доступ к дополнительным "
+"приложениям и обновлениям."
 
 #: ../src/gs-shell-details.ui.h:15
 msgid "Only use software sources that you trust."
-msgstr ""
-"Используйте только те источники программного обеспечения, которым доверяете."
+msgstr "Используйте только те источники программ, которым доверяете."
 
 #: ../src/gs-shell-details.ui.h:16
 msgid "_Website"
@@ -1587,20 +1589,17 @@ msgid ""
 "Software sources can be downloaded from the internet. They give you access "
 "to additional software that is not provided by %s."
 msgstr ""
-"Источники программного обеспечения могут быть загружены из Интернета. Они "
-"дают вам доступ к дополнительному программному обеспечению, которое не "
-"предусмотрено %s."
+"Источники программ могут быть загружены из Интернета. Они дают вам доступ к "
+"дополнительному программному обеспечению, которое не предусмотрено %s."
 
 #. vim: set noexpandtab:
 #: ../src/gs-sources-dialog.ui.h:1
 msgid "Software Sources"
-msgstr "Источники программного обеспечения"
+msgstr "Источники программ"
 
 #: ../src/gs-sources-dialog.ui.h:3
 msgid "Software sources give you access to additional software."
-msgstr ""
-"Источники программного обеспечения предоставляют доступ к дополнительным "
-"приложениям."
+msgstr "Источники программ предоставляют доступ к дополнительным приложениям."
 
 #: ../src/gs-sources-dialog.ui.h:4
 msgid ""
@@ -1692,7 +1691,7 @@ msgstr "Перезапустить и установить"
 
 #: ../src/gs-update-monitor.c:97
 msgid "Software Updates Available"
-msgstr "Доступны обновления программного обеспечения"
+msgstr "Доступны обновления приложений"
 
 #: ../src/gs-update-monitor.c:98
 msgid "Important OS and application updates are ready to be installed"
@@ -1721,7 +1720,7 @@ msgstr "Доступно обновление на новую версию ОС"
 #. TRANSLATORS: title when we offline updates have failed
 #: ../src/gs-update-monitor.c:428
 msgid "Software Updates Failed"
-msgstr "Не удалось обновить программное обеспечение"
+msgstr "Не удалось обновить приложения"
 
 #. TRANSLATORS: message when we offline updates have failed
 #: ../src/gs-update-monitor.c:430
@@ -1958,8 +1957,7 @@ msgstr "_Завершить"
 
 #: ../src/org.gnome.Software.desktop.in.h:2
 msgid "Add, remove or update software on this computer"
-msgstr ""
-"Установка, удаление и обновление программного обеспечения на компьютере"
+msgstr "Установка, удаление и обновление приложений на компьютере"
 
 #: ../src/org.gnome.Software.desktop.in.h:3
 msgid ""
diff --git a/po/sr.po b/po/sr.po
index b911c86..0e10b76 100644
--- a/po/sr.po
+++ b/po/sr.po
@@ -13,7 +13,7 @@ msgstr ""
 "Project-Id-Version: gnome-software\n"
 "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-";
 "software&keywords=I18N+L10N&component=general\n"
-"POT-Creation-Date: 2016-03-29 18:50+0000\n"
+"POT-Creation-Date: 2016-03-29 15:55+0000\n"
 "PO-Revision-Date: 2016-03-29 18:16+0200\n"
 "Last-Translator: Марко М. Костић <marko m kostic gmail com>\n"
 "Language-Team: Serbian <gnom prevod org>\n"
@@ -808,11 +808,8 @@ msgstr "Подешавања проширења"
 #. * can be installed
 #. TRANSLATORS: button text in the header when firmware
 #. * can be live-installed
-#. TRANSLATORS: button text in the header when an application
-#. * can be live-updated
 #: ../src/gs-shell-details.c:201 ../src/gs-shell-details.c:227
-#: ../src/gs-shell-details.c:232 ../src/gs-shell-details.ui.h:2
-#: ../src/gs-upgrade-banner.ui.h:4
+#: ../src/gs-shell-details.ui.h:2 ../src/gs-upgrade-banner.ui.h:4
 msgid "_Install"
 msgstr "_Инсталирај"
 
@@ -822,6 +819,12 @@ msgstr "_Инсталирај"
 msgid "_Installing"
 msgstr "_Инсталирам"
 
+#. TRANSLATORS: button text in the header when an application
+#. * can be live-updated
+#: ../src/gs-shell-details.c:232
+msgid "_Update"
+msgstr "Аж_урирај"
+
 #. TRANSLATORS: this is a button that allows the apps to
 #. * be installed.
 #. * The ellipsis indicates that further steps are required,
@@ -2865,9 +2868,6 @@ msgctxt "Menu subcategory of Add-ons"
 msgid "Localization"
 msgstr "Превод"
 
-#~ msgid "_Update"
-#~ msgstr "Аж_урирај"
-
 #~ msgid "A previous update was unfinished."
 #~ msgstr "Претходно ажурирање је остало недовршено."
 
diff --git a/src/Makefile.am b/src/Makefile.am
index eb13f14..132fa71 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,34 +28,34 @@ desktop_in_files =                                  \
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 
 UI_FILES =                                             \
-       app-folder-dialog.ui                            \
-       menus.ui                                        \
-       app-tile.ui                                     \
-       category-tile.ui                                \
-       feature-tile.ui                                 \
        gnome-software.ui                               \
        gs-app-addon-row.ui                             \
+       gs-app-folder-dialog.ui                         \
        gs-app-row.ui                                   \
+       gs-app-tile.ui                                  \
+       gs-category-tile.ui                             \
+       gs-feature-tile.ui                              \
        gs-first-run-dialog.ui                          \
        gs-history-dialog.ui                            \
+       gs-menus.ui                                     \
+       gs-popular-tile.ui                              \
        gs-review-dialog.ui                             \
        gs-review-histogram.ui                          \
        gs-review-row.ui                                \
+       gs-screenshot-image.ui                          \
        gs-shell-category.ui                            \
-       gs-shell-extras.ui                              \
        gs-shell-details.ui                             \
+       gs-shell-extras.ui                              \
        gs-shell-installed.ui                           \
        gs-shell-moderate.ui                            \
        gs-shell-overview.ui                            \
        gs-shell-search.ui                              \
        gs-shell-updates.ui                             \
-       gs-sources-dialog.ui                            \
        gs-sources-dialog-row.ui                        \
+       gs-sources-dialog.ui                            \
        gs-star-widget.ui                               \
        gs-update-dialog.ui                             \
-       gs-upgrade-banner.ui                            \
-       screenshot-image.ui                             \
-       popular-tile.ui
+       gs-upgrade-banner.ui
 
 dbusservicedir = $(datadir)/dbus-1/services
 dbusservice_DATA =                                     \
@@ -163,8 +163,6 @@ gnome_software_SOURCES =                            \
        gs-screenshot-image.h                           \
        gs-shell.c                                      \
        gs-shell.h                                      \
-       gs-markdown.c                                   \
-       gs-markdown.h                                   \
        gs-shell-details.c                              \
        gs-shell-details.h                              \
        gs-shell-category.c                             \
@@ -286,7 +284,6 @@ check_PROGRAMS =                                            \
 gs_self_test_SOURCES =                                         \
        gs-app.c                                                \
        gs-category.c                                           \
-       gs-markdown.c                                           \
        gs-os-release.c                                         \
        gs-plugin-loader-sync.c                                 \
        gs-plugin-loader.c                                      \
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index c567d48..bc01ff5 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -2,30 +2,30 @@
 <gresources>
  <gresource prefix="/org/gnome/Software">
   <file preprocess="xml-stripblanks">gnome-software.ui</file>
-  <file preprocess="xml-stripblanks" alias="gtk/menus.ui">menus.ui</file>
-  <file preprocess="xml-stripblanks">popular-tile.ui</file>
-  <file preprocess="xml-stripblanks">feature-tile.ui</file>
-  <file preprocess="xml-stripblanks">category-tile.ui</file>
-  <file preprocess="xml-stripblanks">app-tile.ui</file>
-  <file preprocess="xml-stripblanks">app-folder-dialog.ui</file>
-  <file preprocess="xml-stripblanks">screenshot-image.ui</file>
+  <file preprocess="xml-stripblanks" alias="gtk/menus.ui">gs-menus.ui</file>
   <file preprocess="xml-stripblanks">gs-app-addon-row.ui</file>
+  <file preprocess="xml-stripblanks">gs-app-folder-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-app-row.ui</file>
+  <file preprocess="xml-stripblanks">gs-app-tile.ui</file>
+  <file preprocess="xml-stripblanks">gs-category-tile.ui</file>
+  <file preprocess="xml-stripblanks">gs-feature-tile.ui</file>
   <file preprocess="xml-stripblanks">gs-first-run-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-history-dialog.ui</file>
+  <file preprocess="xml-stripblanks">gs-popular-tile.ui</file>
   <file preprocess="xml-stripblanks">gs-review-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-review-histogram.ui</file>
   <file preprocess="xml-stripblanks">gs-review-row.ui</file>
+  <file preprocess="xml-stripblanks">gs-screenshot-image.ui</file>
   <file preprocess="xml-stripblanks">gs-shell-category.ui</file>
-  <file preprocess="xml-stripblanks">gs-shell-extras.ui</file>
   <file preprocess="xml-stripblanks">gs-shell-details.ui</file>
+  <file preprocess="xml-stripblanks">gs-shell-extras.ui</file>
   <file preprocess="xml-stripblanks">gs-shell-installed.ui</file>
   <file preprocess="xml-stripblanks">gs-shell-moderate.ui</file>
   <file preprocess="xml-stripblanks">gs-shell-overview.ui</file>
   <file preprocess="xml-stripblanks">gs-shell-search.ui</file>
   <file preprocess="xml-stripblanks">gs-shell-updates.ui</file>
-  <file preprocess="xml-stripblanks">gs-sources-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-sources-dialog-row.ui</file>
+  <file preprocess="xml-stripblanks">gs-sources-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-star-widget.ui</file>
   <file preprocess="xml-stripblanks">gs-update-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-upgrade-banner.ui</file>
diff --git a/src/gs-app-folder-dialog.c b/src/gs-app-folder-dialog.c
index 2b55179..f6b3d76 100644
--- a/src/gs-app-folder-dialog.c
+++ b/src/gs-app-folder-dialog.c
@@ -146,7 +146,7 @@ gs_app_folder_dialog_class_init (GsAppFolderDialogClass *klass)
 
        widget_class->destroy = gs_app_folder_dialog_destroy;
 
-       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Software/app-folder-dialog.ui");
+       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Software/gs-app-folder-dialog.ui");
 
        gtk_widget_class_bind_template_child (widget_class, GsAppFolderDialog, cancel_button);
        gtk_widget_class_bind_template_child (widget_class, GsAppFolderDialog, done_button);
diff --git a/src/app-folder-dialog.ui b/src/gs-app-folder-dialog.ui
similarity index 100%
rename from src/app-folder-dialog.ui
rename to src/gs-app-folder-dialog.ui
diff --git a/src/gs-app-row.c b/src/gs-app-row.c
index 623d840..aaff113 100644
--- a/src/gs-app-row.c
+++ b/src/gs-app-row.c
@@ -27,7 +27,6 @@
 
 #include "gs-app-row.h"
 #include "gs-star-widget.h"
-#include "gs-markdown.h"
 #include "gs-progress-button.h"
 #include "gs-utils.h"
 #include "gs-folders.h"
@@ -85,6 +84,17 @@ gs_app_row_get_description (GsAppRow *app_row)
        const gchar *tmp = NULL;
        g_autofree gchar *escaped = NULL;
 
+#if 0
+       /* convert the markdown update description into PangoMarkup */
+       if (priv->show_update &&
+           (gs_app_get_state (priv->app) == AS_APP_STATE_UPDATABLE ||
+            gs_app_get_state (priv->app) == AS_APP_STATE_UPDATABLE_LIVE)) {
+               tmp = gs_app_get_update_details (priv->app);
+               if (tmp != NULL && tmp[0] != '\0')
+                       return g_string_new (tmp);
+       }
+#endif
+
        if (gs_app_get_state (priv->app) == AS_APP_STATE_UNAVAILABLE)
                return g_string_new (gs_app_get_summary_missing (priv->app));
 
diff --git a/src/gs-app-tile.c b/src/gs-app-tile.c
index 5d58eb0..c9001c8 100644
--- a/src/gs-app-tile.c
+++ b/src/gs-app-tile.c
@@ -276,7 +276,7 @@ gs_app_tile_class_init (GsAppTileClass *klass)
                                  -1, G_MAXINT, -1,
                                  G_PARAM_READWRITE));
 
-       gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/app-tile.ui");
+       gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-app-tile.ui");
 
        gtk_widget_class_bind_template_child (widget_class, GsAppTile, image);
        gtk_widget_class_bind_template_child (widget_class, GsAppTile, name);
diff --git a/src/app-tile.ui b/src/gs-app-tile.ui
similarity index 100%
rename from src/app-tile.ui
rename to src/gs-app-tile.ui
diff --git a/src/gs-app.c b/src/gs-app.c
index 2770a03..3fc93e3 100644
--- a/src/gs-app.c
+++ b/src/gs-app.c
@@ -68,12 +68,13 @@ struct _GsApp
        gchar                   *summary_missing;
        gchar                   *description;
        GsAppQuality             description_quality;
+       GError                  *last_error;
        GPtrArray               *screenshots;
        GPtrArray               *categories;
        GPtrArray               *keywords;
        GHashTable              *urls;
-       gchar                   *licence;
-       GsAppQuality             licence_quality;
+       gchar                   *license;
+       GsAppQuality             license_quality;
        gchar                   **menu_path;
        gchar                   *origin;
        gchar                   *origin_ui;
@@ -89,6 +90,7 @@ struct _GsApp
        guint64                  size;
        AsAppKind                kind;
        AsAppState               state;
+       AsAppState               state_recover;
        guint                    progress;
        GHashTable              *metadata;
        GdkPixbuf               *pixbuf;
@@ -101,7 +103,7 @@ struct _GsApp
        guint64                  kudos;
        gboolean                 to_be_installed;
        AsAppQuirk               quirk;
-       gboolean                 licence_is_free;
+       gboolean                 license_is_free;
        GsApp                   *runtime;
        GFile                   *local_file;
 };
@@ -130,6 +132,34 @@ G_DEFINE_TYPE (GsApp, gs_app, G_TYPE_OBJECT)
 G_DEFINE_QUARK (gs-app-error-quark, gs_app_error)
 
 /**
+ * gs_app_kv_lpad:
+ **/
+static void
+gs_app_kv_lpad (GString *str, const gchar *key, const gchar *value)
+{
+       guint i;
+       g_string_append_printf (str, "  %s:", key);
+       for (i = strlen (key); i < 18; i++)
+               g_string_append (str, " ");
+       g_string_append_printf (str, " %s\n", value);
+}
+
+/**
+ * gs_app_kv_printf:
+ **/
+G_GNUC_PRINTF (3, 4)
+static void
+gs_app_kv_printf (GString *str, const gchar *key, const gchar *fmt, ...)
+{
+       va_list args;
+       g_autofree gchar *tmp = NULL;
+       va_start (args, fmt);
+       tmp = g_strdup_vprintf (fmt, args);
+       va_end (args);
+       gs_app_kv_lpad (str, key, tmp);
+}
+
+/**
  * gs_app_to_string:
  **/
 gchar *
@@ -146,108 +176,107 @@ gs_app_to_string (GsApp *app)
        g_return_val_if_fail (GS_IS_APP (app), NULL);
 
        str = g_string_new ("GsApp:\n");
-       g_string_append_printf (str, "\tkind:\t%s\n",
-                               as_app_kind_to_string (app->kind));
-       g_string_append_printf (str, "\tcompulsory:\t%s\n",
-                               gs_app_has_quirk (app, AS_APP_QUIRK_COMPULSORY)
-                               ? "True" : "False");
-       g_string_append_printf (str, "\tstate:\t%s\n",
-                               as_app_state_to_string (app->state));
+       gs_app_kv_lpad (str, "kind", as_app_kind_to_string (app->kind));
+       if (app->last_error != NULL)
+               gs_app_kv_lpad (str, "last-error", app->last_error->message);
+       gs_app_kv_lpad (str, "compulsory",
+                       gs_app_has_quirk (app, AS_APP_QUIRK_COMPULSORY)
+                       ? "True" : "False");
+       gs_app_kv_lpad (str, "state", as_app_state_to_string (app->state));
        if (app->progress > 0)
-               g_string_append_printf (str, "\tprogress:\t%i%%\n", app->progress);
+               gs_app_kv_printf (str, "progress", "%i%%", app->progress);
        if (app->id != NULL)
-               g_string_append_printf (str, "\tid:\t%s\n", app->id);
+               gs_app_kv_lpad (str, "id", app->id);
        if ((app->kudos & GS_APP_KUDO_MY_LANGUAGE) > 0)
-               g_string_append (str, "\tkudo:\tmy-language\n");
+               gs_app_kv_lpad (str, "kudo", "my-language");
        if ((app->kudos & GS_APP_KUDO_RECENT_RELEASE) > 0)
-               g_string_append (str, "\tkudo:\trecent-release\n");
+               gs_app_kv_lpad (str, "kudo", "recent-release");
        if ((app->kudos & GS_APP_KUDO_FEATURED_RECOMMENDED) > 0)
-               g_string_append (str, "\tkudo:\tfeatured-recommended\n");
+               gs_app_kv_lpad (str, "kudo", "featured-recommended");
        if ((app->kudos & GS_APP_KUDO_MODERN_TOOLKIT) > 0)
-               g_string_append (str, "\tkudo:\tmodern-toolkit\n");
+               gs_app_kv_lpad (str, "kudo", "modern-toolkit");
        if ((app->kudos & GS_APP_KUDO_SEARCH_PROVIDER) > 0)
-               g_string_append (str, "\tkudo:\tsearch-provider\n");
+               gs_app_kv_lpad (str, "kudo", "search-provider");
        if ((app->kudos & GS_APP_KUDO_INSTALLS_USER_DOCS) > 0)
-               g_string_append (str, "\tkudo:\tinstalls-user-docs\n");
+               gs_app_kv_lpad (str, "kudo", "installs-user-docs");
        if ((app->kudos & GS_APP_KUDO_USES_NOTIFICATIONS) > 0)
-               g_string_append (str, "\tkudo:\tuses-notifications\n");
+               gs_app_kv_lpad (str, "kudo", "uses-notifications");
        if ((app->kudos & GS_APP_KUDO_USES_APP_MENU) > 0)
-               g_string_append (str, "\tkudo:\tuses-app-menu\n");
+               gs_app_kv_lpad (str, "kudo", "uses-app-menu");
        if ((app->kudos & GS_APP_KUDO_HAS_KEYWORDS) > 0)
-               g_string_append (str, "\tkudo:\thas-keywords\n");
+               gs_app_kv_lpad (str, "kudo", "has-keywords");
        if ((app->kudos & GS_APP_KUDO_HAS_SCREENSHOTS) > 0)
-               g_string_append (str, "\tkudo:\thas-screenshots\n");
+               gs_app_kv_lpad (str, "kudo", "has-screenshots");
        if ((app->kudos & GS_APP_KUDO_POPULAR) > 0)
-               g_string_append (str, "\tkudo:\tpopular\n");
+               gs_app_kv_lpad (str, "kudo", "popular");
        if ((app->kudos & GS_APP_KUDO_IBUS_HAS_SYMBOL) > 0)
-               g_string_append (str, "\tkudo:\tibus-has-symbol\n");
+               gs_app_kv_lpad (str, "kudo", "ibus-has-symbol");
        if ((app->kudos & GS_APP_KUDO_PERFECT_SCREENSHOTS) > 0)
-               g_string_append (str, "\tkudo:\tperfect-screenshots\n");
+               gs_app_kv_lpad (str, "kudo", "perfect-screenshots");
        if ((app->kudos & GS_APP_KUDO_HIGH_CONTRAST) > 0)
-               g_string_append (str, "\tkudo:\thigh-contrast\n");
+               gs_app_kv_lpad (str, "kudo", "high-contrast");
        if ((app->kudos & GS_APP_KUDO_HI_DPI_ICON) > 0)
-               g_string_append (str, "\tkudo:\thi-dpi-icon\n");
-       g_string_append_printf (str, "\tkudo-percentage:\t%i\n",
-                               gs_app_get_kudos_percentage (app));
+               gs_app_kv_lpad (str, "kudo", "hi-dpi-icon");
+       gs_app_kv_printf (str, "kudo-percentage", "%i",
+                         gs_app_get_kudos_percentage (app));
        if (app->name != NULL)
-               g_string_append_printf (str, "\tname:\t%s\n", app->name);
+               gs_app_kv_lpad (str, "name", app->name);
        if (app->icon != NULL) {
-               g_string_append_printf (str, "\ticon-kind:\t%s\n",
-                                       as_icon_kind_to_string (as_icon_get_kind (app->icon)));
+               gs_app_kv_lpad (str, "icon-kind",
+                               as_icon_kind_to_string (as_icon_get_kind (app->icon)));
                if (as_icon_get_name (app->icon) != NULL)
-                       g_string_append_printf (str, "\ticon-name:\t%s\n",
-                                               as_icon_get_name (app->icon));
+                       gs_app_kv_lpad (str, "icon-name",
+                                       as_icon_get_name (app->icon));
                if (as_icon_get_prefix (app->icon) != NULL)
-                       g_string_append_printf (str, "\ticon-prefix:\t%s\n",
-                                               as_icon_get_prefix (app->icon));
+                       gs_app_kv_lpad (str, "icon-prefix",
+                                       as_icon_get_prefix (app->icon));
                if (as_icon_get_filename (app->icon) != NULL)
-                       g_string_append_printf (str, "\ticon-filename:\t%s\n",
-                                               as_icon_get_filename (app->icon));
-       }
-       if (app->match_value != 0) {
-               g_string_append_printf (str, "\tmatch-value:\t%05x\n",
-                                       app->match_value);
+                       gs_app_kv_lpad (str, "icon-filename",
+                                       as_icon_get_filename (app->icon));
        }
+       if (app->match_value != 0)
+               gs_app_kv_printf (str, "match-value", "%05x", app->match_value);
        if (app->version != NULL)
-               g_string_append_printf (str, "\tversion:\t%s\n", app->version);
+               gs_app_kv_lpad (str, "version", app->version);
        if (app->version_ui != NULL)
-               g_string_append_printf (str, "\tversion-ui:\t%s\n", app->version_ui);
+               gs_app_kv_lpad (str, "version-ui", app->version_ui);
        if (app->update_version != NULL)
-               g_string_append_printf (str, "\tupdate-version:\t%s\n", app->update_version);
+               gs_app_kv_lpad (str, "update-version", app->update_version);
        if (app->update_version_ui != NULL)
-               g_string_append_printf (str, "\tupdate-version-ui:\t%s\n", app->update_version_ui);
-       if (app->update_details != NULL) {
-               g_string_append_printf (str, "\tupdate-details:\t%s\n",
-                                       app->update_details);
-       }
+               gs_app_kv_lpad (str, "update-version-ui", app->update_version_ui);
+       if (app->update_details != NULL)
+               gs_app_kv_lpad (str, "update-details", app->update_details);
        if (app->update_urgency != AS_URGENCY_KIND_UNKNOWN) {
-               g_string_append_printf (str, "\tupdate-urgency:\t%i\n",
-                                       app->update_urgency);
+               gs_app_kv_printf (str, "update-urgency", "%i",
+                                 app->update_urgency);
        }
        if (app->summary != NULL)
-               g_string_append_printf (str, "\tsummary:\t%s\n", app->summary);
+               gs_app_kv_lpad (str, "summary", app->summary);
        if (app->description != NULL)
-               g_string_append_printf (str, "\tdescription:\t%s\n", app->description);
-       g_string_append_printf (str, "\tprovenance:\t%s\n",
-                               gs_app_has_quirk (app,
-                                                 AS_APP_QUIRK_PROVENANCE) ? "yes" : "no");
+               gs_app_kv_lpad (str, "description", app->description);
        for (i = 0; i < app->screenshots->len; i++) {
+               g_autofree gchar *key = NULL;
                ss = g_ptr_array_index (app->screenshots, i);
                tmp = as_screenshot_get_caption (ss, NULL);
                im = as_screenshot_get_image (ss, 0, 0);
                if (im == NULL)
                        continue;
-               g_string_append_printf (str, "\tscreenshot-%02i:\t%s [%s]\n",
-                                       i, as_image_get_url (im),
-                                       tmp != NULL ? tmp : "<none>");
+               key = g_strdup_printf ("screenshot-%02i", i);
+               gs_app_kv_printf (str, key, "%s [%s]",
+                                 as_image_get_url (im),
+                                 tmp != NULL ? tmp : "<none>");
        }
        for (i = 0; i < app->sources->len; i++) {
+               g_autofree gchar *key = NULL;
                tmp = g_ptr_array_index (app->sources, i);
-               g_string_append_printf (str, "\tsource-%02i:\t%s\n", i, tmp);
+               key = g_strdup_printf ("source-%02i", i);
+               gs_app_kv_lpad (str, key, tmp);
        }
        for (i = 0; i < app->source_ids->len; i++) {
+               g_autofree gchar *key = NULL;
                tmp = g_ptr_array_index (app->source_ids, i);
-               g_string_append_printf (str, "\tsource-id-%02i:\t%s\n", i, tmp);
+               key = g_strdup_printf ("source-id-%02i", i);
+               gs_app_kv_lpad (str, key, tmp);
        }
        if (app->local_file != NULL) {
                g_autofree gchar *fn = g_file_get_path (app->local_file);
@@ -255,66 +284,65 @@ gs_app_to_string (GsApp *app)
        }
        tmp = g_hash_table_lookup (app->urls, as_url_kind_to_string (AS_URL_KIND_HOMEPAGE));
        if (tmp != NULL)
-               g_string_append_printf (str, "\turl{homepage}:\t%s\n", tmp);
-       if (app->licence != NULL)
-               g_string_append_printf (str, "\tlicence:\t%s\n", app->licence);
-       g_string_append_printf (str, "\topen source:\t%s\n",
-                               gs_app_get_license_is_free (app) ? "yes" : "no");
+               gs_app_kv_lpad (str, "url{homepage}", tmp);
+       if (app->license != NULL)
+               gs_app_kv_lpad (str, "license", app->license);
        if (app->management_plugin != NULL)
-               g_string_append_printf (str, "\tmanagement-plugin:\t%s\n", app->management_plugin);
+               gs_app_kv_lpad (str, "management-plugin", app->management_plugin);
        if (app->summary_missing != NULL)
-               g_string_append_printf (str, "\tsummary-missing:\t%s\n", app->summary_missing);
+               gs_app_kv_lpad (str, "summary-missing", app->summary_missing);
        if (app->menu_path != NULL &&
            app->menu_path[0] != NULL &&
            app->menu_path[0][0] != '\0') {
                g_autofree gchar *path = g_strjoinv (" → ", app->menu_path);
-               g_string_append_printf (str, "\tmenu-path:\t%s\n", path);
+               gs_app_kv_lpad (str, "menu-path", path);
        }
        if (app->origin != NULL && app->origin[0] != '\0')
-               g_string_append_printf (str, "\torigin:\t%s\n", app->origin);
+               gs_app_kv_lpad (str, "origin", app->origin);
        if (app->origin_ui != NULL && app->origin_ui[0] != '\0')
-               g_string_append_printf (str, "\torigin-ui:\t%s\n", app->origin_ui);
+               gs_app_kv_lpad (str, "origin-ui", app->origin_ui);
        if (app->rating != -1)
-               g_string_append_printf (str, "\trating:\t%i\n", app->rating);
+               gs_app_kv_printf (str, "rating", "%i", app->rating);
        if (app->review_ratings != NULL) {
                for (i = 0; i < app->review_ratings->len; i++) {
                        gint rat = g_array_index (app->review_ratings, gint, i);
-                       g_string_append_printf (str, "\treview-rating:\t[%i:%i]\n",
-                                               i, rat);
+                       gs_app_kv_printf (str, "review-rating", "[%i:%i]",
+                                         i, rat);
                }
        }
        if (app->reviews != NULL)
-               g_string_append_printf (str, "\treviews:\t%i\n", app->reviews->len);
+               gs_app_kv_printf (str, "reviews", "%i", app->reviews->len);
        if (app->pixbuf != NULL)
-               g_string_append_printf (str, "\tpixbuf:\t%p\n", app->pixbuf);
+               gs_app_kv_printf (str, "pixbuf", "%p", app->pixbuf);
        if (app->install_date != 0) {
-               g_string_append_printf (str, "\tinstall-date:\t%"
-                                       G_GUINT64_FORMAT "\n",
-                                       app->install_date);
+               gs_app_kv_printf (str, "install-date", "%"
+                                 G_GUINT64_FORMAT "",
+                                 app->install_date);
        }
        if (app->size != 0) {
-               g_string_append_printf (str, "\tsize:\t%" G_GUINT64_FORMAT "k\n",
-                                       app->size / 1024);
+               gs_app_kv_printf (str, "size", "%" G_GUINT64_FORMAT "k",
+                                 app->size / 1024);
        }
        if (app->related->len > 0)
-               g_string_append_printf (str, "\trelated:\t%i\n", app->related->len);
+               gs_app_kv_printf (str, "related", "%i", app->related->len);
        if (app->history->len > 0)
-               g_string_append_printf (str, "\thistory:\t%i\n", app->history->len);
+               gs_app_kv_printf (str, "history", "%i", app->history->len);
        for (i = 0; i < app->categories->len; i++) {
                tmp = g_ptr_array_index (app->categories, i);
-               g_string_append_printf (str, "\tcategory:\t%s\n", tmp);
+               gs_app_kv_lpad (str, "category", tmp);
        }
        if (app->keywords != NULL) {
                for (i = 0; i < app->keywords->len; i++) {
                        tmp = g_ptr_array_index (app->keywords, i);
-                       g_string_append_printf (str, "\tkeyword:\t%s\n", tmp);
+                       gs_app_kv_lpad (str, "keyword", tmp);
                }
        }
        keys = g_hash_table_get_keys (app->metadata);
        for (l = keys; l != NULL; l = l->next) {
+               g_autofree gchar *key = NULL;
+               key = g_strdup_printf ("{%s}", (const gchar *) l->data);
                tmp = g_hash_table_lookup (app->metadata, l->data);
-               g_string_append_printf (str, "\t{%s}:\t%s\n",
-                                       (const gchar *) l->data, tmp);
+               gs_app_kv_lpad (str, key, tmp);
        }
        g_list_free (keys);
 
@@ -417,6 +445,24 @@ gs_app_get_progress (GsApp *app)
 }
 
 /**
+ * gs_app_set_state_recover:
+ *
+ * Sets the application state to the last status value that was not
+ * transient.
+ */
+void
+gs_app_set_state_recover (GsApp *app)
+{
+       if (app->state_recover == AS_APP_STATE_UNKNOWN)
+               return;
+       if (app->state_recover == app->state)
+               return;
+       app->state = app->state_recover;
+       app->state_recover = AS_APP_STATE_UNKNOWN;
+       gs_app_queue_notify (app, "state");
+}
+
+/**
  * gs_app_set_state_internal:
  */
 static gboolean
@@ -466,6 +512,8 @@ gs_app_set_state_internal (GsApp *app, AsAppState state)
                /* installing has to go into an stable state */
                if (state == AS_APP_STATE_UNKNOWN ||
                    state == AS_APP_STATE_INSTALLED ||
+                   state == AS_APP_STATE_UPDATABLE ||
+                   state == AS_APP_STATE_UPDATABLE_LIVE ||
                    state == AS_APP_STATE_AVAILABLE)
                        state_change_ok = TRUE;
                break;
@@ -522,6 +570,22 @@ gs_app_set_state_internal (GsApp *app, AsAppState state)
            state == AS_APP_STATE_AVAILABLE)
                app->install_date = 0;
 
+       /* save this to simplify error handling in the plugins */
+       switch (state) {
+       case AS_APP_STATE_INSTALLING:
+       case AS_APP_STATE_REMOVING:
+               /* transient, so ignore */
+               break;
+       default:
+               g_debug ("non-transient state now %s",
+                        as_app_state_to_string (state));
+               app->state_recover = state;
+
+               /* clear the error as the application has changed state */
+               g_clear_error (&app->last_error);
+               break;
+       }
+
        return TRUE;
 }
 
@@ -1281,7 +1345,7 @@ const gchar *
 gs_app_get_license (GsApp *app)
 {
        g_return_val_if_fail (GS_IS_APP (app), NULL);
-       return app->licence;
+       return app->license;
 }
 
 /**
@@ -1291,7 +1355,7 @@ gboolean
 gs_app_get_license_is_free (GsApp *app)
 {
        g_return_val_if_fail (GS_IS_APP (app), FALSE);
-       return app->licence_is_free;
+       return app->license_is_free;
 }
 
 /**
@@ -1318,30 +1382,30 @@ gs_app_get_license_token_is_nonfree (const gchar *token)
  * gs_app_set_license:
  */
 void
-gs_app_set_license (GsApp *app, GsAppQuality quality, const gchar *licence)
+gs_app_set_license (GsApp *app, GsAppQuality quality, const gchar *license)
 {
        GString *urld;
        guint i;
        g_auto(GStrv) tokens = NULL;
 
        /* only save this if the data is sufficiently high quality */
-       if (quality <= app->licence_quality)
+       if (quality <= app->license_quality)
                return;
-       app->licence_quality = quality;
+       app->license_quality = quality;
 
        g_return_if_fail (GS_IS_APP (app));
 
        /* assume free software until we find an unmatched SPDX token */
-       app->licence_is_free = TRUE;
+       app->license_is_free = TRUE;
 
        /* tokenize the license string and URLify any SPDX IDs */
-       urld = g_string_sized_new (strlen (licence) + 1);
-       tokens = as_utils_spdx_license_tokenize (licence);
+       urld = g_string_sized_new (strlen (license) + 1);
+       tokens = as_utils_spdx_license_tokenize (license);
        for (i = 0; tokens[i] != NULL; i++) {
 
                /* translated join */
                if (g_strcmp0 (tokens[i], "&") == 0) {
-                       /* TRANSLATORS: This is how we join the licences and can
+                       /* TRANSLATORS: This is how we join the licenses and can
                         * be considered a "Conjunctive AND Operator" according
                         * to the SPDX specification. For example:
                         * "LGPL-2.1 and MIT and BSD-2-Clause" */
@@ -1349,7 +1413,7 @@ gs_app_set_license (GsApp *app, GsAppQuality quality, const gchar *licence)
                        continue;
                }
                if (g_strcmp0 (tokens[i], "|") == 0) {
-                       /* TRANSLATORS: This is how we join the licences and can
+                       /* TRANSLATORS: This is how we join the licenses and can
                         * be considered a "Disjunctive OR Operator" according
                         * to the SPDX specification. For example:
                         * "LGPL-2.1 or MIT" */
@@ -1359,9 +1423,9 @@ gs_app_set_license (GsApp *app, GsAppQuality quality, const gchar *licence)
 
                /* do the best we can */
                if (gs_app_get_license_token_is_nonfree (tokens[i])) {
-                       g_debug ("nonfree licence from %s: '%s'",
+                       g_debug ("nonfree license from %s: '%s'",
                                 gs_app_get_id (app), tokens[i]);
-                       app->licence_is_free = FALSE;
+                       app->license_is_free = FALSE;
                }
 
                /* legacy literal text */
@@ -1427,8 +1491,8 @@ gs_app_set_license (GsApp *app, GsAppQuality quality, const gchar *licence)
                g_string_append (urld, tokens[i]);
        }
 
-       g_free (app->licence);
-       app->licence = g_string_free (urld, FALSE);
+       g_free (app->license);
+       app->license = g_string_free (urld, FALSE);
 }
 
 /**
@@ -1777,6 +1841,7 @@ void
 gs_app_set_metadata (GsApp *app, const gchar *key, const gchar *value)
 {
        const gchar *found;
+       GString *str;
 
        g_return_if_fail (GS_IS_APP (app));
 
@@ -1795,9 +1860,11 @@ gs_app_set_metadata (GsApp *app, const gchar *key, const gchar *value)
                           key, found, value);
                return;
        }
+       str = g_string_new (value);
+       as_utils_string_replace (str, "@datadir@", DATADIR);
        g_hash_table_insert (app->metadata,
                             g_strdup (key),
-                            g_strdup (value));
+                            g_string_free (str, FALSE));
 }
 
 /**
@@ -1824,10 +1891,8 @@ gs_app_add_addon (GsApp *app, GsApp *addon)
 
        id = gs_app_get_id (addon);
        found = g_hash_table_lookup (app->addons_hash, id);
-       if (found != NULL) {
-               g_debug ("Already added %s as an addon", id);
+       if (found != NULL)
                return;
-       }
        g_hash_table_insert (app->addons_hash, g_strdup (id), GINT_TO_POINTER (1));
 
        g_ptr_array_add (app->addons, g_object_ref (addon));
@@ -2092,102 +2157,6 @@ gs_app_add_quirk (GsApp *app, AsAppQuirk quirk)
 }
 
 /**
- * gs_app_subsume:
- *
- * Imports all the useful data from @other into @app.
- *
- * IMPORTANT: This method can be called from a thread as the notify signals
- * are not sent.
- **/
-void
-gs_app_subsume (GsApp *app, GsApp *other)
-{
-       const gchar *tmp;
-       GList *keys;
-       GList *l;
-       GsApp *app_tmp;
-       guint i;
-
-       g_return_if_fail (GS_IS_APP (app));
-       g_return_if_fail (GS_IS_APP (other));
-       g_return_if_fail (app != other);
-
-       /* an [updatable] installable package is more information than
-        * just the fact that something is installed */
-       if (other->state == AS_APP_STATE_UPDATABLE &&
-           app->state == AS_APP_STATE_INSTALLED) {
-               /* we have to do the little dance to appease the
-                * angry gnome controlling the state-machine */
-               gs_app_set_state_internal (app, AS_APP_STATE_UNKNOWN);
-               gs_app_set_state_internal (app, AS_APP_STATE_UPDATABLE);
-       }
-
-       /* save any properties we already know */
-       if (other->id != NULL)
-               gs_app_set_id (app, other->id);
-       if (other->sources->len > 0)
-               gs_app_set_sources (app, other->sources);
-       if (other->project_group != NULL)
-               gs_app_set_project_group (app, other->project_group);
-       if (other->name != NULL)
-               gs_app_set_name (app, other->name_quality, other->name);
-       if (other->summary != NULL)
-               gs_app_set_summary (app, other->summary_quality, other->summary);
-       if (other->match_value != 0)
-               gs_app_set_match_value (app, other->match_value);
-       if (other->description != NULL)
-               gs_app_set_description (app, other->description_quality, other->description);
-       if (other->update_details != NULL)
-               gs_app_set_update_details (app, other->update_details);
-       if (other->management_plugin != NULL &&
-           app->management_plugin != NULL &&
-           g_strcmp0 (other->management_plugin, app->management_plugin) != 0) {
-               g_warning ("%s changing management plugin %s->%s",
-                          app->id,
-                          app->management_plugin,
-                          other->management_plugin);
-       }
-       if (other->update_urgency != AS_URGENCY_KIND_UNKNOWN)
-               gs_app_set_update_urgency (app, other->update_urgency);
-       if (other->update_version != NULL)
-               gs_app_set_update_version_internal (app, other->update_version);
-       if (other->pixbuf != NULL)
-               gs_app_set_pixbuf (app, other->pixbuf);
-       if (app->categories != other->categories) {
-               for (i = 0; i < other->categories->len; i++) {
-                       tmp = g_ptr_array_index (other->categories, i);
-                       gs_app_add_category (app, tmp);
-               }
-       }
-       if (other->licence != NULL) {
-               /* can't use setter as the incoming text is lost */
-               g_free (app->licence);
-               app->licence = g_strdup (other->licence);
-               app->licence_is_free = other->licence_is_free;
-       }
-       if (other->origin != NULL)
-               gs_app_set_origin (app, other->origin);
-       for (i = 0; i < other->related->len; i++) {
-               app_tmp = g_ptr_array_index (other->related, i);
-               gs_app_add_related (app, app_tmp);
-       }
-       app->kudos |= other->kudos;
-       app->quirk |= other->quirk;
-
-       /* copy metadata from @other to @app unless the app already has a key
-        * of that name */
-       keys = g_hash_table_get_keys (other->metadata);
-       for (l = keys; l != NULL; l = l->next) {
-               tmp = g_hash_table_lookup (app->metadata, l->data);
-               if (tmp != NULL)
-                       continue;
-               tmp = g_hash_table_lookup (other->metadata, l->data);
-               gs_app_set_metadata (app, l->data, tmp);
-       }
-       g_list_free (keys);
-}
-
-/**
  * gs_app_set_match_value:
  */
 void
@@ -2208,6 +2177,25 @@ gs_app_get_match_value (GsApp *app)
 }
 
 /**
+ * gs_app_get_last_error:
+ */
+GError *
+gs_app_get_last_error (GsApp *app)
+{
+       return app->last_error;
+}
+
+/**
+ * gs_app_set_last_error:
+ */
+void
+gs_app_set_last_error (GsApp *app, GError *error)
+{
+       g_clear_error (&app->last_error);
+       app->last_error = g_error_copy (error);
+}
+
+/**
  * gs_app_get_property:
  */
 static void
@@ -2315,6 +2303,7 @@ gs_app_dispose (GObject *object)
        g_clear_object (&app->icon);
        g_clear_object (&app->runtime);
        g_clear_object (&app->pixbuf);
+       g_clear_object (&app->local_file);
 
        g_clear_pointer (&app->addons, g_ptr_array_unref);
        g_clear_pointer (&app->history, g_ptr_array_unref);
@@ -2337,7 +2326,7 @@ gs_app_finalize (GObject *object)
        g_free (app->id);
        g_free (app->name);
        g_hash_table_unref (app->urls);
-       g_free (app->licence);
+       g_free (app->license);
        g_strfreev (app->menu_path);
        g_free (app->origin);
        g_free (app->origin_ui);
@@ -2359,8 +2348,8 @@ gs_app_finalize (GObject *object)
        g_ptr_array_unref (app->categories);
        if (app->keywords != NULL)
                g_ptr_array_unref (app->keywords);
-       if (app->local_file != NULL)
-               g_object_unref (app->local_file);
+       if (app->last_error != NULL)
+               g_error_free (app->last_error);
 
        G_OBJECT_CLASS (gs_app_parent_class)->finalize (object);
 }
diff --git a/src/gs-app.h b/src/gs-app.h
index 5e6d566..ce13ae0 100644
--- a/src/gs-app.h
+++ b/src/gs-app.h
@@ -73,14 +73,12 @@ typedef enum {
 
 #define        GS_APP_KUDOS_WEIGHT_TO_PERCENTAGE(w)    (w * 20)
 
-#if !AS_CHECK_VERSION(0,5,14)
-#define AS_APP_QUIRK_NEEDS_REBOOT              (1 << 4)
-#define AS_APP_QUIRK_NOT_REVIEWABLE            (1 << 5)
+#if !AS_CHECK_VERSION(0,5,12)
+#define AS_APP_QUIRK_MATCH_ANY_PREFIX          (1 << 3)
 #endif
 
-#if !AS_CHECK_VERSION(0,5,15)
-#define AS_APP_QUIRK_HAS_SHORTCUT              (1 << 6)
-#define AS_APP_QUIRK_NOT_LAUNCHABLE            (1 << 7)
+#if !AS_CHECK_VERSION(0,5,14)
+#define AS_APP_QUIRK_NOT_REVIEWABLE            (1 << 5)
 #endif
 
 GQuark          gs_app_error_quark             (void);
@@ -88,9 +86,6 @@ GQuark                 gs_app_error_quark             (void);
 GsApp          *gs_app_new                     (const gchar    *id);
 gchar          *gs_app_to_string               (GsApp          *app);
 
-void            gs_app_subsume                 (GsApp          *app,
-                                                GsApp          *other);
-
 const gchar    *gs_app_get_id                  (GsApp          *app);
 void            gs_app_set_id                  (GsApp          *app,
                                                 const gchar    *id);
@@ -101,6 +96,7 @@ void          gs_app_set_kind                (GsApp          *app,
 AsAppState      gs_app_get_state               (GsApp          *app);
 void            gs_app_set_state               (GsApp          *app,
                                                 AsAppState      state);
+void            gs_app_set_state_recover       (GsApp          *app);
 guint           gs_app_get_progress            (GsApp          *app);
 void            gs_app_set_progress            (GsApp          *app,
                                                 guint           percentage);
@@ -148,7 +144,7 @@ const gchar *gs_app_get_license             (GsApp          *app);
 gboolean        gs_app_get_license_is_free     (GsApp          *app);
 void            gs_app_set_license             (GsApp          *app,
                                                 GsAppQuality    quality,
-                                                const gchar    *licence);
+                                                const gchar    *license);
 gchar          **gs_app_get_menu_path          (GsApp          *app);
 void            gs_app_set_menu_path           (GsApp          *app,
                                                 gchar          **menu_path);
@@ -245,6 +241,9 @@ gboolean     gs_app_has_quirk               (GsApp          *app,
                                                 AsAppQuirk      quirk);
 void            gs_app_add_quirk               (GsApp          *app,
                                                 AsAppQuirk      quirk);
+GError         *gs_app_get_last_error          (GsApp          *app);
+void            gs_app_set_last_error          (GsApp          *app,
+                                                GError         *error);
 
 G_END_DECLS
 
diff --git a/src/gs-application.c b/src/gs-application.c
index 532ff09..8d7381e 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
  * Copyright (C) 2013 Matthias Clasen <mclasen redhat com>
- * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -205,7 +205,7 @@ gs_application_initialize_plugins (GsApplication *app)
 
        app->plugin_loader = gs_plugin_loader_new ();
        gs_plugin_loader_set_location (app->plugin_loader, NULL);
-       if (!gs_plugin_loader_setup (app->plugin_loader, &error)) {
+       if (!gs_plugin_loader_setup (app->plugin_loader, NULL, &error)) {
                g_warning ("Failed to setup plugins: %s", error->message);
                exit (1);
        }
diff --git a/src/gs-category-tile.c b/src/gs-category-tile.c
index 1f6956b..10aa9db 100644
--- a/src/gs-category-tile.c
+++ b/src/gs-category-tile.c
@@ -80,7 +80,7 @@ gs_category_tile_class_init (GsCategoryTileClass *klass)
 
        widget_class->destroy = gs_category_tile_destroy;
 
-       gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/category-tile.ui");
+       gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-category-tile.ui");
 
        gtk_widget_class_bind_template_child (widget_class, GsCategoryTile, label);
 }
diff --git a/src/category-tile.ui b/src/gs-category-tile.ui
similarity index 100%
rename from src/category-tile.ui
rename to src/gs-category-tile.ui
diff --git a/src/gs-category.c b/src/gs-category.c
index f54ae78..5d10c19 100644
--- a/src/gs-category.c
+++ b/src/gs-category.c
@@ -237,6 +237,9 @@ gs_category_new (GsCategory *parent, const gchar *id, const gchar *name)
                /* TRANSLATORS: this is a subcategory matching all the
                 * different apps in the parent category, e.g. "Games" */
                name =_("All");
+       } else if (g_strcmp0 (id, "featured") == 0) {
+               /* TRANSLATORS: this is a subcategory of featured apps */
+               name =_("Featured");
        }
 
        category = g_object_new (GS_TYPE_CATEGORY, NULL);
diff --git a/src/gs-cmd.c b/src/gs-cmd.c
index d695216..03e015d 100644
--- a/src/gs-cmd.c
+++ b/src/gs-cmd.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2013-2014 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -112,8 +112,8 @@ gs_cmd_refine_flag_from_string (const gchar *flag, GError **error)
 {
        if (g_strcmp0 (flag, "all") == 0)
                return G_MAXINT32;
-       if (g_strcmp0 (flag, "licence") == 0)
-               return GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE;
+       if (g_strcmp0 (flag, "license") == 0)
+               return GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE;
        if (g_strcmp0 (flag, "url") == 0)
                return GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL;
        if (g_strcmp0 (flag, "description") == 0)
@@ -175,6 +175,21 @@ gs_cmd_parse_refine_flags (const gchar *extra, GError **error)
        return refine_flags;
 }
 
+/**
+ * gs_cmd_refresh_flag_from_string:
+ **/
+static GsPluginRefreshFlags
+gs_cmd_refresh_flag_from_string (const gchar *flag)
+{
+       if (flag == NULL || g_strcmp0 (flag, "all") == 0)
+               return G_MAXINT32;
+       if (g_strcmp0 (flag, "metadata") == 0)
+               return GS_PLUGIN_REFRESH_FLAGS_METADATA;
+       if (g_strcmp0 (flag, "payload") == 0)
+               return GS_PLUGIN_REFRESH_FLAGS_PAYLOAD;
+       return GS_PLUGIN_REFRESH_FLAGS_NONE;
+}
+
 int
 main (int argc, char **argv)
 {
@@ -246,7 +261,7 @@ main (int argc, char **argv)
        /* load plugins */
        plugin_loader = gs_plugin_loader_new ();
        gs_plugin_loader_set_location (plugin_loader, "./plugins/.libs");
-       ret = gs_plugin_loader_setup (plugin_loader, &error);
+       ret = gs_plugin_loader_setup (plugin_loader, NULL, &error);
        if (!ret) {
                g_print ("Failed to setup plugins: %s\n", error->message);
                goto out;
@@ -422,10 +437,11 @@ main (int argc, char **argv)
                                break;
                        }
                }
-       } else if (argc == 2 && g_strcmp0 (argv[1], "refresh") == 0) {
+       } else if (argc >= 2 && g_strcmp0 (argv[1], "refresh") == 0) {
+               GsPluginRefreshFlags refresh_flags;
+               refresh_flags = gs_cmd_refresh_flag_from_string (argv[2]);
                ret = gs_plugin_loader_refresh (plugin_loader, cache_age,
-                                               GS_PLUGIN_REFRESH_FLAGS_UPDATES,
-                                               NULL, &error);
+                                               refresh_flags, NULL, &error);
        } else {
                ret = FALSE;
                g_set_error_literal (&error,
diff --git a/src/gs-feature-tile.c b/src/gs-feature-tile.c
index 96f7120..2c0f0f9 100644
--- a/src/gs-feature-tile.c
+++ b/src/gs-feature-tile.c
@@ -184,7 +184,7 @@ gs_feature_tile_class_init (GsFeatureTileClass *klass)
 
        widget_class->destroy = gs_feature_tile_destroy;
 
-       gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/feature-tile.ui");
+       gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-feature-tile.ui");
 
        gtk_widget_class_bind_template_child (widget_class, GsFeatureTile, image);
        gtk_widget_class_bind_template_child (widget_class, GsFeatureTile, stack);
diff --git a/src/feature-tile.ui b/src/gs-feature-tile.ui
similarity index 100%
rename from src/feature-tile.ui
rename to src/gs-feature-tile.ui
diff --git a/src/menus.ui b/src/gs-menus.ui
similarity index 100%
rename from src/menus.ui
rename to src/gs-menus.ui
diff --git a/src/gs-page.c b/src/gs-page.c
index db91dea..b7dd9da 100644
--- a/src/gs-page.c
+++ b/src/gs-page.c
@@ -60,6 +60,7 @@ gs_page_app_installed_cb (GObject *source,
                           GAsyncResult *res,
                           gpointer user_data)
 {
+       GError *last_error;
        GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
        GsPageHelper *helper = (GsPageHelper *) user_data;
        GsPage *page = helper->page;
@@ -81,6 +82,19 @@ gs_page_app_installed_cb (GObject *source,
                goto out;
        }
 
+       /* non-fatal error */
+       last_error = gs_app_get_last_error (helper->app);
+       if (last_error != NULL) {
+               g_warning ("failed to install %s: %s",
+                          gs_app_get_id (helper->app),
+                          last_error->message);
+               gs_app_notify_failed_modal (helper->app,
+                                           gs_shell_get_window (priv->shell),
+                                           GS_PLUGIN_LOADER_ACTION_INSTALL,
+                                           last_error);
+               goto out;
+       }
+
        /* only show this if the window is not active */
        if (gs_app_get_state (helper->app) != AS_APP_STATE_QUEUED_FOR_INSTALL &&
            !gs_shell_is_active (priv->shell))
@@ -98,6 +112,7 @@ gs_page_app_removed_cb (GObject *source,
                         GAsyncResult *res,
                         gpointer user_data)
 {
+       GError *last_error;
        GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
        GsPageHelper *helper = (GsPageHelper *) user_data;
        GsPage *page = helper->page;
@@ -117,6 +132,19 @@ gs_page_app_removed_cb (GObject *source,
                goto out;
        }
 
+       /* non-fatal error */
+       last_error = gs_app_get_last_error (helper->app);
+       if (last_error != NULL) {
+               g_warning ("failed to remove %s: %s",
+                          gs_app_get_id (helper->app),
+                          last_error->message);
+               gs_app_notify_failed_modal (helper->app,
+                                           gs_shell_get_window (priv->shell),
+                                           GS_PLUGIN_LOADER_ACTION_REMOVE,
+                                           last_error);
+               goto out;
+       }
+
        if (GS_PAGE_GET_CLASS (page)->app_removed != NULL)
                GS_PAGE_GET_CLASS (page)->app_removed (page, helper->app);
 
diff --git a/src/gs-plugin-loader-sync.c b/src/gs-plugin-loader-sync.c
index b139a78..37ed2de 100644
--- a/src/gs-plugin-loader-sync.c
+++ b/src/gs-plugin-loader-sync.c
@@ -37,7 +37,6 @@ gs_plugin_loader_get_app_by_id (GsPluginLoader *plugin_loader,
        gboolean ret;
 
        app = gs_app_new (id);
-       app = gs_plugin_loader_dedupe (plugin_loader, app);
        ret = gs_plugin_loader_app_refine (plugin_loader, app, flags,
                                           cancellable, error);
        if (!ret)
diff --git a/src/gs-plugin-loader.c b/src/gs-plugin-loader.c
index 3bace24..7cb9d16 100644
--- a/src/gs-plugin-loader.c
+++ b/src/gs-plugin-loader.c
@@ -43,8 +43,6 @@ typedef struct
        GMutex                   pending_apps_mutex;
        GPtrArray               *pending_apps;
 
-       GMutex                   app_cache_mutex;
-       GHashTable              *app_cache;
        GSettings               *settings;
 
        gchar                   **compatible_projects;
@@ -76,8 +74,6 @@ typedef struct {
        GsCategory                      *category;
        GsApp                           *app;
        GsReview                        *review;
-       AsAppState                       state_success;
-       AsAppState                       state_failure;
 } GsPluginLoaderAsyncState;
 
 static void
@@ -114,62 +110,6 @@ gs_plugin_loader_app_sort_cb (gconstpointer a, gconstpointer b)
 }
 
 /**
- * gs_plugin_loader_dedupe:
- */
-GsApp *
-gs_plugin_loader_dedupe (GsPluginLoader *plugin_loader, GsApp *app)
-{
-       GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
-       GsApp *new_app;
-       g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&priv->app_cache_mutex);
-
-       g_return_val_if_fail (GS_IS_PLUGIN_LOADER (plugin_loader), NULL);
-       g_return_val_if_fail (GS_IS_APP (app), NULL);
-
-       /* not yet set */
-       if (gs_app_get_id (app) == NULL) {
-               return app;
-       }
-
-       /* already exists */
-       new_app = g_hash_table_lookup (priv->app_cache, gs_app_get_id (app));
-       if (new_app == app) {
-               return app;
-       }
-
-       /* insert new entry */
-       if (new_app == NULL) {
-               g_hash_table_insert (priv->app_cache,
-                                    g_strdup (gs_app_get_id (app)),
-                                    g_object_ref (app));
-               return app;
-       }
-
-       /* import all the useful properties */
-       gs_app_subsume (new_app, app);
-
-       /* this looks a little odd to unref the method parameter,
-        * but it allows us to do:
-        * app = gs_plugin_loader_dedupe (cache, app);
-        */
-       g_object_unref (app);
-       g_object_ref (new_app);
-
-       return new_app;
-}
-
-/**
- * gs_plugin_loader_list_dedupe:
- **/
-static void
-gs_plugin_loader_list_dedupe (GsPluginLoader *plugin_loader, GList *list)
-{
-       GList *l;
-       for (l = list; l != NULL; l = l->next)
-               l->data = gs_plugin_loader_dedupe (plugin_loader, GS_APP (l->data));
-}
-
-/**
  * gs_plugin_loader_run_refine:
  **/
 static gboolean
@@ -186,9 +126,8 @@ gs_plugin_loader_run_refine (GsPluginLoader *plugin_loader,
        GPtrArray *related;
        GsApp *app;
        GsPlugin *plugin;
-       GsPluginRefineFunc plugin_func = NULL;
+       const gchar *function_name_app = "gs_plugin_refine_app";
        const gchar *function_name = "gs_plugin_refine";
-       gboolean exists;
        gboolean ret = TRUE;
        guint i;
        g_autoptr(GsAppList) addons_list = NULL;
@@ -202,18 +141,20 @@ gs_plugin_loader_run_refine (GsPluginLoader *plugin_loader,
 
        /* run each plugin */
        for (i = 0; i < priv->plugins->len; i++) {
+               GsPluginRefineAppFunc plugin_app_func = NULL;
+               GsPluginRefineFunc plugin_func = NULL;
                g_autoptr(AsProfileTask) ptask = NULL;
-               g_autoptr(GError) error_local = NULL;
 
                plugin = g_ptr_array_index (priv->plugins, i);
                if (!plugin->enabled)
                        continue;
 
-               /* load the symbol */
-               exists = g_module_symbol (plugin->module,
-                                         function_name,
-                                         (gpointer *) &plugin_func);
-               if (!exists)
+               /* load the possible symbols */
+               g_module_symbol (plugin->module, function_name,
+                                (gpointer *) &plugin_func);
+               g_module_symbol (plugin->module, function_name_app,
+                                (gpointer *) &plugin_app_func);
+               if (plugin_func == NULL && plugin_app_func == NULL)
                        continue;
 
                /* profile the plugin runtime */
@@ -229,12 +170,36 @@ gs_plugin_loader_run_refine (GsPluginLoader *plugin_loader,
                                                  function_name_parent,
                                                  function_name);
                }
-               ret = plugin_func (plugin, list, flags, cancellable, &error_local);
-               if (!ret) {
-                       g_warning ("failed to call %s on %s: %s",
-                                  function_name, plugin->name,
-                                  error_local->message);
-                       continue;
+
+               /* run the batched plugin symbol then the per-app plugin */
+               if (plugin_func != NULL) {
+                       g_autoptr(GError) error_local = NULL;
+                       g_rw_lock_reader_lock (&plugin->rwlock);
+                       ret = plugin_func (plugin, list, flags,
+                                          cancellable, &error_local);
+                       g_rw_lock_reader_unlock (&plugin->rwlock);
+                       if (!ret) {
+                               g_warning ("failed to call %s on %s: %s",
+                                          function_name, plugin->name,
+                                          error_local->message);
+                               continue;
+                       }
+               }
+               if (plugin_app_func != NULL) {
+                       for (l = *list; l != NULL; l = l->next) {
+                               g_autoptr(GError) error_local = NULL;
+                               app = GS_APP (l->data);
+                               g_rw_lock_reader_lock (&plugin->rwlock);
+                               ret = plugin_app_func (plugin, app, flags,
+                                                      cancellable, &error_local);
+                               g_rw_lock_reader_unlock (&plugin->rwlock);
+                               if (!ret) {
+                                       g_warning ("failed to call %s on %s: %s",
+                                                  function_name_app, plugin->name,
+                                                  error_local->message);
+                                       continue;
+                               }
+                       }
                }
                gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
        }
@@ -292,9 +257,6 @@ gs_plugin_loader_run_refine (GsPluginLoader *plugin_loader,
                                goto out;
                }
        }
-
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, *list);
 out:
        /* now emit all the changed signals */
        for (l = freeze_list; l != NULL; l = l->next)
@@ -355,7 +317,9 @@ gs_plugin_loader_run_results (GsPluginLoader *plugin_loader,
                ptask2 = as_profile_start (priv->profile,
                                           "GsPlugin::%s(%s)",
                                           plugin->name, function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                ret = plugin_func (plugin, &list, cancellable, &error_local);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   function_name, plugin->name,
@@ -365,9 +329,6 @@ gs_plugin_loader_run_results (GsPluginLoader *plugin_loader,
                gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
        }
 
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, list);
-
        /* run refine() on each one */
        ret = gs_plugin_loader_run_refine (plugin_loader,
                                           function_name,
@@ -581,6 +542,29 @@ gs_plugin_loader_get_app_is_compatible (GsApp *app, gpointer user_data)
 }
 
 /**
+ * gs_plugin_loader_set_app_error:
+ **/
+static void
+gs_plugin_loader_set_app_error (GsApp *app, GError *error)
+{
+       if (error == NULL)
+               return;
+
+       /* random, non-plugin error domains are never shown to the user */
+       if (error->domain == GS_PLUGIN_ERROR &&
+           gs_app_get_last_error (app) == NULL) {
+               g_debug ("saving error for %s: %s",
+                        gs_app_get_id (app),
+                        error->message);
+               gs_app_set_last_error (app, error);
+       } else {
+               g_warning ("not saving error for %s: %s",
+                          gs_app_get_id (app),
+                          error->message);
+       }
+}
+
+/**
  * gs_plugin_loader_run_action:
  **/
 static gboolean
@@ -617,11 +601,14 @@ gs_plugin_loader_run_action (GsPluginLoader *plugin_loader,
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                ret = plugin_func (plugin, app, cancellable, &error_local);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   function_name, plugin->name,
                                   error_local->message);
+                       gs_plugin_loader_set_app_error (app, error_local);
                        continue;
                }
                anything_ran = TRUE;
@@ -737,9 +724,6 @@ gs_plugin_loader_get_updates_thread_cb (GTask *task,
        /* filter package list */
        gs_plugin_list_filter_duplicates (&state->list);
 
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, state->list);
-
        /* coalesce all packages down into one os-update */
        state->list = gs_plugin_loader_add_os_update_item (state->list);
 
@@ -850,9 +834,6 @@ gs_plugin_loader_get_distro_upgrades_thread_cb (GTask *task,
        /* filter package list */
        gs_plugin_list_filter_duplicates (&state->list);
 
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, state->list);
-
        /* success */
        g_task_return_pointer (task, gs_plugin_list_copy (state->list), (GDestroyNotify) gs_plugin_list_free);
 }
@@ -933,9 +914,6 @@ gs_plugin_loader_get_unvoted_reviews_thread_cb (GTask *task,
        /* filter package list */
        gs_plugin_list_filter_duplicates (&state->list);
 
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, state->list);
-
        /* success */
        g_task_return_pointer (task, gs_plugin_list_copy (state->list), (GDestroyNotify) gs_plugin_list_free);
 }
@@ -1016,9 +994,6 @@ gs_plugin_loader_get_sources_thread_cb (GTask *task,
        /* filter package list */
        gs_plugin_list_filter_duplicates (&state->list);
 
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, state->list);
-
        /* none left? */
        if (state->list == NULL) {
                g_task_return_new_error (task,
@@ -1504,8 +1479,10 @@ gs_plugin_loader_search_thread_cb (GTask *task,
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                ret = plugin_func (plugin, values, &state->list,
                                   cancellable, &error_local);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   function_name, plugin->name,
@@ -1515,9 +1492,6 @@ gs_plugin_loader_search_thread_cb (GTask *task,
                gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
        }
 
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, state->list);
-
        /* run refine() on each one */
        ret = gs_plugin_loader_run_refine (plugin_loader,
                                           function_name,
@@ -1666,8 +1640,10 @@ gs_plugin_loader_search_files_thread_cb (GTask *task,
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                ret = plugin_func (plugin, values, &state->list,
                                   cancellable, &error_local);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   function_name, plugin->name,
@@ -1677,9 +1653,6 @@ gs_plugin_loader_search_files_thread_cb (GTask *task,
                gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
        }
 
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, state->list);
-
        /* run refine() on each one */
        ret = gs_plugin_loader_run_refine (plugin_loader,
                                           function_name,
@@ -1829,8 +1802,10 @@ gs_plugin_loader_search_what_provides_thread_cb (GTask *task,
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                ret = plugin_func (plugin, values, &state->list,
                                   cancellable, &error_local);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   function_name, plugin->name,
@@ -1840,9 +1815,6 @@ gs_plugin_loader_search_what_provides_thread_cb (GTask *task,
                gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
        }
 
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, state->list);
-
        /* run refine() on each one */
        ret = gs_plugin_loader_run_refine (plugin_loader,
                                           function_name,
@@ -1998,8 +1970,10 @@ gs_plugin_loader_get_categories_thread_cb (GTask *task,
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                ret = plugin_func (plugin, &state->list,
                                   cancellable, &error_local);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   function_name, plugin->name,
@@ -2129,8 +2103,10 @@ gs_plugin_loader_get_category_apps_thread_cb (GTask *task,
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                ret = plugin_func (plugin, state->category, &state->list,
                                   cancellable, &error_local);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   function_name, plugin->name,
@@ -2140,9 +2116,6 @@ gs_plugin_loader_get_category_apps_thread_cb (GTask *task,
                gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
        }
 
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, state->list);
-
        /* run refine() on each one */
        ret = gs_plugin_loader_run_refine (plugin_loader,
                                           function_name,
@@ -2369,16 +2342,12 @@ gs_plugin_loader_app_action_thread_cb (GTask *task,
                                           cancellable,
                                           &error);
        if (ret) {
-               if (state->state_success != AS_APP_STATE_UNKNOWN) {
-                       gs_app_set_state (state->app, state->state_success);
-                       addons = gs_app_get_addons (state->app);
-                       for (i = 0; i < addons->len; i++) {
-                               GsApp *addon = g_ptr_array_index (addons, i);
-                               if (gs_app_get_to_be_installed (addon)) {
-                                       gs_app_set_state (addon, state->state_success);
-                                       gs_app_set_to_be_installed (addon, FALSE);
-                               }
-                       }
+               /* unstage addons */
+               addons = gs_app_get_addons (state->app);
+               for (i = 0; i < addons->len; i++) {
+                       GsApp *addon = g_ptr_array_index (addons, i);
+                       if (gs_app_get_to_be_installed (addon))
+                               gs_app_set_to_be_installed (addon, FALSE);
                }
 
                /* refine again to make sure we pick up new source id */
@@ -2395,20 +2364,22 @@ gs_plugin_loader_app_action_thread_cb (GTask *task,
                        g_task_return_error (task, error);
                }
        } else {
-               if (state->state_failure != AS_APP_STATE_UNKNOWN) {
-                       gs_app_set_state (state->app, state->state_failure);
-                       addons = gs_app_get_addons (state->app);
-                       for (i = 0; i < addons->len; i++) {
-                               GsApp *addon = g_ptr_array_index (addons, i);
-                               if (gs_app_get_to_be_installed (addon)) {
-                                       gs_app_set_state (addon, state->state_failure);
-                                       gs_app_set_to_be_installed (addon, FALSE);
-                               }
-                       }
-               }
                g_task_return_error (task, error);
        }
 
+       /* check the app is not still in an action state */
+       switch (gs_app_get_state (state->app)) {
+       case AS_APP_STATE_INSTALLING:
+       case AS_APP_STATE_REMOVING:
+               g_warning ("application %s left in %s state",
+                          gs_app_get_id (state->app),
+                          as_app_state_to_string (gs_app_get_state (state->app)));
+               gs_app_set_state (state->app, AS_APP_STATE_UNKNOWN);
+               break;
+       default:
+               break;
+       }
+
        /* remove from list */
        g_mutex_lock (&priv->pending_apps_mutex);
        g_ptr_array_remove (priv->pending_apps, state->app);
@@ -2456,8 +2427,10 @@ gs_plugin_loader_review_action_thread_cb (GTask *task,
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          state->function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                ret = plugin_func (plugin, state->app, state->review,
                                   cancellable, &error_local);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   state->function_name, plugin->name,
@@ -2521,12 +2494,6 @@ load_install_queue (GsPluginLoader *plugin_loader, GError **error)
                app = gs_app_new (names[i]);
                gs_app_set_state (app, AS_APP_STATE_QUEUED_FOR_INSTALL);
 
-               g_mutex_lock (&priv->app_cache_mutex);
-               g_hash_table_insert (priv->app_cache,
-                                    g_strdup (gs_app_get_id (app)),
-                                    g_object_ref (app));
-               g_mutex_unlock (&priv->app_cache_mutex);
-
                g_mutex_lock (&priv->pending_apps_mutex);
                g_ptr_array_add (priv->pending_apps,
                                 g_object_ref (app));
@@ -2699,38 +2666,27 @@ gs_plugin_loader_app_action_async (GsPluginLoader *plugin_loader,
        switch (action) {
        case GS_PLUGIN_LOADER_ACTION_INSTALL:
                state->function_name = "gs_plugin_app_install";
-               state->state_success = AS_APP_STATE_INSTALLED;
-               state->state_failure = AS_APP_STATE_AVAILABLE;
                break;
        case GS_PLUGIN_LOADER_ACTION_REMOVE:
                state->function_name = "gs_plugin_app_remove";
-               state->state_success = AS_APP_STATE_AVAILABLE;
-               state->state_failure = AS_APP_STATE_INSTALLED;
                break;
        case GS_PLUGIN_LOADER_ACTION_SET_RATING:
                state->function_name = "gs_plugin_app_set_rating";
-               state->state_success = AS_APP_STATE_UNKNOWN;
-               state->state_failure = AS_APP_STATE_UNKNOWN;
+               break;
+       case GS_PLUGIN_LOADER_ACTION_UPDATE:
+               state->function_name = "gs_plugin_app_update";
                break;
        case GS_PLUGIN_LOADER_ACTION_UPGRADE_DOWNLOAD:
                state->function_name = "gs_plugin_app_upgrade_download";
-               state->state_success = AS_APP_STATE_AVAILABLE;
-               state->state_failure = AS_APP_STATE_UPDATABLE;
                break;
        case GS_PLUGIN_LOADER_ACTION_UPGRADE_TRIGGER:
                state->function_name = "gs_plugin_app_upgrade_trigger";
-               state->state_success = AS_APP_STATE_UNKNOWN;
-               state->state_failure = AS_APP_STATE_UNKNOWN;
                break;
        case GS_PLUGIN_LOADER_ACTION_LAUNCH:
                state->function_name = "gs_plugin_launch";
-               state->state_success = AS_APP_STATE_UNKNOWN;
-               state->state_failure = AS_APP_STATE_UNKNOWN;
                break;
-       case GS_PLUGIN_LOADER_ACTION_UPDATE_CANCEL:
-               state->function_name = "gs_plugin_update_cancel";
-               state->state_success = AS_APP_STATE_UNKNOWN;
-               state->state_failure = AS_APP_STATE_UNKNOWN;
+       case GS_PLUGIN_LOADER_ACTION_OFFLINE_UPDATE_CANCEL:
+               state->function_name = "gs_plugin_offline_update_cancel";
                break;
        default:
                g_assert_not_reached ();
@@ -2866,33 +2822,44 @@ gs_plugin_loader_run (GsPluginLoader *plugin_loader, const gchar *function_name)
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                plugin_func (plugin);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
        }
 }
 
 /**
- * gs_plugin_loader_set_enabled:
+ * gs_plugin_loader_find_plugin:
  */
-gboolean
-gs_plugin_loader_set_enabled (GsPluginLoader *plugin_loader,
-                             const gchar *plugin_name,
-                             gboolean enabled)
+static GsPlugin *
+gs_plugin_loader_find_plugin (GsPluginLoader *plugin_loader,
+                             const gchar *plugin_name)
 {
        GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
-       gboolean ret = FALSE;
        GsPlugin *plugin;
        guint i;
 
        for (i = 0; i < priv->plugins->len; i++) {
                plugin = g_ptr_array_index (priv->plugins, i);
-               if (g_strcmp0 (plugin->name, plugin_name) == 0) {
-                       plugin->enabled = enabled;
-                       ret = TRUE;
-                       break;
-               }
+               if (g_strcmp0 (plugin->name, plugin_name) == 0)
+                       return plugin;
        }
-       return ret;
+       return NULL;
+}
+
+/**
+ * gs_plugin_loader_get_enabled:
+ */
+gboolean
+gs_plugin_loader_get_enabled (GsPluginLoader *plugin_loader,
+                             const gchar *plugin_name)
+{
+       GsPlugin *plugin;
+       plugin = gs_plugin_loader_find_plugin (plugin_loader, plugin_name);
+       if (plugin == NULL)
+               return FALSE;
+       return plugin->enabled;
 }
 
 /**
@@ -2929,30 +2896,6 @@ gs_plugin_loader_updates_changed_delay_cb (gpointer user_data)
 {
        GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (user_data);
        GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
-       GList *apps;
-       GList *l;
-       GsApp *app;
-
-       /* no longer know the state of these */
-       g_mutex_lock (&priv->app_cache_mutex);
-       apps = g_hash_table_get_values (priv->app_cache);
-       for (l = apps; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               switch (gs_app_get_state (app)) {
-               case AS_APP_STATE_INSTALLED:
-               case AS_APP_STATE_UPDATABLE:
-               case AS_APP_STATE_UPDATABLE_LIVE:
-                       gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
-                       break;
-               default:
-                       break;
-               }
-       }
-       g_list_free (apps);
-
-       /* not valid anymore */
-       g_hash_table_remove_all (priv->app_cache);
-       g_mutex_unlock (&priv->app_cache_mutex);
 
        /* notify shells */
        g_debug ("updates-changed");
@@ -3043,6 +2986,9 @@ gs_plugin_loader_open_plugin (GsPluginLoader *plugin_loader,
        plugin->scale = gs_plugin_loader_get_scale (plugin_loader);
        g_debug ("opened plugin %s: %s", filename, plugin->name);
 
+       /* rwlock */
+       g_rw_lock_init (&plugin->rwlock);
+
        /* add to array */
        g_ptr_array_add (priv->plugins, plugin);
        return plugin;
@@ -3114,29 +3060,12 @@ gs_plugin_loader_plugin_sort_fn (gconstpointer a, gconstpointer b)
 }
 
 /**
- * gs_plugin_loader_find_plugin:
- */
-static GsPlugin *
-gs_plugin_loader_find_plugin (GsPluginLoader *plugin_loader,
-                             const gchar *plugin_name)
-{
-       GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
-       GsPlugin *plugin;
-       guint i;
-
-       for (i = 0; i < priv->plugins->len; i++) {
-               plugin = g_ptr_array_index (priv->plugins, i);
-               if (g_strcmp0 (plugin->name, plugin_name) == 0)
-                       return plugin;
-       }
-       return NULL;
-}
-
-/**
  * gs_plugin_loader_setup:
  */
 gboolean
-gs_plugin_loader_setup (GsPluginLoader *plugin_loader, GError **error)
+gs_plugin_loader_setup (GsPluginLoader *plugin_loader,
+                       gchar **whitelist,
+                       GError **error)
 {
        GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
        const gchar *filename_tmp;
@@ -3173,6 +3102,17 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader, GError **error)
                gs_plugin_loader_open_plugin (plugin_loader, filename_plugin);
        } while (TRUE);
 
+       /* optional whitelist */
+       if (whitelist != NULL) {
+               for (i = 0; i < priv->plugins->len; i++) {
+                       plugin = g_ptr_array_index (priv->plugins, i);
+                       if (!plugin->enabled)
+                               continue;
+                       plugin->enabled = g_strv_contains ((const gchar * const *) whitelist,
+                                                          plugin->name);
+               }
+       }
+
        /* order by deps */
        do {
                changes = FALSE;
@@ -3264,6 +3204,36 @@ gs_plugin_loader_setup (GsPluginLoader *plugin_loader, GError **error)
                }
        }
 
+       /* run setup */
+       for (i = 0; i < priv->plugins->len; i++) {
+               GsPluginSetupFunc plugin_func = NULL;
+               const gchar *function_name = "gs_plugin_setup";
+               gboolean ret;
+               g_autoptr(AsProfileTask) ptask2 = NULL;
+               g_autoptr(GError) error_local = NULL;
+
+               /* run setup() if it exists */
+               plugin = g_ptr_array_index (priv->plugins, i);
+               if (!plugin->enabled)
+                       continue;
+               ret = g_module_symbol (plugin->module,
+                                      function_name,
+                                      (gpointer *) &plugin_func);
+               if (!ret)
+                       continue;
+               ptask2 = as_profile_start (priv->profile,
+                                          "GsPlugin::%s(%s)",
+                                          plugin->name,
+                                          function_name);
+               g_rw_lock_writer_lock (&plugin->rwlock);
+               ret = plugin_func (plugin, NULL, &error_local);
+               g_rw_lock_writer_unlock (&plugin->rwlock);
+               if (!ret) {
+                       g_debug ("disabling %s as setup failed: %s",
+                                plugin->name, error_local->message);
+               }
+       }
+
        /* now we can load the install-queue */
        if (!load_install_queue (plugin_loader, error))
                return FALSE;
@@ -3284,7 +3254,7 @@ gs_plugin_loader_dump_state (GsPluginLoader *plugin_loader)
        for (i = 0; i < priv->plugins->len; i++) {
                plugin = g_ptr_array_index (priv->plugins, i);
                g_debug ("[%s]\t%.1f\t->\t%s",
-                        plugin->enabled ? "enabled" : "disabled",
+                        plugin->enabled ? "enabled" : "disabld",
                         plugin->priority,
                         plugin->name);
        }
@@ -3298,6 +3268,7 @@ gs_plugin_loader_plugin_free (GsPlugin *plugin)
 {
        g_free (plugin->priv);
        g_free (plugin->name);
+       g_rw_lock_clear (&plugin->rwlock);
        g_object_unref (plugin->profile);
        g_object_unref (plugin->soup_session);
        g_module_close (plugin->module);
@@ -3325,7 +3296,6 @@ gs_plugin_loader_dispose (GObject *object)
        g_clear_object (&priv->soup_session);
        g_clear_object (&priv->profile);
        g_clear_object (&priv->settings);
-       g_clear_pointer (&priv->app_cache, g_hash_table_unref);
        g_clear_pointer (&priv->pending_apps, g_ptr_array_unref);
 
        G_OBJECT_CLASS (gs_plugin_loader_parent_class)->dispose (object);
@@ -3346,7 +3316,6 @@ gs_plugin_loader_finalize (GObject *object)
        g_free (priv->locale);
 
        g_mutex_clear (&priv->pending_apps_mutex);
-       g_mutex_clear (&priv->app_cache_mutex);
 
        G_OBJECT_CLASS (gs_plugin_loader_parent_class)->finalize (object);
 }
@@ -3391,7 +3360,6 @@ gs_plugin_loader_init (GsPluginLoader *plugin_loader)
 {
        GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
        const gchar *tmp;
-       gchar *match;
        gchar **projects;
        guint i;
 
@@ -3401,10 +3369,6 @@ gs_plugin_loader_init (GsPluginLoader *plugin_loader)
        priv->pending_apps = g_ptr_array_new_with_free_func ((GFreeFunc) g_object_unref);
        priv->profile = as_profile_new ();
        priv->settings = g_settings_new ("org.gnome.software");
-       priv->app_cache = g_hash_table_new_full (g_str_hash,
-                                                               g_str_equal,
-                                                               g_free,
-                                                               (GFreeFunc) g_object_unref);
 
        /* share a soup session (also disable the double-compression) */
        priv->soup_session = soup_session_new_with_options (SOUP_SESSION_USER_AGENT, gs_user_agent (),
@@ -3413,16 +3377,22 @@ gs_plugin_loader_init (GsPluginLoader *plugin_loader)
                                             SOUP_TYPE_CONTENT_DECODER);
 
        /* get the locale without the various UTF-8 suffixes */
-       priv->locale = g_strdup (setlocale (LC_MESSAGES, NULL));
-       match = g_strstr_len (priv->locale, -1, ".UTF-8");
-       if (match != NULL)
-               *match = '\0';
-       match = g_strstr_len (priv->locale, -1, ".utf8");
-       if (match != NULL)
-               *match = '\0';
+       tmp = g_getenv ("GS_SELF_TEST_LOCALE");
+       if (tmp != NULL) {
+               g_debug ("using self test locale of %s", tmp);
+               priv->locale = g_strdup (tmp);
+       } else {
+               gchar *match;
+               priv->locale = g_strdup (setlocale (LC_MESSAGES, NULL));
+               match = g_strstr_len (priv->locale, -1, ".UTF-8");
+               if (match != NULL)
+                       *match = '\0';
+               match = g_strstr_len (priv->locale, -1, ".utf8");
+               if (match != NULL)
+                       *match = '\0';
+       }
 
        g_mutex_init (&priv->pending_apps_mutex);
-       g_mutex_init (&priv->app_cache_mutex);
 
        /* by default we only show project-less apps or compatible projects */
        tmp = g_getenv ("GNOME_SOFTWARE_COMPATIBLE_PROJECTS");
@@ -3489,7 +3459,7 @@ gs_plugin_loader_set_network_status (GsPluginLoader *plugin_loader,
        if (priv->online == online)
                return;
 
-       g_debug ("*** Network status change: %s", online ? "online" : "offline");
+       g_debug ("network status change: %s", online ? "online" : "offline");
 
        priv->online = online;
 
@@ -3555,7 +3525,9 @@ gs_plugin_loader_run_refresh (GsPluginLoader *plugin_loader,
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          function_name);
+               g_rw_lock_writer_lock (&plugin->rwlock);
                ret = plugin_func (plugin, cache_age, flags, cancellable, &error_local);
+               g_rw_lock_writer_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   function_name, plugin->name,
@@ -3671,7 +3643,6 @@ gs_plugin_loader_file_to_app_thread_cb (GTask *task,
        const gchar *function_name = "gs_plugin_file_to_app";
        gboolean ret = TRUE;
        GError *error = NULL;
-       GList *l;
        GsPluginLoaderAsyncState *state = (GsPluginLoaderAsyncState *) task_data;
        GsPlugin *plugin;
        GsPluginFileToAppFunc plugin_func = NULL;
@@ -3696,8 +3667,10 @@ gs_plugin_loader_file_to_app_thread_cb (GTask *task,
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                ret = plugin_func (plugin, &state->list, state->file,
                                   cancellable, &error_local);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   function_name, plugin->name,
@@ -3707,16 +3680,6 @@ gs_plugin_loader_file_to_app_thread_cb (GTask *task,
                gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_FINISHED);
        }
 
-       /* dedupe applications we already know about */
-       gs_plugin_loader_list_dedupe (plugin_loader, state->list);
-
-       /* set the local file on any of the returned results */
-       for (l = state->list; l != NULL; l = l->next) {
-               GsApp *app = GS_APP (l->data);
-               if (gs_app_get_local_file (app) == NULL)
-                       gs_app_set_local_file (app, state->file);
-       }
-
        /* run refine() on each one */
        ret = gs_plugin_loader_run_refine (plugin_loader,
                                           function_name,
@@ -3850,7 +3813,9 @@ gs_plugin_loader_update_thread_cb (GTask *task,
                                          "GsPlugin::%s(%s)",
                                          plugin->name,
                                          function_name);
+               g_rw_lock_reader_lock (&plugin->rwlock);
                ret = plugin_func (plugin, state->list, cancellable, &error_local);
+               g_rw_lock_reader_unlock (&plugin->rwlock);
                if (!ret) {
                        g_warning ("failed to call %s on %s: %s",
                                   function_name, plugin->name,
diff --git a/src/gs-plugin-loader.h b/src/gs-plugin-loader.h
index ab4c36e..481c644 100644
--- a/src/gs-plugin-loader.h
+++ b/src/gs-plugin-loader.h
@@ -60,7 +60,7 @@ typedef enum {
        GS_PLUGIN_LOADER_ACTION_UPGRADE_DOWNLOAD,
        GS_PLUGIN_LOADER_ACTION_UPGRADE_TRIGGER,
        GS_PLUGIN_LOADER_ACTION_LAUNCH,
-       GS_PLUGIN_LOADER_ACTION_UPDATE_CANCEL,
+       GS_PLUGIN_LOADER_ACTION_OFFLINE_UPDATE_CANCEL,
        GS_PLUGIN_LOADER_ACTION_LAST
 } GsPluginLoaderAction;
 
@@ -189,11 +189,11 @@ gboolean   gs_plugin_loader_update_finish         (GsPluginLoader *plugin_loader,
                                                         GAsyncResult   *res,
                                                         GError         **error);
 gboolean        gs_plugin_loader_setup                 (GsPluginLoader *plugin_loader,
+                                                        gchar          **whitelist,
                                                         GError         **error);
 void            gs_plugin_loader_dump_state            (GsPluginLoader *plugin_loader);
-gboolean        gs_plugin_loader_set_enabled           (GsPluginLoader *plugin_loader,
-                                                        const gchar    *plugin_name,
-                                                        gboolean        enabled);
+gboolean        gs_plugin_loader_get_enabled           (GsPluginLoader *plugin_loader,
+                                                        const gchar    *plugin_name);
 void            gs_plugin_loader_set_location          (GsPluginLoader *plugin_loader,
                                                         const gchar    *location);
 gint            gs_plugin_loader_get_scale             (GsPluginLoader *plugin_loader);
@@ -237,8 +237,6 @@ void                 gs_plugin_loader_refresh_async         (GsPluginLoader 
*plugin_loader,
                                                         GAsyncReadyCallback callback,
                                                         gpointer        user_data);
 GPtrArray      *gs_plugin_loader_get_pending           (GsPluginLoader *plugin_loader);
-GsApp          *gs_plugin_loader_dedupe                (GsPluginLoader *plugin_loader,
-                                                        GsApp          *app);
 void            gs_plugin_loader_set_network_status    (GsPluginLoader *plugin_loader,
                                                         gboolean        online);
 gboolean        gs_plugin_loader_get_plugin_supported  (GsPluginLoader *plugin_loader,
diff --git a/src/gs-plugin.c b/src/gs-plugin.c
index 6002a7a..5b2780c 100644
--- a/src/gs-plugin.c
+++ b/src/gs-plugin.c
@@ -399,4 +399,141 @@ gs_plugin_updates_changed (GsPlugin *plugin)
        g_idle_add (gs_plugin_updates_changed_cb, plugin);
 }
 
+typedef struct {
+       GsPlugin        *plugin;
+       GsApp           *app;
+       GCancellable    *cancellable;
+} GsPluginDownloadHelper;
+
+/**
+ * gs_plugin_download_chunk_cb:
+ **/
+static void
+gs_plugin_download_chunk_cb (SoupMessage *msg, SoupBuffer *chunk,
+                            GsPluginDownloadHelper *helper)
+{
+       guint percentage;
+       goffset header_size;
+       goffset body_length;
+
+       /* cancelled? */
+       if (g_cancellable_is_cancelled (helper->cancellable)) {
+               g_debug ("cancelling download of %s",
+                        gs_app_get_id (helper->app));
+               soup_session_cancel_message (helper->plugin->soup_session,
+                                            msg,
+                                            SOUP_STATUS_CANCELLED);
+               return;
+       }
+
+       /* if it's returning "Found" or an error, ignore the percentage */
+       if (msg->status_code != SOUP_STATUS_OK) {
+               g_debug ("ignoring status code %i (%s)",
+                        msg->status_code, msg->reason_phrase);
+               return;
+       }
+
+       /* get data */
+       body_length = msg->response_body->length;
+       header_size = soup_message_headers_get_content_length (msg->response_headers);
+
+       /* size is not known */
+       if (header_size < body_length)
+               return;
+
+       /* calulate percentage */
+       percentage = (100 * body_length) / header_size;
+       g_debug ("%s progress: %i%%", gs_app_get_id (helper->app), percentage);
+       gs_app_set_progress (helper->app, percentage);
+       gs_plugin_status_update (helper->plugin,
+                                helper->app,
+                                GS_PLUGIN_STATUS_DOWNLOADING);
+}
+
+/**
+ * gs_plugin_download_data:
+ */
+GBytes *
+gs_plugin_download_data (GsPlugin *plugin,
+                        GsApp *app,
+                        const gchar *uri,
+                        GCancellable *cancellable,
+                        GError **error)
+{
+       GsPluginDownloadHelper helper;
+       guint status_code;
+       g_autoptr(SoupMessage) msg = NULL;
+
+       g_debug ("downloading %s from %s", uri, plugin->name);
+       msg = soup_message_new (SOUP_METHOD_GET, uri);
+       if (app != NULL) {
+               helper.plugin = plugin;
+               helper.app = app;
+               helper.cancellable = cancellable;
+               g_signal_connect (msg, "got-chunk",
+                                 G_CALLBACK (gs_plugin_download_chunk_cb),
+                                 &helper);
+       }
+       status_code = soup_session_send_message (plugin->soup_session, msg);
+       if (status_code != SOUP_STATUS_OK) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "failed to get shell extensions: %s",
+                            msg->response_body->data);
+               return NULL;
+       }
+       return g_bytes_new (msg->response_body->data,
+                           msg->response_body->length);
+}
+
+/**
+ * gs_plugin_download_file:
+ */
+gboolean
+gs_plugin_download_file (GsPlugin *plugin,
+                        GsApp *app,
+                        const gchar *uri,
+                        const gchar *filename,
+                        GCancellable *cancellable,
+                        GError **error)
+{
+       GsPluginDownloadHelper helper;
+       guint status_code;
+       g_autoptr(GError) error_local = NULL;
+       g_autoptr(SoupMessage) msg = NULL;
+
+       g_debug ("downloading %s to %s from %s", uri, filename, plugin->name);
+       msg = soup_message_new (SOUP_METHOD_GET, uri);
+       if (app != NULL) {
+               helper.plugin = plugin;
+               helper.app = app;
+               helper.cancellable = cancellable;
+               g_signal_connect (msg, "got-chunk",
+                                 G_CALLBACK (gs_plugin_download_chunk_cb),
+                                 &helper);
+       }
+       status_code = soup_session_send_message (plugin->soup_session, msg);
+       if (status_code != SOUP_STATUS_OK) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "failed to get shell extensions: %s",
+                            msg->response_body->data);
+               return FALSE;
+       }
+       if (!g_file_set_contents (filename,
+                                 msg->response_body->data,
+                                 msg->response_body->length,
+                                 &error_local)) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "Failed to save firmware: %s",
+                            error_local->message);
+               return FALSE;
+       }
+       return TRUE;
+}
+
 /* vim: set noexpandtab: */
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index d40fcfa..aded797 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -79,6 +79,7 @@ struct GsPlugin {
        gpointer                 updates_changed_user_data;
        AsProfile               *profile;
        SoupSession             *soup_session;
+       GRWLock                  rwlock;
 };
 
 typedef enum {
@@ -94,7 +95,7 @@ typedef enum {
 typedef enum {
        GS_PLUGIN_REFINE_FLAGS_DEFAULT                  = 0,
        GS_PLUGIN_REFINE_FLAGS_USE_HISTORY              = 1 << 0,
-       GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE          = 1 << 1,
+       GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE          = 1 << 1,
        GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL              = 1 << 2,
        GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION      = 1 << 3,
        GS_PLUGIN_REFINE_FLAGS_REQUIRE_SIZE             = 1 << 4,
@@ -113,12 +114,32 @@ typedef enum {
        GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE       = 1 << 17,
        GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEWS          = 1 << 18,
        GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEW_RATINGS   = 1 << 19,
+       /*< private >*/
        GS_PLUGIN_REFINE_FLAGS_LAST
 } GsPluginRefineFlags;
 
+/**
+ * GsPluginRefreshFlags:
+ * @GS_PLUGIN_REFRESH_FLAGS_NONE:      Generate new metadata if possible
+ * @GS_PLUGIN_REFRESH_FLAGS_METADATA:  Download new metadata
+ * @GS_PLUGIN_REFRESH_FLAGS_PAYLOAD:   Download any pending payload
+ * @GS_PLUGIN_REFRESH_FLAGS_UI:                FIXME
+ *
+ * The flags used for refresh. Regeneration and downloading is only
+ * done if the cache is older than the %cache_age.
+ *
+ * The %GS_PLUGIN_REFRESH_FLAGS_METADATA can be used to make sure
+ * there's enough metadata to start the application.
+ * The %GS_PLUGIN_REFRESH_FLAGS_PAYLOAD flag should only be used when
+ * the session is idle and bandwidth is unmetered as the amount of data
+ * and IO may be large.
+ **/
 typedef enum {
-       GS_PLUGIN_REFRESH_FLAGS_UPDATES                 = 1 << 0,
-       GS_PLUGIN_REFRESH_FLAGS_UI                      = 1 << 1,
+       GS_PLUGIN_REFRESH_FLAGS_NONE                    = 0,
+       GS_PLUGIN_REFRESH_FLAGS_METADATA                = 1 << 0,
+       GS_PLUGIN_REFRESH_FLAGS_PAYLOAD                 = 1 << 1,
+       GS_PLUGIN_REFRESH_FLAGS_UI                      = 1 << 2,
+       /*< private >*/
        GS_PLUGIN_REFRESH_FLAGS_LAST
 } GsPluginRefreshFlags;
 
@@ -130,6 +151,9 @@ typedef enum {
 typedef const gchar    *(*GsPluginGetNameFunc)         (void);
 typedef const gchar    **(*GsPluginGetDepsFunc)        (GsPlugin       *plugin);
 typedef void            (*GsPluginFunc)                (GsPlugin       *plugin);
+typedef gboolean        (*GsPluginSetupFunc)           (GsPlugin       *plugin,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 typedef gboolean        (*GsPluginSearchFunc)          (GsPlugin       *plugin,
                                                         gchar          **value,
                                                         GList          **list,
@@ -158,6 +182,11 @@ typedef gboolean    (*GsPluginRefineFunc)          (GsPlugin       *plugin,
                                                         GsPluginRefineFlags flags,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
+typedef gboolean        (*GsPluginRefineAppFunc)       (GsPlugin       *plugin,
+                                                        GsApp          *app,
+                                                        GsPluginRefineFlags flags,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 typedef gboolean        (*GsPluginRefreshFunc  )       (GsPlugin       *plugin,
                                                         guint           cache_age,
                                                         GsPluginRefreshFlags flags,
@@ -168,7 +197,7 @@ typedef gboolean     (*GsPluginFileToAppFunc)       (GsPlugin       *plugin,
                                                         GFile          *file,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
-typedef gboolean        (*GsPluginUpdateFunc)          (GsPlugin       *plugin,
+typedef gboolean        (*GsPluginOfflineUpdateFunc)   (GsPlugin       *plugin,
                                                         GList          *apps,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
@@ -178,6 +207,17 @@ void                gs_plugin_initialize                   (GsPlugin       *plugin);
 void            gs_plugin_destroy                      (GsPlugin       *plugin);
 void            gs_plugin_set_enabled                  (GsPlugin       *plugin,
                                                         gboolean        enabled);
+GBytes         *gs_plugin_download_data                (GsPlugin       *plugin,
+                                                        GsApp          *app,
+                                                        const gchar    *uri,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
+gboolean        gs_plugin_download_file                (GsPlugin       *plugin,
+                                                        GsApp          *app,
+                                                        const gchar    *uri,
+                                                        const gchar    *filename,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 gboolean        gs_plugin_check_distro_id              (GsPlugin       *plugin,
                                                         const gchar    *distro_id);
 void            gs_plugin_add_app                      (GList          **list,
@@ -219,6 +259,9 @@ gboolean     gs_plugin_add_search_what_provides     (GsPlugin       *plugin,
 const gchar    **gs_plugin_order_after                 (GsPlugin       *plugin);
 const gchar    **gs_plugin_order_before                (GsPlugin       *plugin);
 const gchar    **gs_plugin_get_conflicts               (GsPlugin       *plugin);
+gboolean        gs_plugin_setup                        (GsPlugin       *plugin,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 gboolean        gs_plugin_add_installed                (GsPlugin       *plugin,
                                                         GList          **list,
                                                         GCancellable   *cancellable,
@@ -265,11 +308,16 @@ gboolean   gs_plugin_refine                       (GsPlugin       *plugin,
                                                         GsPluginRefineFlags flags,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
+gboolean        gs_plugin_refine_app                   (GsPlugin       *plugin,
+                                                        GsApp          *app,
+                                                        GsPluginRefineFlags flags,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 gboolean        gs_plugin_launch                       (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
-gboolean        gs_plugin_update_cancel                (GsPlugin       *plugin,
+gboolean        gs_plugin_offline_update_cancel        (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
@@ -285,7 +333,7 @@ gboolean     gs_plugin_app_set_rating               (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
-gboolean        gs_plugin_update_app                   (GsPlugin       *plugin,
+gboolean        gs_plugin_app_update                   (GsPlugin       *plugin,
                                                         GsApp          *app,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
@@ -337,7 +385,7 @@ gboolean     gs_plugin_file_to_app                  (GsPlugin       *plugin,
                                                         GFile          *file,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
-gboolean        gs_plugin_update                       (GsPlugin       *plugin,
+gboolean        gs_plugin_offline_update               (GsPlugin       *plugin,
                                                         GList          *apps,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
diff --git a/src/gs-popular-tile.c b/src/gs-popular-tile.c
index d9c5f4b..d083104 100644
--- a/src/gs-popular-tile.c
+++ b/src/gs-popular-tile.c
@@ -159,7 +159,7 @@ gs_popular_tile_class_init (GsPopularTileClass *klass)
 
        widget_class->destroy = gs_popular_tile_destroy;
 
-       gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/popular-tile.ui");
+       gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-popular-tile.ui");
 
        gtk_widget_class_bind_template_child (widget_class, GsPopularTile, label);
        gtk_widget_class_bind_template_child (widget_class, GsPopularTile, image);
diff --git a/src/popular-tile.ui b/src/gs-popular-tile.ui
similarity index 100%
rename from src/popular-tile.ui
rename to src/gs-popular-tile.ui
diff --git a/src/gs-screenshot-image.c b/src/gs-screenshot-image.c
index 3cd176e..b72dda1 100644
--- a/src/gs-screenshot-image.c
+++ b/src/gs-screenshot-image.c
@@ -379,7 +379,17 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
                gs_screenshot_image_set_error (ssimg, _("Screenshot size not found"));
                return;
        }
+
+       /* check if the URL points to a local file */
        url = as_image_get_url (im);
+       if (g_str_has_prefix (url, "file://")) {
+               ssimg->filename = g_strdup (url + 7);
+               if (g_file_test (ssimg->filename, G_FILE_TEST_EXISTS)) {
+                       as_screenshot_show_image (ssimg);
+                       return;
+               }
+       }
+
        basename = gs_screenshot_get_cachefn_for_url (url);
        if (ssimg->width == G_MAXUINT || ssimg->height == G_MAXUINT) {
                sizedir = g_strdup ("unknown");
@@ -524,7 +534,7 @@ gs_screenshot_image_class_init (GsScreenshotImageClass *klass)
        widget_class->draw = gs_screenshot_image_draw;
 
        gtk_widget_class_set_template_from_resource (widget_class,
-                                                    "/org/gnome/Software/screenshot-image.ui");
+                                                    "/org/gnome/Software/gs-screenshot-image.ui");
 
        gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, stack);
        gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, image1);
diff --git a/src/screenshot-image.ui b/src/gs-screenshot-image.ui
similarity index 100%
rename from src/screenshot-image.ui
rename to src/gs-screenshot-image.ui
diff --git a/src/gs-self-test.c b/src/gs-self-test.c
index e66c515..8aa5ce7 100644
--- a/src/gs-self-test.c
+++ b/src/gs-self-test.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -21,13 +21,10 @@
 
 #include "config.h"
 
-#include <glib.h>
 #include <glib-object.h>
-#include <glib/gstdio.h>
 #include <stdlib.h>
 
 #include "gs-app.h"
-#include "gs-markdown.h"
 #include "gs-plugin.h"
 #include "gs-plugin-loader.h"
 #include "gs-plugin-loader-sync.h"
@@ -49,186 +46,6 @@ gs_test_get_filename (const gchar *filename)
        return g_strdup (full_tmp);
 }
 
-static void
-gs_markdown_func (void)
-{
-       gchar *text;
-       const gchar *markdown;
-       const gchar *markdown_expected;
-       g_autoptr(GsMarkdown) md = NULL;
-
-       /* get GsMarkdown object */
-       md = gs_markdown_new (GS_MARKDOWN_OUTPUT_PANGO);
-       g_assert (md);
-
-       markdown = "OEMs\n"
-                  "====\n"
-                  " - Bullett\n";
-       markdown_expected =
-                  "<big>OEMs</big>\n"
-                  "• Bullett";
-       /* markdown (type2 header) */
-       text = gs_markdown_parse (md, markdown);
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-
-       /* markdown (autocode) */
-       markdown = "this is http://www.hughsie.com/with_spaces_in_url inline link\n";
-       markdown_expected = "this is <tt>http://www.hughsie.com/with_spaces_in_url</tt> inline link";
-       gs_markdown_set_autocode (md, TRUE);
-       text = gs_markdown_parse (md, markdown);
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-
-       /* markdown some invalid header */
-       markdown = "*** This software is currently in alpha state ***\n";
-       markdown_expected = "<b><i> This software is currently in alpha state </b></i>";
-       text = gs_markdown_parse (md, markdown);
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-
-       /* markdown (complex1) */
-       markdown = " - This is a *very*\n"
-                  "   short paragraph\n"
-                  "   that is not usual.\n"
-                  " - Another";
-       markdown_expected =
-                  "• This is a <i>very</i> short paragraph that is not usual.\n"
-                  "• Another";
-       text = gs_markdown_parse (md, markdown);
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-
-       /* markdown (complex1) */
-       markdown = "*  This is a *very*\n"
-                  "   short paragraph\n"
-                  "   that is not usual.\n"
-                  "*  This is the second\n"
-                  "   bullett point.\n"
-                  "*  And the third.\n"
-                  " \n"
-                  "* * *\n"
-                  " \n"
-                  "Paragraph one\n"
-                  "isn't __very__ long at all.\n"
-                  "\n"
-                  "Paragraph two\n"
-                  "isn't much better.";
-       markdown_expected =
-                  "• This is a <i>very</i> short paragraph that is not usual.\n"
-                  "• This is the second bullett point.\n"
-                  "• And the third.\n"
-                  "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\n"
-                  "Paragraph one isn&apos;t <b>very</b> long at all.\n"
-                  "Paragraph two isn&apos;t much better.";
-       text = gs_markdown_parse (md, markdown);
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-
-       markdown = "This is a spec file description or\n"
-                  "an **update** description in bohdi.\n"
-                  "\n"
-                  "* * *\n"
-                  "# Big title #\n"
-                  "\n"
-                  "The *following* things 'were' fixed:\n"
-                  "- Fix `dave`\n"
-                  "* Fubar update because of \"security\"\n";
-       markdown_expected =
-                  "This is a spec file description or an <b>update</b> description in bohdi.\n"
-                  "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\n"
-                  "<big>Big title</big>\n"
-                  "The <i>following</i> things 'were' fixed:\n"
-                  "• Fix <tt>dave</tt>\n"
-                  "• Fubar update because of \"security\"";
-       /* markdown (complex2) */
-       text = gs_markdown_parse (md, markdown);
-       if (g_strcmp0 (text, markdown_expected) == 0)
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-
-       /* markdown (list with spaces) */
-       markdown = "* list seporated with spaces -\n"
-                  "  first item\n"
-                  "\n"
-                  "* second item\n"
-                  "\n"
-                  "* third item\n";
-       markdown_expected =
-                  "• list seporated with spaces - first item\n"
-                  "• second item\n"
-                  "• third item";
-       text = gs_markdown_parse (md, markdown);
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-
-       gs_markdown_set_max_lines (md, 1);
-
-       /* markdown (one line limit) */
-       markdown = "* list seporated with spaces -\n"
-                  "  first item\n"
-                  "* second item\n";
-       markdown_expected =
-                  "• list seporated with spaces - first item";
-       text = gs_markdown_parse (md, markdown);
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-
-       gs_markdown_set_max_lines (md, 1);
-
-       /* markdown (escaping) */
-       markdown = "* list & <spaces>";
-       markdown_expected =
-                  "• list &amp; &lt;spaces&gt;";
-       text = gs_markdown_parse (md, markdown);
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-
-       /* markdown (URLs) */
-       markdown = "this is the http://www.hughsie.com/ coolest site";
-       markdown_expected =
-                  "this is the "
-                  "<a href=\"http://www.hughsie.com/\";>http://www.hughsie.com/</a>"
-                  " coolest site";
-       text = gs_markdown_parse (md, markdown);
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-
-       /* markdown (free text) */
-       gs_markdown_set_escape (md, FALSE);
-       text = gs_markdown_parse (md, "This isn't a present");
-       g_assert_cmpstr (text, ==, "This isn't a present");
-       g_free (text);
-
-       /* markdown (autotext underscore) */
-       text = gs_markdown_parse (md, "This isn't CONFIG_UEVENT_HELPER_PATH present");
-       g_assert_cmpstr (text, ==, "This isn't <tt>CONFIG_UEVENT_HELPER_PATH</tt> present");
-       g_free (text);
-
-       /* markdown (end of bullett) */
-       markdown = "*Thu Mar 12 12:00:00 2009* Dan Walsh <dwalsh redhat com> - 2.0.79-1\n"
-                  "- Update to upstream \n"
-                  " * Netlink socket handoff patch from Adam Jackson.\n"
-                  " * AVC caching of compute_create results by Eric Paris.\n"
-                  "\n"
-                  "*Tue Mar 10 12:00:00 2009* Dan Walsh <dwalsh redhat com> - 2.0.78-5\n"
-                  "- Add patch from ajax to accellerate X SELinux \n"
-                  "- Update eparis patch\n";
-       markdown_expected =
-                  "<i>Thu Mar 12 12:00:00 2009</i> Dan Walsh <tt>&lt;dwalsh redhat com&gt;</tt> - 2.0.79-1\n"
-                  "• Update to upstream\n"
-                  "• Netlink socket handoff patch from Adam Jackson.\n"
-                  "• AVC caching of compute_create results by Eric Paris.\n"
-                  "<i>Tue Mar 10 12:00:00 2009</i> Dan Walsh <tt>&lt;dwalsh redhat com&gt;</tt> - 2.0.78-5\n"
-                  "• Add patch from ajax to accellerate X SELinux\n"
-                  "• Update eparis patch";
-       gs_markdown_set_escape (md, TRUE);
-       gs_markdown_set_max_lines (md, 1024);
-       text = gs_markdown_parse (md, markdown);
-       g_assert_cmpstr (text, ==, markdown_expected);
-       g_free (text);
-}
-
 static gboolean
 gs_plugin_list_filter_cb (GsApp *app, gpointer user_data)
 {
@@ -289,19 +106,6 @@ gs_plugin_func (void)
 }
 
 static void
-gs_app_subsume_func (void)
-{
-       g_autoptr(GsApp) new = NULL;
-       g_autoptr(GsApp) old = NULL;
-
-       new = gs_app_new ("xxx.desktop");
-       old = gs_app_new ("yyy.desktop");
-       gs_app_set_metadata (old, "foo", "bar");
-       gs_app_subsume (new, old);
-       g_assert_cmpstr (gs_app_get_metadata_item (new, "foo"), ==, "bar");
-}
-
-static void
 gs_app_func (void)
 {
        g_autoptr(GsApp) app = NULL;
@@ -327,6 +131,14 @@ gs_app_func (void)
        g_assert_cmpstr (gs_app_get_name (app), ==, "dave");
        gs_app_set_name (app, GS_APP_QUALITY_HIGHEST, "hugh");
        g_assert_cmpstr (gs_app_get_name (app), ==, "hugh");
+
+       /* check non-transient state saving */
+       gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
+       gs_app_set_state (app, AS_APP_STATE_REMOVING);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_REMOVING);
+       gs_app_set_state_recover (app); // simulate an error
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
 }
 
 static guint _status_changed_cnt = 0;
@@ -341,358 +153,274 @@ gs_plugin_loader_status_changed_cb (GsPluginLoader *plugin_loader,
 }
 
 static void
-gs_plugin_loader_dedupe_func (void)
+gs_plugin_loader_install_func (GsPluginLoader *plugin_loader)
 {
-       g_autoptr(GsApp) app1 = NULL;
-       g_autoptr(GsApp) app2 = NULL;
-       g_autoptr(GsPluginLoader) loader = NULL;
-
-       loader = gs_plugin_loader_new ();
-
-       /* add app */
-       app1 = gs_app_new ("app1");
-       gs_app_set_description (app1, GS_APP_QUALITY_NORMAL, "description");
-       app1 = gs_plugin_loader_dedupe (loader, app1);
-       g_assert_cmpstr (gs_app_get_id (app1), ==, "app1");
-       g_assert_cmpstr (gs_app_get_description (app1), ==, "description");
-
-       app2 = gs_app_new ("app1");
-       app2 = gs_plugin_loader_dedupe (loader, app2);
-       g_assert_cmpstr (gs_app_get_id (app2), ==, "app1");
-       g_assert_cmpstr (gs_app_get_description (app2), ==, "description");
-       app2 = gs_plugin_loader_dedupe (loader, app2);
-       g_assert_cmpstr (gs_app_get_id (app2), ==, "app1");
-       g_assert_cmpstr (gs_app_get_description (app2), ==, "description");
+       gboolean ret;
+       g_autoptr(GsApp) app = NULL;
+       g_autoptr(GError) error = NULL;
+
+       /* install */
+       app = gs_app_new ("chiron.desktop");
+       gs_app_set_management_plugin (app, "dummy");
+       gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+       ret = gs_plugin_loader_app_action (plugin_loader, app,
+                                          GS_PLUGIN_LOADER_ACTION_INSTALL,
+                                          NULL,
+                                          &error);
+       g_assert_no_error (error);
+       g_assert (ret);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
+
+       /* remove -- we're really testing for return code UNKNOWN,
+        * but dummy::refine() sets it */
+       ret = gs_plugin_loader_app_action (plugin_loader, app,
+                                          GS_PLUGIN_LOADER_ACTION_REMOVE,
+                                          NULL,
+                                          &error);
+       g_assert_no_error (error);
+       g_assert (ret);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
 }
 
 static void
-gs_plugin_loader_func (void)
+gs_plugin_loader_error_func (GsPluginLoader *plugin_loader)
 {
        gboolean ret;
-       GError *error = NULL;
-       GList *list;
-       GList *l;
-       GsApp *app;
-       g_autoptr(GsPluginLoader) loader = NULL;
-
-       /* not avaiable in make distcheck */
-       if (!g_file_test (GS_MODULESETDIR, G_FILE_TEST_EXISTS))
-               return;
+       g_autoptr(GsApp) app = NULL;
+       g_autoptr(GError) error = NULL;
+       GError *last_error;
+
+       /* suppress this */
+       g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                              "failed to call gs_plugin_app_update on dummy*");
+
+       /* update, which should cause an error to be emitted */
+       app = gs_app_new ("chiron.desktop");
+       gs_app_set_management_plugin (app, "dummy");
+       gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+       ret = gs_plugin_loader_app_action (plugin_loader, app,
+                                          GS_PLUGIN_LOADER_ACTION_UPDATE,
+                                          NULL,
+                                          &error);
+//     g_assert_no_error (error);
+//     g_assert (ret);
 
-       loader = gs_plugin_loader_new ();
-       g_assert (GS_IS_PLUGIN_LOADER (loader));
-       g_signal_connect (loader, "status-changed",
-                         G_CALLBACK (gs_plugin_loader_status_changed_cb), NULL);
+       /* ensure we failed the plugin action */
+       g_test_assert_expected_messages ();
 
-       /* load the plugins */
-       gs_plugin_loader_set_location (loader, "./plugins/.libs");
-       ret = gs_plugin_loader_setup (loader, &error);
-       g_assert_no_error (error);
-       g_assert (ret);
+       /* retrieve the error from the application */
+       last_error = gs_app_get_last_error (app);
+       g_assert_error (last_error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NO_NETWORK);
+}
 
-       /* enable some that will give us predictable results */
-       ret = gs_plugin_loader_set_enabled (loader, "dummy", TRUE);
-       g_assert (ret);
-       ret = gs_plugin_loader_set_enabled (loader, "hardcoded-kind", TRUE);
-       g_assert (ret);
-       ret = gs_plugin_loader_set_enabled (loader, "moduleset", TRUE);
-       g_assert (ret);
-       ret = gs_plugin_loader_set_enabled (loader, "hardcoded-ratings", TRUE);
-       g_assert (ret);
-       ret = gs_plugin_loader_set_enabled (loader, "datadir-filename", TRUE);
-       g_assert (ret);
-       ret = gs_plugin_loader_set_enabled (loader, "datadir-apps", TRUE);
-       g_assert (ret);
-       ret = gs_plugin_loader_set_enabled (loader, "notgoingtoexist", TRUE);
-       g_assert (!ret);
+static void
+gs_plugin_loader_refine_func (GsPluginLoader *plugin_loader)
+{
+       gboolean ret;
+       g_autoptr(GsApp) app = NULL;
+       g_autoptr(GError) error = NULL;
 
-       list = gs_plugin_loader_get_popular (loader, GS_PLUGIN_REFINE_FLAGS_DEFAULT, NULL, &error);
+       /* get the extra bits */
+       app = gs_app_new ("chiron.desktop");
+       gs_app_set_management_plugin (app, "dummy");
+       ret = gs_plugin_loader_app_refine (plugin_loader, app,
+                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION |
+                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE |
+                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL,
+                                          NULL,
+                                          &error);
        g_assert_no_error (error);
-       g_assert (list != NULL);
-       g_assert_cmpint (_status_changed_cnt, ==, 1);
-       g_assert_cmpint (g_list_length (list), ==, 6);
-       app = g_list_nth_data (list, 0);
-       g_assert_cmpstr (gs_app_get_id (app), ==, "gnome-boxes");
-       g_assert_cmpstr (gs_app_get_name (app), ==, "Boxes");
+       g_assert (ret);
 
-       app = g_list_nth_data (list, 1);
-       g_assert_cmpstr (gs_app_get_id (app), ==, "gedit");
-       g_assert_cmpstr (gs_app_get_summary (app), ==, "Edit text files");
+       g_assert_cmpstr (gs_app_get_license (app), ==,
+                        "<a href=\"http://spdx.org/licenses/GPL-2.0+\";>GPL-2.0+</a>");
+       g_assert_cmpstr (gs_app_get_description (app), !=, NULL);
+       g_assert_cmpstr (gs_app_get_url (app, AS_URL_KIND_HOMEPAGE), ==, "http://www.test.org/";);
+}
 
-       gs_plugin_list_free (list);
+static void
+gs_plugin_loader_updates_func (GsPluginLoader *plugin_loader)
+{
+       GsApp *app;
+       g_autoptr(GError) error = NULL;
+       g_autoptr(GsAppList) list = NULL;
 
-       /* get updates */
-       _status_changed_cnt = 0;
-       list = gs_plugin_loader_get_updates (loader, GS_PLUGIN_REFINE_FLAGS_DEFAULT, NULL, &error);
+       /* get the updates list */
+       list = gs_plugin_loader_get_updates (plugin_loader,
+                                            GS_PLUGIN_REFINE_FLAGS_DEFAULT,
+                                            NULL,
+                                            &error);
        g_assert_no_error (error);
        g_assert (list != NULL);
-       g_assert_cmpint (_status_changed_cnt, >=, 1);
+
+       /* make sure there are two entries */
        g_assert_cmpint (g_list_length (list), ==, 2);
        app = g_list_nth_data (list, 0);
-       g_assert_cmpstr (gs_app_get_id (app), ==, 
"os-update:gnome-boxes-libs;0.0.1;i386;updates-testing,libvirt-glib-devel;0.0.1;noarch;fedora");
-       g_assert_cmpstr (gs_app_get_name (app), ==, "OS Updates");
-//     g_assert_cmpstr (gs_app_get_summary (app), ==, "Includes performance, stability and security 
improvements for all users\nDo not segfault when using newer versons of libvirt.\nFix several memory leaks.");
-       g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_OS_UPDATE);
+       g_assert_cmpstr (gs_app_get_id (app), ==, "chiron.desktop");
+       g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_UPDATABLE_LIVE);
+       g_assert_cmpstr (gs_app_get_update_details (app), ==, "Do not crash when using libvirt.");
+       g_assert_cmpint (gs_app_get_update_urgency (app), ==, AS_URGENCY_KIND_HIGH);
 
+       /* get the virtual non-apps OS update */
        app = g_list_nth_data (list, 1);
-       g_assert_cmpstr (gs_app_get_id (app), ==, "gnome-boxes");
-       g_assert_cmpstr (gs_app_get_name (app), ==, "Boxes");
-       g_assert_cmpstr (gs_app_get_summary (app), ==, "Do not segfault when using newer versons of 
libvirt.");
-       g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
-       gs_plugin_list_free (list);
+       g_assert_cmpstr (gs_app_get_id (app), ==, "os-update.virtual");
+       g_assert_cmpstr (gs_app_get_name (app), ==, "OS Updates");
+       g_assert_cmpstr (gs_app_get_summary (app), ==, "Includes performance, stability and security 
improvements.");
+       g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_OS_UPDATE);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_UPDATABLE);
+       g_assert_cmpint (gs_app_get_related(app)->len, ==, 2);
+}
 
-       /* test packagekit */
-       gs_plugin_loader_set_enabled (loader, "dummy", FALSE);
-       ret = gs_plugin_loader_set_enabled (loader, "packagekit", TRUE);
-       g_assert (ret);
-       ret = gs_plugin_loader_set_enabled (loader, "desktopdb", TRUE);
-       g_assert (ret);
-       ret = gs_plugin_loader_set_enabled (loader, "datadir-apps", TRUE);
-       g_assert (ret);
+static void
+gs_plugin_loader_distro_upgrades_func (GsPluginLoader *plugin_loader)
+{
+       GsApp *app;
+       gboolean ret;
+       g_autoptr(GError) error = NULL;
+       g_autoptr(GsAppList) list = NULL;
 
-       list = gs_plugin_loader_get_installed (loader, GS_PLUGIN_REFINE_FLAGS_DEFAULT, NULL, &error);
+       /* get the updates list */
+       list = gs_plugin_loader_get_distro_upgrades (plugin_loader,
+                                                    GS_PLUGIN_REFINE_FLAGS_DEFAULT,
+                                                    NULL,
+                                                    &error);
        g_assert_no_error (error);
        g_assert (list != NULL);
-       g_assert_cmpint (g_list_length (list), >, 50);
-
-       /* find a specific app */
-       for (l = list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               if (g_strcmp0 (gs_app_get_id (app), "gnome-screenshot") == 0)
-                       break;
-       }
-       g_assert_cmpstr (gs_app_get_id (app), ==, "gnome-screenshot");
-       g_assert_cmpstr (gs_app_get_name (app), ==, "Screenshot");
-       g_assert_cmpstr (gs_app_get_summary (app), ==, "Save images of your screen or individual windows");
-       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
-       g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
-       g_assert (gs_app_has_quirk (app, AS_APP_QUIRK_COMPULSORY));
-       g_assert (gs_app_get_pixbuf (app) != NULL);
-       gs_plugin_list_free (list);
 
-       /* do this again, which should be much faster */
-       list = gs_plugin_loader_get_installed (loader, GS_PLUGIN_REFINE_FLAGS_DEFAULT, NULL, &error);
-       g_assert_no_error (error);
-       g_assert (list != NULL);
-       g_assert_cmpint (g_list_length (list), >, 50);
-       gs_plugin_list_free (list);
+       /* make sure there is one entry */
+       g_assert_cmpint (g_list_length (list), ==, 1);
+       app = GS_APP (list->data);
+       g_assert_cmpstr (gs_app_get_id (app), ==, "org.fedoraproject.release-24.upgrade");
+       g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_OS_UPGRADE);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_AVAILABLE);
 
-       /* set a rating */
-       gs_plugin_loader_set_enabled (loader, "packagekit", FALSE);
-       gs_plugin_loader_set_enabled (loader, "desktopdb", FALSE);
-       gs_plugin_loader_set_enabled (loader, "datadir-apps", FALSE);
-       ret = gs_plugin_loader_set_enabled (loader, "local-ratings", TRUE);
-       g_assert (ret);
+       /* this should be set with a higher priority by AppStream */
+       g_assert_cmpstr (gs_app_get_summary (app), ==, "Release specific tagline");
 
-       /* create a dummy value */
-       app = gs_app_new ("self-test");
-       gs_app_set_rating (app, 35);
-       ret = gs_plugin_loader_app_action (loader,
+       /* download the update */
+       ret = gs_plugin_loader_app_action (plugin_loader,
                                           app,
-                                          GS_PLUGIN_LOADER_ACTION_SET_RATING,
+                                          GS_PLUGIN_LOADER_ACTION_UPGRADE_DOWNLOAD,
                                           NULL,
                                           &error);
        g_assert_no_error (error);
        g_assert (ret);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_UPDATABLE);
 
-       /* get the saved value */
-       gs_app_set_rating (app, -1);
-       ret = gs_plugin_loader_app_refine (loader,
+       /* trigger the update */
+       ret = gs_plugin_loader_app_action (plugin_loader,
                                           app,
-                                          GS_PLUGIN_REFINE_FLAGS_DEFAULT,
+                                          GS_PLUGIN_LOADER_ACTION_UPGRADE_TRIGGER,
                                           NULL,
                                           &error);
        g_assert_no_error (error);
        g_assert (ret);
-       g_assert_cmpint (gs_app_get_rating (app), ==, 35);
-       g_object_unref (app);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_UPDATABLE);
 }
 
 static void
-gs_plugin_loader_refine_func (void)
+gs_plugin_loader_installed_func (GsPluginLoader *plugin_loader)
 {
-       GError *error = NULL;
-       const gchar *url;
-       gboolean ret;
-       g_autoptr(GsApp) app = NULL;
-       g_autoptr(GsPluginLoader) loader = NULL;
-
-       /* not avaiable in make distcheck */
-       if (!g_file_test (GS_MODULESETDIR, G_FILE_TEST_EXISTS))
-               return;
+       GsApp *app;
+       GsApp *addon;
+       GPtrArray *addons;
+       guint64 kudos;
+       g_autofree gchar *menu_path = NULL;
+       g_autoptr(GError) error = NULL;
+       g_autoptr(GsAppList) list = NULL;
 
-       /* load the plugins */
-       loader = gs_plugin_loader_new ();
-       gs_plugin_loader_set_location (loader, "./plugins/.libs");
-       ret = gs_plugin_loader_setup (loader, &error);
+       /* get installed packages */
+       list = gs_plugin_loader_get_installed (plugin_loader,
+                                              GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE |
+                                              GS_PLUGIN_REFINE_FLAGS_REQUIRE_MENU_PATH |
+                                              GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE,
+                                              NULL,
+                                              &error);
        g_assert_no_error (error);
-       g_assert (ret);
-
-       ret = gs_plugin_loader_set_enabled (loader, "dummy", TRUE);
-       g_assert (ret);
+       g_assert (list != NULL);
 
-       /* get the extra bits */
-       app = gs_app_new ("gnome-boxes");
-       gs_app_add_source (app, "gnome-boxes");
-       ret = gs_plugin_loader_app_refine (loader, app,
-                                          GS_PLUGIN_REFINE_FLAGS_DEFAULT |
-                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION |
-                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE |
-                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL,
-                                          NULL,
-                                          &error);
-       g_assert_no_error (error);
-       g_assert (ret);
+       /* make sure there is one entry */
+       g_assert_cmpint (g_list_length (list), ==, 1);
+       app = GS_APP (list->data);
+       g_assert_cmpstr (gs_app_get_id (app), ==, "zeus.desktop");
+       g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_INSTALLED);
+       g_assert_cmpstr (gs_app_get_name (app), ==, "Zeus");
+       g_assert_cmpstr (gs_app_get_source_default (app), ==, "zeus");
+       g_assert (gs_app_get_pixbuf (app) != NULL);
 
-       g_assert_cmpstr (gs_app_get_license (app), ==,
-                        "<a href=\"http://spdx.org/licenses/GPL-2.0+\";>GPL-2.0+</a>");
-       g_assert_cmpstr (gs_app_get_description (app), !=, NULL);
-       url = gs_app_get_url (app, AS_URL_KIND_HOMEPAGE);
-       g_assert_cmpstr (url, ==, "http://www.gimp.org/";);
+       /* check various bitfields */
+       g_assert (gs_app_has_quirk (app, AS_APP_QUIRK_PROVENANCE));
+       g_assert (gs_app_get_license_is_free (app));
+
+       /* check kudos */
+       kudos = gs_app_get_kudos (app);
+       g_assert (kudos & GS_APP_KUDO_MY_LANGUAGE);
+
+       /* check categories */
+       g_assert (gs_app_has_category (app, "Audio"));
+       g_assert (gs_app_has_category (app, "Player"));
+       g_assert (gs_app_has_category (app, "AudioVideo"));
+       g_assert (!gs_app_has_category (app, "ImageProcessing"));
+       g_assert (gs_app_get_menu_path (app) != NULL);
+       menu_path = g_strjoinv ("->", gs_app_get_menu_path (app));
+       g_assert_cmpstr (menu_path, ==, "Audio->Players");
+
+       /* check addon */
+       addons = gs_app_get_addons (app);
+       g_assert_cmpint (addons->len, ==, 1);
+       addon = g_ptr_array_index (addons, 0);
+       g_assert_cmpstr (gs_app_get_id (addon), ==, "zeus-spell.addon");
+       g_assert_cmpint (gs_app_get_kind (addon), ==, AS_APP_KIND_ADDON);
+       g_assert_cmpint (gs_app_get_state (addon), ==, AS_APP_STATE_UNKNOWN);
+       g_assert_cmpstr (gs_app_get_name (addon), ==, "Spell Check");
+       g_assert_cmpstr (gs_app_get_source_default (addon), ==, "zeus-spell");
+       g_assert (gs_app_get_pixbuf (addon) == NULL);
 }
 
 static void
-gs_plugin_loader_empty_func (void)
+gs_plugin_loader_search_func (GsPluginLoader *plugin_loader)
 {
-       gboolean ret;
-       GError *error = NULL;
-       GList *apps;
-       GList *l;
-       GList *l2;
-       GList *subcats;
-       GsCategory *category;
-       GsCategory *sub;
-       guint empty_subcats_cnt = 0;
+       GsApp *app;
+       g_autofree gchar *menu_path = NULL;
+       g_autoptr(GError) error = NULL;
        g_autoptr(GsAppList) list = NULL;
-       g_autoptr(GsPluginLoader) loader = NULL;
-
-       /* not avaiable in make distcheck */
-       if (!g_file_test (GS_MODULESETDIR, G_FILE_TEST_EXISTS))
-               return;
 
-       /* load the plugins */
-       loader = gs_plugin_loader_new ();
-       gs_plugin_loader_set_location (loader, "./plugins/.libs");
-       ret = gs_plugin_loader_setup (loader, &error);
-       g_assert_no_error (error);
-       g_assert (ret);
-
-       ret = gs_plugin_loader_set_enabled (loader, "hardcoded-menu-spec", TRUE);
-       g_assert (ret);
-       ret = gs_plugin_loader_set_enabled (loader, "appstream", TRUE);
-       g_assert (ret);
-       ret = gs_plugin_loader_set_enabled (loader, "self-test", TRUE);
-       g_assert (ret);
-
-       /* get the list of categories */
-       list = gs_plugin_loader_get_categories (loader, GS_PLUGIN_REFINE_FLAGS_DEFAULT, NULL, &error);
+       /* get search result based on addon keyword */
+       list = gs_plugin_loader_search (plugin_loader,
+                                       "spell",
+                                       GS_PLUGIN_REFINE_FLAGS_DEFAULT,
+                                       NULL,
+                                       &error);
        g_assert_no_error (error);
        g_assert (list != NULL);
 
-       /* find how many packages each sub category has */
-       for (l = list; l != NULL; l = l->next) {
-               category = GS_CATEGORY (l->data);
-               subcats = gs_category_get_subcategories (category);
-               if (subcats == NULL)
-                       continue;
-               for (l2 = subcats; l2 != NULL; l2 = l2->next) {
-                       sub = GS_CATEGORY (l2->data);
-
-                       /* ignore general */
-                       if (gs_category_get_id (sub) == NULL)
-                               continue;
-
-                       /* find subcaegories that have no applications */
-                       apps = gs_plugin_loader_get_category_apps (loader,
-                                                                  sub,
-                                                                  GS_PLUGIN_REFINE_FLAGS_DEFAULT,
-                                                                  NULL,
-                                                                  &error);
-                       if (apps == NULL) {
-                               g_debug ("NOAPPS:\t%s/%s: %s",
-                                        gs_category_get_id (category),
-                                        gs_category_get_id (sub),
-                                        error->message);
-                               g_clear_error (&error);
-                               empty_subcats_cnt++;
-                               //g_warning ("MOO");
-                       } else {
-                               GList *g;
-                               if (g_getenv ("DUMPGROUPS") != NULL) {
-                                       for (g = apps; g != NULL; g = g->next) {
-                                               g_print ("Cat: %s\tSubCat: %s\tPkgName: %s\tAppId: %s\n",
-                                                        gs_category_get_id (category),
-                                                        gs_category_get_id (sub),
-                                                        gs_app_get_source_default (GS_APP (g->data)),
-                                                        gs_app_get_id (GS_APP (g->data)));
-                                       }
-                               }
-                               g_debug ("APPS[%i]:\t%s/%s",
-                                        g_list_length (apps),
-                                        gs_category_get_id (category),
-                                        gs_category_get_id (sub));
-                       }
-                       g_list_free_full (apps, (GDestroyNotify) g_object_unref);
-               }
-               g_list_free (subcats);
-       }
-       g_assert_cmpint (empty_subcats_cnt, ==, 0);
+       /* make sure there is one entry, the parent app */
+       g_assert_cmpint (g_list_length (list), ==, 1);
+       app = GS_APP (list->data);
+       g_assert_cmpstr (gs_app_get_id (app), ==, "zeus.desktop");
+       g_assert_cmpint (gs_app_get_kind (app), ==, AS_APP_KIND_DESKTOP);
 }
 
 static void
-gs_plugin_loader_webapps_func (void)
+gs_plugin_loader_webapps_func (GsPluginLoader *plugin_loader)
 {
        gboolean ret;
-       GError *error = NULL;
-       g_autofree gchar *path = NULL;
+       g_autoptr(GError) error = NULL;
        g_autoptr(GsApp) app = NULL;
-       g_autoptr(GsPluginLoader) loader = NULL;
-
-       /* not avaiable in make distcheck */
-       if (!g_file_test (GS_MODULESETDIR, G_FILE_TEST_EXISTS))
-               return;
 
-       /* load the plugins */
-       loader = gs_plugin_loader_new ();
-       gs_plugin_loader_set_location (loader, "./plugins/.libs");
-       ret = gs_plugin_loader_setup (loader, &error);
-       g_assert_no_error (error);
-       g_assert (ret);
-
-       /* save shitty file */
-       path = g_build_filename (g_get_user_data_dir (),
-                                "app-info",
-                                "xmls",
-                                "test.xml",
-                                NULL);
-       ret = gs_mkdir_parent (path, &error);
-       g_assert_no_error (error);
-       g_assert (ret);
-       ret = g_file_set_contents (path,
-                                  "<?xml version=\"1.0\"?>\n"
-                                  "<applications version=\"0.1\">\n"
-                                  "  <application>\n"
-                                  "    <id type=\"webapp\">epiphany-test.desktop</id>\n"
-                                  "    <name>test</name>\n"
-                                  "    <icon type=\"remote\">http://www.test.com/test.png</icon>\n"
-                                  "  </application>\n"
-                                  "</applications>\n",
-                                  -1,
-                                  &error);
-       g_assert_no_error (error);
-       g_assert (ret);
-
-       /* load a webapp with a failing icon */
-       app = gs_app_new ("epiphany-test");
-       ret = gs_plugin_loader_app_refine (loader, app,
+       /* a webapp with a local icon */
+       app = gs_app_new ("arachne.desktop");
+       gs_app_set_kind (app, AS_APP_KIND_WEB_APP);
+       ret = gs_plugin_loader_app_refine (plugin_loader, app,
                                           GS_PLUGIN_REFINE_FLAGS_DEFAULT,
                                           NULL,
                                           &error);
        g_assert_no_error (error);
        g_assert (ret);
-       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_UNAVAILABLE);
-
-       g_unlink (path);
+       g_assert_cmpint (gs_app_get_state (app), ==, AS_APP_STATE_AVAILABLE);
+       g_assert (gs_app_get_pixbuf (app) != NULL);
 }
 
 static void
@@ -736,7 +464,6 @@ main (int argc, char **argv)
        g_autoptr(GsPluginLoader) plugin_loader = NULL;
        const gchar *whitelist[] = {
                "appstream",
-               "dpkg",
                "dummy",
                "epiphany",
                "hardcoded-blacklist",
@@ -748,24 +475,109 @@ main (int argc, char **argv)
 
        g_test_init (&argc, &argv, NULL);
        g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
-       g_setenv ("GNOME_SOFTWARE_SELF_TEST", "1", TRUE);
+
+       /* set all the things required as a dummy test harness */
+       g_setenv ("GS_SELF_TEST_LOCALE", "en_GB", TRUE);
+       g_setenv ("GS_SELF_TEST_DUMMY_ENABLE", "1", TRUE);
+       g_setenv ("GS_SELF_TEST_PROVENANCE_SOURCES", "london*,boston", TRUE);
+
+       fn = gs_test_get_filename ("icons/hicolor/48x48/org.gnome.Software.png");
+       g_assert (fn != NULL);
+       xml = g_strdup_printf ("<?xml version=\"1.0\"?>\n"
+               "<components version=\"0.9\">\n"
+               "  <component type=\"desktop\">\n"
+               "    <id>zeus.desktop</id>\n"
+               "    <name>Zeus</name>\n"
+               "    <summary>A teaching application</summary>\n"
+               "    <pkgname>zeus</pkgname>\n"
+               "    <icon type=\"stock\">drive-harddisk</icon>\n"
+               "    <categories>\n"
+               "      <category>AudioVideo</category>\n"
+               "      <category>Player</category>\n"
+               "    </categories>\n"
+               "    <languages>\n"
+               "      <lang percentage=\"100\">en_GB</lang>\n"
+               "    </languages>\n"
+               "  </component>\n"
+               "  <component type=\"desktop\">\n"
+               "    <id>mate-spell.desktop</id>\n"
+               "    <name>Spell</name>\n"
+               "    <summary>A spelling application for MATE</summary>\n"
+               "    <pkgname>mate-spell</pkgname>\n"
+               "    <icon type=\"stock\">drive-harddisk</icon>\n"
+               "    <project_group>MATE</project_group>\n"
+               "  </component>\n"
+               "  <component type=\"addon\">\n"
+               "    <id>zeus-spell.addon</id>\n"
+               "    <extends>zeus.desktop</extends>\n"
+               "    <name>Spell Check</name>\n"
+               "    <summary>Check the spelling when teaching</summary>\n"
+               "    <pkgname>zeus-spell</pkgname>\n"
+               "  </component>\n"
+               "  <component type=\"desktop\">\n"
+               "    <id>Uninstall Zeus.desktop</id>\n"
+               "    <name>Uninstall Zeus</name>\n"
+               "    <summary>Uninstall the teaching application</summary>\n"
+               "    <icon type=\"stock\">drive-harddisk</icon>\n"
+               "  </component>\n"
+               "  <component type=\"os-upgrade\">\n"
+               "    <id>org.fedoraproject.release-24.upgrade</id>\n"
+               "    <summary>Release specific tagline</summary>\n"
+               "  </component>\n"
+               "  <component type=\"webapp\">\n"
+               "    <id>arachne.desktop</id>\n"
+               "    <name>test</name>\n"
+               "    <icon type=\"remote\">file://%s</icon>\n"
+               "  </component>\n"
+               "</components>\n", fn);
+       g_setenv ("GS_SELF_TEST_APPSTREAM_XML", xml, TRUE);
 
        /* only critical and error are fatal */
        g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
 
-       /* tests go here */
-       g_test_add_func ("/gnome-software/markdown", gs_markdown_func);
-       g_test_add_func ("/gnome-software/plugin-loader{refine}", gs_plugin_loader_refine_func);
-       g_test_add_func ("/gnome-software/plugin", gs_plugin_func);
+       /* generic tests go here */
        g_test_add_func ("/gnome-software/app", gs_app_func);
-       g_test_add_func ("/gnome-software/app{subsume}", gs_app_subsume_func);
-       if (g_getenv ("HAS_APPSTREAM") != NULL)
-               g_test_add_func ("/gnome-software/plugin-loader{empty}", gs_plugin_loader_empty_func);
-       g_test_add_func ("/gnome-software/plugin-loader{dedupe}", gs_plugin_loader_dedupe_func);
-       if(0)g_test_add_func ("/gnome-software/plugin-loader", gs_plugin_loader_func);
-       if(0)g_test_add_func ("/gnome-software/plugin-loader{webapps}", gs_plugin_loader_webapps_func);
-       if(0)g_test_add_func ("/gnome-software/plugin-loader{dpkg}", gs_plugin_loader_dpkg_func);
+       g_test_add_func ("/gnome-software/plugin", gs_plugin_func);
 
+       /* we can only load this once per process */
+       plugin_loader = gs_plugin_loader_new ();
+       gs_plugin_loader_set_network_status (plugin_loader, TRUE);
+       g_signal_connect (plugin_loader, "status-changed",
+                         G_CALLBACK (gs_plugin_loader_status_changed_cb), NULL);
+       gs_plugin_loader_set_location (plugin_loader, "./plugins/.libs");
+       ret = gs_plugin_loader_setup (plugin_loader, (gchar**) whitelist, &error);
+       g_assert_no_error (error);
+       g_assert (ret);
+       g_assert (!gs_plugin_loader_get_enabled (plugin_loader, "notgoingtoexist"));
+       g_assert (!gs_plugin_loader_get_enabled (plugin_loader, "packagekit"));
+       g_assert (gs_plugin_loader_get_enabled (plugin_loader, "appstream"));
+       g_assert (gs_plugin_loader_get_enabled (plugin_loader, "dummy"));
+
+       /* plugin tests go here */
+       g_test_add_data_func ("/gnome-software/plugin-loader{webapps}",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugin_loader_webapps_func);
+       g_test_add_data_func ("/gnome-software/plugin-loader{search}",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugin_loader_search_func);
+       g_test_add_data_func ("/gnome-software/plugin-loader{install}",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugin_loader_install_func);
+       g_test_add_data_func ("/gnome-software/plugin-loader{error}",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugin_loader_error_func);
+       g_test_add_data_func ("/gnome-software/plugin-loader{installed}",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugin_loader_installed_func);
+       g_test_add_data_func ("/gnome-software/plugin-loader{refine}",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugin_loader_refine_func);
+       g_test_add_data_func ("/gnome-software/plugin-loader{updates}",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugin_loader_updates_func);
+       g_test_add_data_func ("/gnome-software/plugin-loader{distro-upgrades}",
+                             plugin_loader,
+                             (GTestDataFunc) gs_plugin_loader_distro_upgrades_func);
        return g_test_run ();
 }
 
diff --git a/src/gs-shell-details.c b/src/gs-shell-details.c
index de00aea..35609b7 100644
--- a/src/gs-shell-details.c
+++ b/src/gs-shell-details.c
@@ -81,8 +81,8 @@ struct _GsShellDetails
        GtkWidget               *label_details_category_value;
        GtkWidget               *label_details_developer_title;
        GtkWidget               *label_details_developer_value;
-       GtkWidget               *label_details_licence_title;
-       GtkWidget               *label_details_licence_value;
+       GtkWidget               *label_details_license_title;
+       GtkWidget               *label_details_license_value;
        GtkWidget               *label_details_origin_title;
        GtkWidget               *label_details_origin_value;
        GtkWidget               *label_details_size_value;
@@ -664,19 +664,19 @@ gs_shell_details_refresh_all (GsShellDetails *self)
                gtk_widget_set_visible (self->label_details_developer_value, TRUE);
        }
 
-       /* set the licence */
+       /* set the license */
        tmp = gs_app_get_license (self->app);
        if (tmp == NULL) {
-               /* TRANSLATORS: this is where the licence is not known */
-               gtk_label_set_label (GTK_LABEL (self->label_details_licence_value), C_("license", "Unknown"));
-               gtk_widget_set_tooltip_text (self->label_details_licence_value, NULL);
-               gtk_widget_set_visible (self->label_details_licence_title, FALSE);
-               gtk_widget_set_visible (self->label_details_licence_value, FALSE);
+               /* TRANSLATORS: this is where the license is not known */
+               gtk_label_set_label (GTK_LABEL (self->label_details_license_value), C_("license", "Unknown"));
+               gtk_widget_set_tooltip_text (self->label_details_license_value, NULL);
+               gtk_widget_set_visible (self->label_details_license_title, FALSE);
+               gtk_widget_set_visible (self->label_details_license_value, FALSE);
        } else {
-               gtk_label_set_markup (GTK_LABEL (self->label_details_licence_value), tmp);
-               gtk_widget_set_tooltip_text (self->label_details_licence_value, NULL);
-               gtk_widget_set_visible (self->label_details_licence_title, TRUE);
-               gtk_widget_set_visible (self->label_details_licence_value, TRUE);
+               gtk_label_set_markup (GTK_LABEL (self->label_details_license_value), tmp);
+               gtk_widget_set_tooltip_text (self->label_details_license_value, NULL);
+               gtk_widget_set_visible (self->label_details_license_title, TRUE);
+               gtk_widget_set_visible (self->label_details_license_value, TRUE);
        }
 
        /* set version */
@@ -1226,7 +1226,7 @@ gs_shell_details_file_to_app_cb (GObject *source,
        g_signal_connect_object (self->app, "notify::size",
                                 G_CALLBACK (gs_shell_details_notify_state_changed_cb),
                                 self, 0);
-       g_signal_connect_object (self->app, "notify::licence",
+       g_signal_connect_object (self->app, "notify::license",
                                 G_CALLBACK (gs_shell_details_notify_state_changed_cb),
                                 self, 0);
        g_signal_connect_object (self->app, "notify::progress",
@@ -1274,7 +1274,7 @@ static void
 gs_shell_details_load (GsShellDetails *self)
 {
        gs_plugin_loader_app_refine_async (self->plugin_loader, self->app,
-                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE |
+                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE |
                                           GS_PLUGIN_REFINE_FLAGS_REQUIRE_SIZE |
                                           GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING |
                                           GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
@@ -1329,7 +1329,7 @@ gs_shell_details_set_app (GsShellDetails *self, GsApp *app)
        g_signal_connect_object (self->app, "notify::size",
                                 G_CALLBACK (gs_shell_details_notify_state_changed_cb),
                                 self, 0);
-       g_signal_connect_object (self->app, "notify::licence",
+       g_signal_connect_object (self->app, "notify::license",
                                 G_CALLBACK (gs_shell_details_notify_state_changed_cb),
                                 self, 0);
        g_signal_connect_object (self->app, "notify::progress",
@@ -1615,8 +1615,8 @@ gs_shell_details_class_init (GsShellDetailsClass *klass)
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, label_details_category_value);
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, label_details_developer_title);
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, label_details_developer_value);
-       gtk_widget_class_bind_template_child (widget_class, GsShellDetails, label_details_licence_title);
-       gtk_widget_class_bind_template_child (widget_class, GsShellDetails, label_details_licence_value);
+       gtk_widget_class_bind_template_child (widget_class, GsShellDetails, label_details_license_title);
+       gtk_widget_class_bind_template_child (widget_class, GsShellDetails, label_details_license_value);
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, label_details_origin_title);
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, label_details_origin_value);
        gtk_widget_class_bind_template_child (widget_class, GsShellDetails, label_details_size_value);
diff --git a/src/gs-shell-details.ui b/src/gs-shell-details.ui
index c96c75c..3af4a51 100644
--- a/src/gs-shell-details.ui
+++ b/src/gs-shell-details.ui
@@ -947,7 +947,7 @@
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkLabel" id="label_details_licence_title">
+                              <object class="GtkLabel" id="label_details_license_title">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                                 <property name="label" translatable="yes">License</property>
@@ -963,7 +963,7 @@
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkLabel" id="label_details_licence_value">
+                              <object class="GtkLabel" id="label_details_license_value">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                                 <property name="hexpand">True</property>
@@ -1298,7 +1298,7 @@
       <widget name="label_details_updated_title"/>
       <widget name="label_details_category_title"/>
       <widget name="label_details_origin_title"/>
-      <widget name="label_details_licence_title"/>
+      <widget name="label_details_license_title"/>
       <widget name="label_details_size_title"/>
       <widget name="label_details_developer_title"/>
     </widgets>
@@ -1309,7 +1309,7 @@
       <widget name="label_details_version_value"/>
       <widget name="label_details_updated_value"/>
       <widget name="label_details_category_value"/>
-      <widget name="label_details_licence_value"/>
+      <widget name="label_details_license_value"/>
       <widget name="label_details_size_value"/>
       <widget name="label_details_developer_value"/>
     </widgets>
diff --git a/src/gs-shell-extras.c b/src/gs-shell-extras.c
index abcc910..f2f38c9 100644
--- a/src/gs-shell-extras.c
+++ b/src/gs-shell-extras.c
@@ -26,7 +26,6 @@
 #include "gs-app.h"
 #include "gs-app-row.h"
 #include "gs-language.h"
-#include "gs-markdown.h"
 #include "gs-shell.h"
 #include "gs-utils.h"
 #include "gs-vendor.h"
diff --git a/src/gs-shell-installed.c b/src/gs-shell-installed.c
index 813843d..ec21276 100644
--- a/src/gs-shell-installed.c
+++ b/src/gs-shell-installed.c
@@ -237,7 +237,7 @@ gs_shell_installed_load (GsShellInstalled *self)
                                              GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
                                              GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE |
                                              GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION |
-                                             GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE |
+                                             GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE |
                                              GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING,
                                              self->cancellable,
                                              gs_shell_installed_get_installed_cb,
@@ -349,9 +349,10 @@ gs_shell_installed_get_app_sort_key (GsApp *app)
                g_string_append (key, "2:");
 
        /* finally, sort by short name */
-       casefolded_name = g_utf8_casefold (gs_app_get_name (app), -1);
-       g_string_append (key, casefolded_name);
-
+       if (gs_app_get_name (app) != NULL) {
+               casefolded_name = g_utf8_casefold (gs_app_get_name (app), -1);
+               g_string_append (key, casefolded_name);
+       }
        return g_string_free (key, FALSE);
 }
 
diff --git a/src/gs-shell-moderate.c b/src/gs-shell-moderate.c
index 5db01ac..414b704 100644
--- a/src/gs-shell-moderate.c
+++ b/src/gs-shell-moderate.c
@@ -190,7 +190,7 @@ gs_shell_moderate_load (GsShellModerate *self)
                                                    GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
                                                    GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE |
                                                    GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION |
-                                                   GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE |
+                                                   GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE |
                                                    GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEWS,
                                                    self->cancellable,
                                                    gs_shell_moderate_get_unvoted_reviews_cb,
diff --git a/src/gs-shell-search.c b/src/gs-shell-search.c
index 129fe9a..c6ab940 100644
--- a/src/gs-shell-search.c
+++ b/src/gs-shell-search.c
@@ -166,7 +166,7 @@ gs_shell_search_load (GsShellSearch *self)
                                       GS_PLUGIN_REFINE_FLAGS_REQUIRE_HISTORY |
                                       GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION |
                                       GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION |
-                                      GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE |
+                                      GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE |
                                       GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING,
                                       self->search_cancellable,
                                       gs_shell_search_get_search_cb,
diff --git a/src/gs-shell-updates.c b/src/gs-shell-updates.c
index 1ab9ff0..158c2c0 100644
--- a/src/gs-shell-updates.c
+++ b/src/gs-shell-updates.c
@@ -29,7 +29,6 @@
 #include "gs-utils.h"
 #include "gs-app.h"
 #include "gs-app-row.h"
-#include "gs-markdown.h"
 #include "gs-update-dialog.h"
 #include "gs-update-list.h"
 #include "gs-update-monitor.h"
@@ -59,6 +58,7 @@ struct _GsShellUpdates
        GtkBuilder              *builder;
        GCancellable            *cancellable;
        GCancellable            *cancellable_refresh;
+       GCancellable            *cancellable_upgrade_download;
        GSettings               *settings;
        GSettings               *desktop_settings;
        gboolean                 cache_valid;
@@ -737,7 +737,8 @@ gs_shell_updates_get_new_updates (GsShellUpdates *self)
 
        gs_plugin_loader_refresh_async (self->plugin_loader,
                                        10 * 60,
-                                       GS_PLUGIN_REFRESH_FLAGS_UPDATES,
+                                       GS_PLUGIN_REFRESH_FLAGS_METADATA |
+                                       GS_PLUGIN_REFRESH_FLAGS_PAYLOAD,
                                        self->cancellable_refresh,
                                        (GAsyncReadyCallback) gs_shell_updates_refresh_cb,
                                        self);
@@ -932,7 +933,7 @@ gs_shell_updates_reboot_failed_cb (GObject *source, GAsyncResult *res, gpointer
        apps = gs_update_list_get_apps (GS_UPDATE_LIST (self->list_box_updates));
        gs_plugin_loader_app_action_async (self->plugin_loader,
                                           GS_APP (apps->data),
-                                          GS_PLUGIN_LOADER_ACTION_UPDATE_CANCEL,
+                                          GS_PLUGIN_LOADER_ACTION_OFFLINE_UPDATE_CANCEL,
                                           self->cancellable,
                                           cancel_trigger_failed_cb,
                                           self);
@@ -1022,7 +1023,7 @@ upgrade_download_finished_cb (GObject *source,
 }
 
 static void
-gs_shell_updates_download_upgrade_cb (GsUpgradeBanner *upgrade_banner,
+gs_shell_updates_upgrade_download_cb (GsUpgradeBanner *upgrade_banner,
                                       GsShellUpdates *self)
 {
        GsApp *app;
@@ -1033,10 +1034,13 @@ gs_shell_updates_download_upgrade_cb (GsUpgradeBanner *upgrade_banner,
                return;
        }
 
+       if (self->cancellable_upgrade_download != NULL)
+               g_object_unref (self->cancellable_upgrade_download);
+       self->cancellable_upgrade_download = g_cancellable_new ();
        gs_plugin_loader_app_action_async (self->plugin_loader,
                                           app,
                                           GS_PLUGIN_LOADER_ACTION_UPGRADE_DOWNLOAD,
-                                          self->cancellable,
+                                          self->cancellable_upgrade_download,
                                           upgrade_download_finished_cb,
                                           self);
 }
@@ -1065,7 +1069,7 @@ upgrade_reboot_failed_cb (GObject *source,
        apps = gs_update_list_get_apps (GS_UPDATE_LIST (self->list_box_updates));
        gs_plugin_loader_app_action_async (self->plugin_loader,
                                           GS_APP (apps->data),
-                                          GS_PLUGIN_LOADER_ACTION_UPDATE_CANCEL,
+                                          GS_PLUGIN_LOADER_ACTION_OFFLINE_UPDATE_CANCEL,
                                           self->cancellable,
                                           cancel_trigger_failed_cb,
                                           self);
@@ -1100,7 +1104,7 @@ upgrade_trigger_finished_cb (GObject *source,
 }
 
 static void
-gs_shell_updates_install_upgrade_cb (GsUpgradeBanner *upgrade_banner,
+gs_shell_updates_upgrade_install_cb (GsUpgradeBanner *upgrade_banner,
                                      GsShellUpdates *self)
 {
        GsApp *app;
@@ -1119,6 +1123,26 @@ gs_shell_updates_install_upgrade_cb (GsUpgradeBanner *upgrade_banner,
                                           self);
 }
 
+static void
+gs_shell_updates_upgrade_help_cb (GsUpgradeBanner *upgrade_banner,
+                                 GsShellUpdates *self)
+{
+       GsApp *app;
+       const gchar *uri;
+       g_autoptr(GError) error = NULL;
+
+       app = gs_upgrade_banner_get_app (upgrade_banner);
+       if (app == NULL) {
+               g_warning ("no upgrade available to launch");
+               return;
+       }
+
+       /* open the link */
+       uri = gs_app_get_url (app, AS_URL_KIND_HOMEPAGE);
+       if (!gtk_show_uri (NULL, uri, GDK_CURRENT_TIME, &error))
+               g_warning ("failed to open %s: %s", uri, error->message);
+}
+
 /**
  * gs_shell_updates_status_changed_cb:
  **/
@@ -1158,6 +1182,13 @@ gs_shell_updates_monitor_permission (GsShellUpdates *self)
                                  G_CALLBACK (on_permission_changed), self);
 }
 
+static void
+gs_shell_updates_upgrade_cancel_cb (GsUpgradeBanner *upgrade_banner,
+                                   GsShellUpdates *self)
+{
+       g_cancellable_cancel (self->cancellable_upgrade_download);
+}
+
 void
 gs_shell_updates_setup (GsShellUpdates *self,
                        GsShell *shell,
@@ -1188,10 +1219,14 @@ gs_shell_updates_setup (GsShellUpdates *self,
                          G_CALLBACK (gs_shell_updates_button_clicked_cb), self);
 
        /* setup system upgrades */
-       g_signal_connect (self->upgrade_banner, "download-button-clicked",
-                         G_CALLBACK (gs_shell_updates_download_upgrade_cb), self);
-       g_signal_connect (self->upgrade_banner, "install-button-clicked",
-                         G_CALLBACK (gs_shell_updates_install_upgrade_cb), self);
+       g_signal_connect (self->upgrade_banner, "download-clicked",
+                         G_CALLBACK (gs_shell_updates_upgrade_download_cb), self);
+       g_signal_connect (self->upgrade_banner, "install-clicked",
+                         G_CALLBACK (gs_shell_updates_upgrade_install_cb), self);
+       g_signal_connect (self->upgrade_banner, "cancel-clicked",
+                         G_CALLBACK (gs_shell_updates_upgrade_cancel_cb), self);
+       g_signal_connect (self->upgrade_banner, "help-clicked",
+                         G_CALLBACK (gs_shell_updates_upgrade_help_cb), self);
 
        self->header_end_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
        gtk_widget_set_visible (self->header_end_box, TRUE);
diff --git a/src/gs-shell.c b/src/gs-shell.c
index 9e955d0..ab09c4a 100644
--- a/src/gs-shell.c
+++ b/src/gs-shell.c
@@ -867,6 +867,7 @@ gs_shell_show_sources (GsShell *shell)
        GsShellPrivate *priv = gs_shell_get_instance_private (shell);
        GtkWidget *dialog;
 
+       /* use if available */
        if (g_spawn_command_line_async ("software-properties-gtk", NULL))
                return;
 
diff --git a/src/gs-update-dialog.c b/src/gs-update-dialog.c
index 9f8e449..45bae7d 100644
--- a/src/gs-update-dialog.c
+++ b/src/gs-update-dialog.c
@@ -26,7 +26,6 @@
 
 #include "gs-update-dialog.h"
 #include "gs-app-row.h"
-#include "gs-markdown.h"
 #include "gs-update-list.h"
 #include "gs-utils.h"
 
@@ -92,7 +91,7 @@ set_updates_description_ui (GsUpdateDialog *dialog, GsApp *app)
 {
        AsAppKind kind;
        const GdkPixbuf *pixbuf;
-       const gchar *update_desc;
+       const gchar *update_details;
 
        /* set window title */
        kind = gs_app_get_kind (app);
@@ -113,21 +112,15 @@ set_updates_description_ui (GsUpdateDialog *dialog, GsApp *app)
                                      gs_app_get_update_version (app));
        }
 
-       /* this is set unconditionally just in case the output of the
-        * markdown->PangoMarkup parser is invalid */
-       gtk_label_set_markup (GTK_LABEL (dialog->label_details),
-                             /* TRANSLATORS: this is where the
-                              * packager did not write a
-                              * description for the update */
-                             _("No update description available."));
-
-       /* get the update description */
-       update_desc = gs_app_get_update_details (app);
-
        /* set update header */
        gtk_widget_set_visible (dialog->box_header, kind == AS_APP_KIND_DESKTOP);
-       if (update_desc != NULL)
-               gtk_label_set_markup (GTK_LABEL (dialog->label_details), update_desc);
+       update_details = gs_app_get_update_details (app);
+       if (update_details == NULL) {
+               /* TRANSLATORS: this is where the packager did not write
+                * a description for the update */
+               update_details = _("No update description available.");
+       }
+       gtk_label_set_markup (GTK_LABEL (dialog->label_details), update_details);
        gtk_label_set_label (GTK_LABEL (dialog->label_name), gs_app_get_name (app));
        gtk_label_set_label (GTK_LABEL (dialog->label_summary), gs_app_get_summary (app));
 
diff --git a/src/gs-update-monitor.c b/src/gs-update-monitor.c
index 1930326..d67b7f0 100644
--- a/src/gs-update-monitor.c
+++ b/src/gs-update-monitor.c
@@ -338,7 +338,8 @@ check_updates (GsUpdateMonitor *monitor)
        g_debug ("Refreshing cache");
        gs_plugin_loader_refresh_async (monitor->plugin_loader,
                                        60 * 60 * 24,
-                                       GS_PLUGIN_REFRESH_FLAGS_UPDATES,
+                                       GS_PLUGIN_REFRESH_FLAGS_METADATA |
+                                       GS_PLUGIN_REFRESH_FLAGS_PAYLOAD,
                                        monitor->cancellable,
                                        refresh_cache_finished_cb,
                                        monitor);
@@ -761,8 +762,10 @@ GPermission *
 gs_update_monitor_permission_get (void)
 {
        static GPermission *permission = NULL;
+#ifdef HAVE_PACKAGEKIT
        if (permission == NULL)
                permission = gs_utils_get_permission ("org.freedesktop.packagekit.trigger-offline-update");
+#endif
        return permission;
 }
 
diff --git a/src/gs-upgrade-banner.c b/src/gs-upgrade-banner.c
index 45a18db..86f5c07 100644
--- a/src/gs-upgrade-banner.c
+++ b/src/gs-upgrade-banner.c
@@ -21,21 +21,23 @@
 
 #include "config.h"
 
-#include "gs-upgrade-banner.h"
-
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 #include <stdlib.h>
 
+#include "gs-upgrade-banner.h"
+
 typedef struct
 {
        GsApp           *app;
 
        GtkWidget       *button_upgrades_download;
        GtkWidget       *button_upgrades_install;
-       GtkWidget       *button_upgrades_learn_more;
+       GtkWidget       *button_upgrades_help;
+       GtkWidget       *button_upgrades_cancel;
        GtkWidget       *label_upgrades_summary;
        GtkWidget       *label_upgrades_title;
+       GtkWidget       *label_upgrades_warning;
        GtkWidget       *progressbar;
 } GsUpgradeBannerPrivate;
 
@@ -44,7 +46,8 @@ G_DEFINE_TYPE_WITH_PRIVATE (GsUpgradeBanner, gs_upgrade_banner, GTK_TYPE_BIN)
 enum {
        SIGNAL_DOWNLOAD_BUTTON_CLICKED,
        SIGNAL_INSTALL_BUTTON_CLICKED,
-       SIGNAL_LEARN_MORE_BUTTON_CLICKED,
+       SIGNAL_HELP_BUTTON_CLICKED,
+       SIGNAL_CANCEL_BUTTON_CLICKED,
        SIGNAL_LAST
 };
 
@@ -54,10 +57,18 @@ static void
 gs_upgrade_banner_refresh (GsUpgradeBanner *self)
 {
        GsUpgradeBannerPrivate *priv = gs_upgrade_banner_get_instance_private (self);
+       const gchar *uri;
+       g_autofree gchar *name_bold = NULL;
+       g_autofree gchar *version_bold = NULL;
+       g_autofree gchar *str = NULL;
 
        if (priv->app == NULL)
                return;
 
+       /* embolden */
+       name_bold = g_strdup_printf ("<b>%s</b>", gs_app_get_name (priv->app));
+       version_bold = g_strdup_printf ("<b>%s</b>", gs_app_get_version (priv->app));
+
        /* Refresh the title. Normally a distro upgrade state goes from
         *
         * AVAILABLE (available to download) to
@@ -66,45 +77,36 @@ gs_upgrade_banner_refresh (GsUpgradeBanner *self)
         */
        switch (gs_app_get_state (priv->app)) {
        case AS_APP_STATE_AVAILABLE:
-       {
-               g_autofree gchar *str = NULL;
-
                /* TRANSLATORS: This is the text displayed when a distro
                 * upgrade is available. First %s is the distro name and the
                 * 2nd %s is the version, e.g. "Fedora 23 Now Available" */
                str = g_strdup_printf (_("%s %s Now Available"),
-                                      gs_app_get_name (priv->app),
-                                      gs_app_get_version (priv->app));
-               gtk_label_set_text (GTK_LABEL (priv->label_upgrades_title), str);
+                                      name_bold, version_bold);
+               gtk_label_set_markup (GTK_LABEL (priv->label_upgrades_title), str);
+               gtk_widget_set_visible (priv->label_upgrades_warning, FALSE);
+               gtk_widget_set_visible (priv->button_upgrades_cancel, FALSE);
                break;
-       }
        case AS_APP_STATE_INSTALLING:
-       {
-               g_autofree gchar *str = NULL;
-
                /* TRANSLATORS: This is the text displayed while downloading a
                 * distro upgrade. First %s is the distro name and the 2nd %s
                 * is the version, e.g. "Downloading Fedora 23" */
                str = g_strdup_printf (_("Downloading %s %s"),
-                                      gs_app_get_name (priv->app),
-                                      gs_app_get_version (priv->app));
-               gtk_label_set_text (GTK_LABEL (priv->label_upgrades_title), str);
+                                      name_bold, version_bold);
+               gtk_label_set_markup (GTK_LABEL (priv->label_upgrades_title), str);
+               gtk_widget_set_visible (priv->label_upgrades_warning, FALSE);
+               gtk_widget_set_visible (priv->button_upgrades_cancel, TRUE);
                break;
-       }
        case AS_APP_STATE_UPDATABLE:
-       {
-               g_autofree gchar *str = NULL;
-
                /* TRANSLATORS: This is the text displayed when a distro
                 * upgrade has been downloaded and is ready to be installed.
                 * First %s is the distro name and the 2nd %s is the version,
                 * e.g. "Fedora 23 Ready to be Installed" */
                str = g_strdup_printf (_("%s %s Ready to be Installed"),
-                                      gs_app_get_name (priv->app),
-                                      gs_app_get_version (priv->app));
-               gtk_label_set_text (GTK_LABEL (priv->label_upgrades_title), str);
+                                      name_bold, version_bold);
+               gtk_label_set_markup (GTK_LABEL (priv->label_upgrades_title), str);
+               gtk_widget_set_visible (priv->label_upgrades_warning, TRUE);
+               gtk_widget_set_visible (priv->button_upgrades_cancel, FALSE);
                break;
-       }
        default:
                g_critical ("Unexpected app state");
                break;
@@ -118,17 +120,14 @@ gs_upgrade_banner_refresh (GsUpgradeBanner *self)
        /* Show the right buttons for the current state */
        switch (gs_app_get_state (priv->app)) {
        case AS_APP_STATE_AVAILABLE:
-               gtk_widget_show (priv->button_upgrades_learn_more);
                gtk_widget_show (priv->button_upgrades_download);
                gtk_widget_hide (priv->button_upgrades_install);
                break;
        case AS_APP_STATE_INSTALLING:
-               gtk_widget_show (priv->button_upgrades_learn_more);
                gtk_widget_hide (priv->button_upgrades_download);
                gtk_widget_hide (priv->button_upgrades_install);
                break;
        case AS_APP_STATE_UPDATABLE:
-               gtk_widget_show (priv->button_upgrades_learn_more);
                gtk_widget_hide (priv->button_upgrades_download);
                gtk_widget_show (priv->button_upgrades_install);
                break;
@@ -137,11 +136,15 @@ gs_upgrade_banner_refresh (GsUpgradeBanner *self)
                break;
        }
 
+       /* only show help when we have a URL */
+       uri = gs_app_get_url (priv->app, AS_URL_KIND_HOMEPAGE);
+       gtk_widget_set_visible (priv->button_upgrades_help, uri != NULL);
+
        /* do a fill bar for the current progress */
        switch (gs_app_get_state (priv->app)) {
        case AS_APP_STATE_INSTALLING:
                gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progressbar),
-                                              gs_app_get_progress (priv->app));
+                                              (gdouble) gs_app_get_progress (priv->app) / 100.0f);
                gtk_widget_show (priv->progressbar);
                break;
        default:
@@ -188,7 +191,13 @@ install_button_cb (GtkWidget *widget, GsUpgradeBanner *self)
 static void
 learn_more_button_cb (GtkWidget *widget, GsUpgradeBanner *self)
 {
-       g_signal_emit (self, signals[SIGNAL_LEARN_MORE_BUTTON_CLICKED], 0);
+       g_signal_emit (self, signals[SIGNAL_HELP_BUTTON_CLICKED], 0);
+}
+
+static void
+cancel_button_cb (GtkWidget *widget, GsUpgradeBanner *self)
+{
+       g_signal_emit (self, signals[SIGNAL_CANCEL_BUTTON_CLICKED], 0);
 }
 
 void
@@ -255,9 +264,12 @@ gs_upgrade_banner_init (GsUpgradeBanner *self)
        g_signal_connect (priv->button_upgrades_install, "clicked",
                          G_CALLBACK (install_button_cb),
                          self);
-       g_signal_connect (priv->button_upgrades_learn_more, "clicked",
+       g_signal_connect (priv->button_upgrades_help, "clicked",
                          G_CALLBACK (learn_more_button_cb),
                          self);
+       g_signal_connect (priv->button_upgrades_cancel, "clicked",
+                         G_CALLBACK (cancel_button_cb),
+                         self);
 }
 
 static void
@@ -269,23 +281,30 @@ gs_upgrade_banner_class_init (GsUpgradeBannerClass *klass)
        widget_class->destroy = gs_upgrade_banner_destroy;
 
        signals [SIGNAL_DOWNLOAD_BUTTON_CLICKED] =
-               g_signal_new ("download-button-clicked",
+               g_signal_new ("download-clicked",
                              G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (GsUpgradeBannerClass, download_button_clicked),
+                             G_STRUCT_OFFSET (GsUpgradeBannerClass, download_clicked),
                              NULL, NULL, g_cclosure_marshal_VOID__VOID,
                              G_TYPE_NONE, 0);
 
        signals [SIGNAL_INSTALL_BUTTON_CLICKED] =
-               g_signal_new ("install-button-clicked",
+               g_signal_new ("install-clicked",
+                             G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GsUpgradeBannerClass, install_clicked),
+                             NULL, NULL, g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+
+       signals [SIGNAL_CANCEL_BUTTON_CLICKED] =
+               g_signal_new ("cancel-clicked",
                              G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (GsUpgradeBannerClass, install_button_clicked),
+                             G_STRUCT_OFFSET (GsUpgradeBannerClass, cancel_clicked),
                              NULL, NULL, g_cclosure_marshal_VOID__VOID,
                              G_TYPE_NONE, 0);
 
-       signals [SIGNAL_LEARN_MORE_BUTTON_CLICKED] =
-               g_signal_new ("learn-more-button-clicked",
+       signals [SIGNAL_HELP_BUTTON_CLICKED] =
+               g_signal_new ("help-clicked",
                              G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (GsUpgradeBannerClass, learn_more_button_clicked),
+                             G_STRUCT_OFFSET (GsUpgradeBannerClass, help_clicked),
                              NULL, NULL, g_cclosure_marshal_VOID__VOID,
                              G_TYPE_NONE, 0);
 
@@ -293,10 +312,12 @@ gs_upgrade_banner_class_init (GsUpgradeBannerClass *klass)
 
        gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, 
button_upgrades_download);
        gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, button_upgrades_install);
-       gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, 
button_upgrades_learn_more);
+       gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, button_upgrades_cancel);
+       gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, button_upgrades_help);
        gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, label_upgrades_summary);
        gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, label_upgrades_title);
        gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, progressbar);
+       gtk_widget_class_bind_template_child_private (widget_class, GsUpgradeBanner, label_upgrades_warning);
 }
 
 GtkWidget *
diff --git a/src/gs-upgrade-banner.h b/src/gs-upgrade-banner.h
index 8e01884..afd727d 100644
--- a/src/gs-upgrade-banner.h
+++ b/src/gs-upgrade-banner.h
@@ -36,9 +36,10 @@ struct _GsUpgradeBannerClass
 {
        GtkBinClass      parent_class;
 
-       void            (*download_button_clicked)      (GsUpgradeBanner        *self);
-       void            (*install_button_clicked)       (GsUpgradeBanner        *self);
-       void            (*learn_more_button_clicked)    (GsUpgradeBanner        *self);
+       void            (*download_clicked)     (GsUpgradeBanner        *self);
+       void            (*install_clicked)      (GsUpgradeBanner        *self);
+       void            (*cancel_clicked)       (GsUpgradeBanner        *self);
+       void            (*help_clicked)         (GsUpgradeBanner        *self);
 };
 
 GtkWidget      *gs_upgrade_banner_new                  (void);
diff --git a/src/gs-upgrade-banner.ui b/src/gs-upgrade-banner.ui
index 0ee10db..4159e49 100644
--- a/src/gs-upgrade-banner.ui
+++ b/src/gs-upgrade-banner.ui
@@ -60,7 +60,7 @@
             <property name="margin_top">16</property>
             <property name="margin_bottom">28</property>
             <child>
-              <object class="GtkButton" id="button_upgrades_learn_more">
+              <object class="GtkButton" id="button_upgrades_help">
                 <property name="label" translatable="yes">_Learn More</property>
                 <property name="width_request">150</property>
                 <property name="visible">True</property>
@@ -96,6 +96,24 @@
               </packing>
             </child>
             <child>
+              <object class="GtkButton" id="button_upgrades_cancel">
+                <property name="label" translatable="yes">_Cancel</property>
+                <property name="width_request">150</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+                <property name="relief">none</property>
+                <style>
+                  <class name="upgrade-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+              </packing>
+            </child>
+            <child>
               <object class="GtkButton" id="button_upgrades_install">
                 <property name="label" translatable="yes">_Install</property>
                 <property name="width_request">150</property>
diff --git a/src/gs-utils.c b/src/gs-utils.c
index b7a6b99..25a6f3f 100644
--- a/src/gs-utils.c
+++ b/src/gs-utils.c
@@ -163,42 +163,72 @@ gs_app_notify_failed_modal (GsApp *app,
 {
        GtkWidget *dialog;
        const gchar *title;
-       g_autofree gchar *msg = NULL;
+       gboolean show_detailed_error = TRUE;
+       g_autoptr(GString) msg = NULL;
 
+       /* TRANSLATORS: install or removed failed */
        title = _("Sorry, this did not work");
+
+       /* say what we tried to do */
+       msg = g_string_new ("");
        switch (action) {
        case GS_PLUGIN_LOADER_ACTION_INSTALL:
                /* TRANSLATORS: this is when the install fails */
-               msg = g_strdup_printf (_("Installation of %s failed."),
-                                      gs_app_get_name (app));
+               g_string_append_printf (msg, _("Installation of %s failed."),
+                                       gs_app_get_name (app));
                break;
        case GS_PLUGIN_LOADER_ACTION_REMOVE:
                /* TRANSLATORS: this is when the remove fails */
-               msg = g_strdup_printf (_("Removal of %s failed."),
-                                      gs_app_get_name (app));
+               g_string_append_printf (msg, _("Removal of %s failed."),
+                                       gs_app_get_name (app));
                break;
        default:
                g_assert_not_reached ();
                break;
        }
+       g_string_append (msg, " ");
+
        dialog = gtk_message_dialog_new (parent_window,
                                         GTK_DIALOG_MODAL |
+                                        GTK_DIALOG_USE_HEADER_BAR |
                                         GTK_DIALOG_DESTROY_WITH_PARENT,
                                         GTK_MESSAGE_ERROR,
                                         GTK_BUTTONS_CLOSE,
                                         "%s", title);
        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                                                 "%s", msg);
+                                                 "%s", msg->str);
+
+       /* detailed error in an expander */
+       if (show_detailed_error) {
+               GtkWidget *vbox;
+               GtkWidget *expander;
+               GtkWidget *scrolled_window;
+               GtkWidget *label;
+
+               vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+               /* TRANSLATORS: this is an expander title */
+               expander = gtk_expander_new (_("Show Details"));
+               gtk_widget_set_margin_start (expander, 36);
+               gtk_widget_set_margin_end (expander, 36);
+               scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+               gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
+               label = gtk_label_new (error->message);
+               gtk_container_add (GTK_CONTAINER (scrolled_window), label);
+               gtk_box_pack_end (GTK_BOX (vbox), expander, FALSE, TRUE, 4);
+               gtk_widget_show_all (expander);
+
+       }
+
        g_signal_connect (dialog, "response",
                          G_CALLBACK (gtk_widget_destroy), NULL);
        gtk_window_present (GTK_WINDOW (dialog));
 }
 
 typedef enum {
-       GS_APP_LICENCE_FREE             = 0,
-       GS_APP_LICENCE_NONFREE          = 1,
-       GS_APP_LICENCE_PATENT_CONCERN   = 2
-} GsAppLicenceHint;
+       GS_APP_LICENSE_FREE             = 0,
+       GS_APP_LICENSE_NONFREE          = 1,
+       GS_APP_LICENSE_PATENT_CONCERN   = 2
+} GsAppLicenseHint;
 
 /**
  * gs_app_notify_unavailable:
@@ -206,19 +236,19 @@ typedef enum {
 GtkResponseType
 gs_app_notify_unavailable (GsApp *app, GtkWindow *parent)
 {
-       GsAppLicenceHint hint = GS_APP_LICENCE_FREE;
+       GsAppLicenseHint hint = GS_APP_LICENSE_FREE;
        GtkResponseType response;
        GtkWidget *dialog;
-       const gchar *licence;
+       const gchar *license;
        gboolean already_enabled = FALSE;       /* FIXME */
        guint i;
        struct {
                const gchar     *str;
-               GsAppLicenceHint hint;
+               GsAppLicenseHint hint;
        } keywords[] = {
-               { "NonFree",            GS_APP_LICENCE_NONFREE },
-               { "PatentConcern",      GS_APP_LICENCE_PATENT_CONCERN },
-               { "Proprietary",        GS_APP_LICENCE_NONFREE },
+               { "NonFree",            GS_APP_LICENSE_NONFREE },
+               { "PatentConcern",      GS_APP_LICENSE_PATENT_CONCERN },
+               { "Proprietary",        GS_APP_LICENSE_NONFREE },
                { NULL, 0 }
        };
        g_autofree gchar *origin_url = NULL;
@@ -227,15 +257,15 @@ gs_app_notify_unavailable (GsApp *app, GtkWindow *parent)
        g_autoptr(GString) title = NULL;
 
        /* this is very crude */
-       licence = gs_app_get_license (app);
-       if (licence != NULL) {
+       license = gs_app_get_license (app);
+       if (license != NULL) {
                for (i = 0; keywords[i].str != NULL; i++) {
-                       if (g_strstr_len (licence, -1, keywords[i].str) != NULL)
+                       if (g_strstr_len (license, -1, keywords[i].str) != NULL)
                                hint |= keywords[i].hint;
                }
        } else {
                /* use the worst-case assumption */
-               hint = GS_APP_LICENCE_NONFREE | GS_APP_LICENCE_PATENT_CONCERN;
+               hint = GS_APP_LICENSE_NONFREE | GS_APP_LICENSE_PATENT_CONCERN;
        }
 
        /* check if the user has already dismissed */
@@ -263,7 +293,7 @@ gs_app_notify_unavailable (GsApp *app, GtkWindow *parent)
        /* FIXME: get the URL somehow... */
        origin_url = g_strdup_printf ("<a href=\"\">%s</a>", gs_app_get_origin (app));
        body = g_string_new ("");
-       if (hint & GS_APP_LICENCE_NONFREE) {
+       if (hint & GS_APP_LICENSE_NONFREE) {
                g_string_append_printf (body,
                                        /* TRANSLATORS: the replacements are as follows:
                                         * 1. Application name, e.g. "Firefox"
@@ -294,7 +324,7 @@ gs_app_notify_unavailable (GsApp *app, GtkWindow *parent)
        }
 
        /* be aware of patent clauses */
-       if (hint & GS_APP_LICENCE_PATENT_CONCERN) {
+       if (hint & GS_APP_LICENSE_PATENT_CONCERN) {
                g_string_append (body, "\n\n");
                if (gs_app_get_kind (app) != AS_APP_KIND_CODEC) {
                        g_string_append_printf (body,
diff --git a/src/gs-utils.h b/src/gs-utils.h
index a9d4cb4..7016785 100644
--- a/src/gs-utils.h
+++ b/src/gs-utils.h
@@ -65,6 +65,9 @@ gchar         *gs_utils_get_cachedir          (const gchar    *kind,
                                                 GError         **error);
 gchar          *gs_utils_get_user_hash         (GError         **error);
 GPermission    *gs_utils_get_permission        (const gchar    *id);
+gboolean        gs_utils_is_current_desktop    (const gchar    *name);
+
+gboolean        gs_utils_is_current_desktop    (const gchar    *name);
 
 gboolean        gs_utils_is_current_desktop    (const gchar    *name);
 
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 00b892f..f777b04 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -26,9 +26,6 @@ AM_CPPFLAGS =                                         \
        -DTESTDATADIR=\""$(top_srcdir)/data/tests"\"    \
        -I$(top_srcdir)/src
 
-noinst_LTLIBRARIES =                                   \
-       libgs_plugin_self_test.la
-
 plugindir = $(libdir)/gs-plugins-${GS_PLUGIN_API_VERSION}
 plugin_LTLIBRARIES =                                   \
        libgs_plugin_appstream.la                       \
@@ -77,7 +74,7 @@ plugin_LTLIBRARIES += libgs_plugin_limba.la
 endif
 
 if HAVE_ODRS
-plugin_LTLIBRARIES += libgs_plugin_xdg_app_reviews.la
+plugin_LTLIBRARIES += libgs_plugin_odrs.la
 endif
 
 libgs_plugin_dummy_la_SOURCES = gs-plugin-dummy.c
@@ -115,11 +112,6 @@ libgs_plugin_icons_la_LIBADD = $(GS_PLUGIN_LIBS) $(SOUP_LIBS)
 libgs_plugin_icons_la_LDFLAGS = -module -avoid-version
 libgs_plugin_icons_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 
-libgs_plugin_self_test_la_SOURCES = gs-plugin-self-test.c
-libgs_plugin_self_test_la_LIBADD = $(GS_PLUGIN_LIBS)
-libgs_plugin_self_test_la_LDFLAGS = -module -avoid-version
-libgs_plugin_self_test_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
-
 libgs_plugin_appstream_la_SOURCES =                    \
        gs-appstream.c                                  \
        gs-appstream.h                                  \
@@ -141,10 +133,10 @@ libgs_plugin_xdg_app_la_LIBADD = $(GS_PLUGIN_LIBS) $(XDG_APP_LIBS)
 libgs_plugin_xdg_app_la_LDFLAGS = -module -avoid-version
 libgs_plugin_xdg_app_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 
-libgs_plugin_xdg_app_reviews_la_SOURCES = gs-plugin-xdg-app-reviews.c
-libgs_plugin_xdg_app_reviews_la_LIBADD = $(GS_PLUGIN_LIBS) $(JSON_GLIB_LIBS)
-libgs_plugin_xdg_app_reviews_la_LDFLAGS = -module -avoid-version
-libgs_plugin_xdg_app_reviews_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
+libgs_plugin_odrs_la_SOURCES = gs-plugin-odrs.c
+libgs_plugin_odrs_la_LIBADD = $(GS_PLUGIN_LIBS) $(JSON_GLIB_LIBS)
+libgs_plugin_odrs_la_LDFLAGS = -module -avoid-version
+libgs_plugin_odrs_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 endif
 
 if HAVE_APT
@@ -230,6 +222,8 @@ libgs_plugin_packagekit_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 
 libgs_plugin_packagekit_refine_la_SOURCES =            \
        gs-plugin-packagekit-refine.c                   \
+       gs-markdown.c                                   \
+       gs-markdown.h                                   \
        packagekit-common.c                             \
        packagekit-common.h
 libgs_plugin_packagekit_refine_la_LIBADD = $(GS_PLUGIN_LIBS) $(PACKAGEKIT_LIBS)
@@ -292,15 +286,16 @@ libgs_plugin_snappy_la_LIBADD =                           \
 libgs_plugin_snappy_la_LDFLAGS = -module -avoid-version
 libgs_plugin_snappy_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 
-check_PROGRAMS =                                       \
+check_PROGRAMS =                                               \
        gs-self-test
 
-gs_self_test_SOURCES =                                 \
-       gs-moduleset.c                                  \
+gs_self_test_SOURCES =                                         \
+       gs-markdown.c                                           \
+       gs-moduleset.c                                          \
        gs-self-test.c
 
-gs_self_test_LDADD =                                   \
-       $(GLIB_LIBS)                                    \
+gs_self_test_LDADD =                                           \
+       $(GLIB_LIBS)                                            \
        $(GTK_LIBS)
 
 gs_self_test_CFLAGS = $(WARN_CFLAGS)
diff --git a/src/plugins/gs-appstream.c b/src/plugins/gs-appstream.c
index f4cf73d..ddc1e7c 100644
--- a/src/plugins/gs-appstream.c
+++ b/src/plugins/gs-appstream.c
@@ -263,6 +263,8 @@ gs_appstream_copy_metadata (GsApp *app, AsApp *item)
        for (l = keys; l != NULL; l = l->next) {
                const gchar *key = l->data;
                const gchar *value = g_hash_table_lookup (hash, key);
+               if (gs_app_get_metadata_item (app, key) != NULL)
+                       continue;
                gs_app_set_metadata (app, key, value);
        }
 }
@@ -319,12 +321,19 @@ gs_refine_item_management_plugin (GsApp *app, AsApp *item)
        const gchar *runtime = NULL;
        guint i;
 
+       /* allow override */
+       management_plugin = as_app_get_metadata_item (item, "GnomeSoftware::Plugin");
+       if (management_plugin != NULL) {
+               gs_app_set_management_plugin (app, management_plugin);
+               return;
+       }
+
        /* find the default bundle kind */
        bundles = as_app_get_bundles (item);
        for (i = 0; i < bundles->len; i++) {
                AsBundle *bundle = g_ptr_array_index (bundles, i);
                if (as_bundle_get_kind (bundle) == AS_BUNDLE_KIND_XDG_APP) {
-                       management_plugin = "XgdApp";
+                       management_plugin = "xdg-app";
                        gs_app_add_source (app, as_bundle_get_id (bundle));
 
                        /* automatically add runtime */
@@ -341,7 +350,7 @@ gs_refine_item_management_plugin (GsApp *app, AsApp *item)
                        break;
                }
                if (as_bundle_get_kind (bundle) == AS_BUNDLE_KIND_LIMBA) {
-                       management_plugin = "Limba";
+                       management_plugin = "limba";
                        gs_app_add_source (app, as_bundle_get_id (bundle));
                        break;
                }
@@ -350,7 +359,7 @@ gs_refine_item_management_plugin (GsApp *app, AsApp *item)
        /* fall back to PackageKit */
        if (management_plugin == NULL &&
            as_app_get_pkgname_default (item) != NULL)
-               management_plugin = "PackageKit";
+               management_plugin = "packagekit";
        if (management_plugin != NULL)
                gs_app_set_management_plugin (app, management_plugin);
 }
@@ -382,7 +391,6 @@ gs_appstream_refine_app (GsPlugin *plugin,
                switch (as_app_get_source_kind (item)) {
                case AS_APP_SOURCE_KIND_APPDATA:
                case AS_APP_SOURCE_KIND_DESKTOP:
-                       gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
                        gs_app_set_state (app, AS_APP_STATE_INSTALLED);
                        break;
                case AS_APP_SOURCE_KIND_METAINFO:
@@ -453,7 +461,7 @@ gs_appstream_refine_app (GsPlugin *plugin,
                }
        }
 
-       /* set licence */
+       /* set license */
        if (as_app_get_project_license (item) != NULL && gs_app_get_license (app) == NULL)
                gs_app_set_license (app,
                                    GS_APP_QUALITY_HIGHEST,
@@ -560,7 +568,6 @@ gs_appstream_refine_app (GsPlugin *plugin,
                        gs_app_add_kudo (app, GS_APP_KUDO_HI_DPI_ICON);
                        break;
                default:
-                       g_debug ("no idea how to handle kudo '%s'", tmp);
                        break;
                }
        }
@@ -572,7 +579,7 @@ gs_appstream_refine_app (GsPlugin *plugin,
                if (tmp != NULL) {
                        g_autofree gchar *desc = NULL;
                        desc = as_markup_convert (tmp,
-                                                 AS_MARKUP_CONVERT_FORMAT_MARKDOWN,
+                                                 AS_MARKUP_CONVERT_FORMAT_SIMPLE,
                                                  error);
                        if (desc == NULL)
                                return FALSE;
diff --git a/src/gs-markdown.c b/src/plugins/gs-markdown.c
similarity index 100%
rename from src/gs-markdown.c
rename to src/plugins/gs-markdown.c
diff --git a/src/gs-markdown.h b/src/plugins/gs-markdown.h
similarity index 100%
rename from src/gs-markdown.h
rename to src/plugins/gs-markdown.h
diff --git a/src/plugins/gs-plugin-appstream.c b/src/plugins/gs-plugin-appstream.c
index 159f0a4..adeb545 100644
--- a/src/plugins/gs-plugin-appstream.c
+++ b/src/plugins/gs-plugin-appstream.c
@@ -43,8 +43,6 @@
 
 struct GsPluginPrivate {
        AsStore                 *store;
-       GMutex                   store_mutex;
-       gboolean                 done_init;
 };
 
 /**
@@ -69,8 +67,6 @@ gs_plugin_appstream_store_changed_cb (AsStore *store, GsPlugin *plugin)
        gs_plugin_updates_changed (plugin);
 }
 
-static gboolean gs_plugin_appstream_startup (GsPlugin *plugin, GError **error);
-
 gboolean
 gs_plugin_refresh (GsPlugin              *plugin,
                   guint                  cache_age,
@@ -79,8 +75,6 @@ gs_plugin_refresh (GsPlugin              *plugin,
                   GError               **error)
 {
        if (flags & GS_PLUGIN_REFRESH_FLAGS_UI) {
-               plugin->priv->done_init = FALSE;
-               gs_plugin_appstream_startup (plugin, NULL);
                gs_plugin_updates_changed (plugin);
        }
 
@@ -94,7 +88,6 @@ void
 gs_plugin_initialize (GsPlugin *plugin)
 {
        plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
-       g_mutex_init (&plugin->priv->store_mutex);
        plugin->priv->store = as_store_new ();
        as_store_set_watch_flags (plugin->priv->store,
                                  AS_STORE_WATCH_FLAG_ADDED |
@@ -121,7 +114,6 @@ void
 gs_plugin_destroy (GsPlugin *plugin)
 {
        g_object_unref (plugin->priv->store);
-       g_mutex_clear (&plugin->priv->store_mutex);
 }
 
 /**
@@ -172,51 +164,52 @@ gs_plugin_appstream_get_origins_hash (GPtrArray *array)
 }
 
 /**
- * gs_plugin_appstream_startup:
- *
- * This must be called with plugin->priv->store_mutex held.
+ * gs_plugin_setup:
  */
-static gboolean
-gs_plugin_appstream_startup (GsPlugin *plugin, GError **error)
+gboolean
+gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
 {
        AsApp *app;
        GPtrArray *items;
        gboolean ret;
        const gchar *origin;
+       const gchar *tmp;
        guint *perc;
        guint i;
        g_autoptr(GHashTable) origins = NULL;
-       g_autoptr(AsProfileTask) ptask = NULL;
-
-       /* already done */
-       if (plugin->priv->done_init)
-               return TRUE;
-
-       ptask = as_profile_start_literal (plugin->profile, "appstream::startup");
 
        /* Parse the XML */
        if (g_getenv ("GNOME_SOFTWARE_PREFER_LOCAL") != NULL) {
                as_store_set_add_flags (plugin->priv->store,
                                        AS_STORE_ADD_FLAG_PREFER_LOCAL);
        }
-       ret = as_store_load (plugin->priv->store,
-                            AS_STORE_LOAD_FLAG_APP_INFO_SYSTEM |
-                            AS_STORE_LOAD_FLAG_APP_INFO_USER |
-                            AS_STORE_LOAD_FLAG_APPDATA |
-                            AS_STORE_LOAD_FLAG_DESKTOP |
-                            AS_STORE_LOAD_FLAG_XDG_APP_USER |
-                            AS_STORE_LOAD_FLAG_APP_INSTALL,
-                            NULL,
-                            error);
-       if (!ret)
-               return FALSE;
+
+       /* only when in self test */
+       tmp = g_getenv ("GS_SELF_TEST_APPSTREAM_XML");
+       if (tmp != NULL) {
+               g_debug ("using self test data of %s", tmp);
+               if (!as_store_from_xml (plugin->priv->store, tmp, NULL, error))
+                       return FALSE;
+       } else {
+               ret = as_store_load (plugin->priv->store,
+                                    AS_STORE_LOAD_FLAG_APP_INFO_SYSTEM |
+                                    AS_STORE_LOAD_FLAG_APP_INFO_USER |
+                                    AS_STORE_LOAD_FLAG_APPDATA |
+                                    AS_STORE_LOAD_FLAG_DESKTOP |
+                                    AS_STORE_LOAD_FLAG_XDG_APP_USER |
+                                    AS_STORE_LOAD_FLAG_APP_INSTALL,
+                                    NULL,
+                                    error);
+               if (!ret)
+                       return FALSE;
+       }
        items = as_store_get_apps (plugin->priv->store);
        if (items->len == 0) {
                g_warning ("No AppStream data, try 'make install-sample-data' in data/");
                g_set_error (error,
                             GS_PLUGIN_LOADER_ERROR,
                             GS_PLUGIN_LOADER_ERROR_FAILED,
-                            _("No AppStream data found"));
+                            "No AppStream data found");
                return FALSE;
        }
 
@@ -261,7 +254,6 @@ gs_plugin_appstream_startup (GsPlugin *plugin, GError **error)
        }
 
        /* rely on the store keeping itself updated */
-       plugin->priv->done_init = TRUE;
        return TRUE;
 }
 
@@ -285,6 +277,14 @@ gs_plugin_refine_from_id (GsPlugin *plugin,
        if (id == NULL)
                return TRUE;
        item = as_store_get_app_by_id (plugin->priv->store, id);
+#if AS_CHECK_VERSION(0,5,12)
+       if (item == NULL &&
+           gs_app_has_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX)) {
+               item = as_store_get_app_by_id_ignore_prefix (plugin->priv->store, id);
+               if (item != NULL)
+                       g_debug ("found %s for wildcard %s", as_app_get_id (item), id);
+       }
+#endif
        if (item == NULL)
                return TRUE;
 
@@ -339,22 +339,13 @@ gs_plugin_add_distro_upgrades (GsPlugin *plugin,
        AsApp *item;
        GPtrArray *array;
        guint i;
-       g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&plugin->priv->store_mutex);
-
-       /* load XML files */
-       if (!gs_plugin_appstream_startup (plugin, error))
-               return FALSE;
 
        /* find any upgrades */
        array = as_store_get_apps (plugin->priv->store);
        for (i = 0; i < array->len; i++) {
                g_autoptr(GsApp) app = NULL;
                item = g_ptr_array_index (array, i);
-
-               // FIXME: AS_APP_KIND_OS_UPGRADE
-               if (as_app_get_kind (item) != AS_APP_KIND_UNKNOWN)
-                       continue;
-               if (as_app_get_metadata_item (item, "X-IsUpgrade") == NULL)
+               if (as_app_get_kind (item) != AS_APP_KIND_OS_UPDATE)
                        continue;
 
                /* create */
@@ -369,34 +360,23 @@ gs_plugin_add_distro_upgrades (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_refine:
+ * gs_plugin_refine_app:
  */
 gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
 {
        gboolean found = FALSE;
-       GList *l;
-       GsApp *app;
-       g_autoptr(AsProfileTask) ptask = NULL;
-       g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&plugin->priv->store_mutex);
 
-       /* load XML files */
-       if (!gs_plugin_appstream_startup (plugin, error))
+       /* find by ID then package name */
+       if (!gs_plugin_refine_from_id (plugin, app, &found, error))
                return FALSE;
-
-       ptask = as_profile_start_literal (plugin->profile, "appstream::refine");
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               if (!gs_plugin_refine_from_id (plugin, app, &found, error))
+       if (!found) {
+               if (!gs_plugin_refine_from_pkgname (plugin, app, error))
                        return FALSE;
-               if (!found) {
-                       if (!gs_plugin_refine_from_pkgname (plugin, app, error))
-                               return FALSE;
-               }
        }
 
        /* sucess */
@@ -420,11 +400,6 @@ gs_plugin_add_category_apps (GsPlugin *plugin,
        GPtrArray *array;
        guint i;
        g_autoptr(AsProfileTask) ptask = NULL;
-       g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&plugin->priv->store_mutex);
-
-       /* load XML files */
-       if (!gs_plugin_appstream_startup (plugin, error))
-               return FALSE;
 
        /* get the two search terms */
        ptask = as_profile_start_literal (plugin->profile, "appstream::add-category-apps");
@@ -514,11 +489,6 @@ gs_plugin_add_search (GsPlugin *plugin,
        gboolean ret = TRUE;
        guint i;
        g_autoptr(AsProfileTask) ptask = NULL;
-       g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&plugin->priv->store_mutex);
-
-       /* load XML files */
-       if (!gs_plugin_appstream_startup (plugin, error))
-               return FALSE;
 
        /* search categories for the search term */
        ptask = as_profile_start_literal (plugin->profile, "appstream::search");
@@ -548,11 +518,6 @@ gs_plugin_add_installed (GsPlugin *plugin,
        GPtrArray *array;
        guint i;
        g_autoptr(AsProfileTask) ptask = NULL;
-       g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&plugin->priv->store_mutex);
-
-       /* load XML files */
-       if (!gs_plugin_appstream_startup (plugin, error))
-               return FALSE;
 
        /* search categories for the search term */
        ptask = as_profile_start_literal (plugin->profile, "appstream::add_installed");
@@ -629,11 +594,6 @@ gs_plugin_add_categories (GsPlugin *plugin,
        GPtrArray *array;
        guint i;
        g_autoptr(AsProfileTask) ptask = NULL;
-       g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&plugin->priv->store_mutex);
-
-       /* load XML files */
-       if (!gs_plugin_appstream_startup (plugin, error))
-               return FALSE;
 
        /* find out how many packages are in each category */
        ptask = as_profile_start_literal (plugin->profile, "appstream::add-categories");
diff --git a/src/plugins/gs-plugin-apt.cc b/src/plugins/gs-plugin-apt.cc
index a0c547d..ff3578a 100644
--- a/src/plugins/gs-plugin-apt.cc
+++ b/src/plugins/gs-plugin-apt.cc
@@ -646,7 +646,7 @@ gs_plugin_refine (GsPlugin *plugin,
                                gs_app_set_update_version (app, info->update_version);
                        }
                }
-               if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE) != 0 && is_open_source(info)) {
+               if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE) != 0 && is_open_source(info)) {
                        gs_app_set_license (app, GS_APP_QUALITY_LOWEST, "@LicenseRef-free=" LICENSE_URL);
                }
 
@@ -965,7 +965,7 @@ gs_plugin_refresh (GsPlugin *plugin,
                   GCancellable *cancellable,
                   GError **error)
 {
-       if ((flags & GS_PLUGIN_REFRESH_FLAGS_UPDATES) == 0)
+       if ((flags & GS_PLUGIN_REFRESH_FLAGS_METADATA) == 0)
                return TRUE;
 
        if (!aptd_transaction (plugin, "UpdateCache", NULL, NULL, NULL, error))
diff --git a/src/plugins/gs-plugin-dummy.c b/src/plugins/gs-plugin-dummy.c
index 213c17f..e244aea 100644
--- a/src/plugins/gs-plugin-dummy.c
+++ b/src/plugins/gs-plugin-dummy.c
@@ -26,9 +26,6 @@
 /*
  * SECTION:
  * Provides some dummy data that is useful in self test programs.
- *
- * Methods:     | Search, AddUpdates, AddInstalled, AddPopular
- * Refines:     | [id]->[name], [id]->[summary]
  */
 
 /**
@@ -46,12 +43,92 @@ gs_plugin_get_name (void)
 void
 gs_plugin_initialize (GsPlugin *plugin)
 {
-       if (g_getenv ("GNOME_SOFTWARE_SELF_TEST") == NULL) {
+       if (g_getenv ("GS_SELF_TEST_DUMMY_ENABLE") == NULL) {
                g_debug ("disabling '%s' as not in self test", plugin->name);
                gs_plugin_set_enabled (plugin, FALSE);
        }
 }
 
+typedef struct {
+       GsPlugin        *plugin;
+       GsApp           *app;
+       GMainLoop       *loop;
+       GCancellable    *cancellable;
+       GError          **error;
+       guint            percentage;
+} GsPluginDummyHelper;
+
+/**
+ * gs_plugin_dummy_delay_cb:
+ */
+static gboolean
+gs_plugin_dummy_delay_cb (gpointer user_data)
+{
+       GsPluginDummyHelper *helper = (GsPluginDummyHelper *) user_data;
+       helper->percentage += 10;
+       if (helper->percentage >= 100) {
+               g_main_loop_quit (helper->loop);
+               return FALSE;
+       }
+       if (helper->error != NULL && *(helper->error) != NULL) {
+               g_main_loop_quit (helper->loop);
+               return FALSE;
+       }
+       g_debug ("dummy percentage=%i%%", helper->percentage);
+       if (helper->app != NULL) {
+               gs_app_set_progress (helper->app, helper->percentage);
+               gs_plugin_status_update (helper->plugin,
+                                        helper->app,
+                                        GS_PLUGIN_STATUS_DOWNLOADING);
+       }
+       return TRUE;
+}
+
+/**
+ * gs_plugin_dummy_delay_cancel_cb:
+ */
+static void
+gs_plugin_dummy_delay_cancel_cb (GCancellable *cancellable,
+                                GsPluginDummyHelper *helper)
+{
+       g_debug ("dummy delay cancelled");
+       g_cancellable_set_error_if_cancelled (cancellable, helper->error);
+}
+
+/**
+ * gs_plugin_dummy_delay:
+ */
+static gboolean
+gs_plugin_dummy_delay (GsPlugin *plugin,
+                      GsApp *app,
+                      guint timeout_ms,
+                      GCancellable *cancellable,
+                      GError **error)
+{
+       g_autofree GsPluginDummyHelper *helper = g_new0 (GsPluginDummyHelper, 1);
+       g_autoptr(GMainLoop) loop = g_main_loop_new (NULL, FALSE);
+
+       /* cancel the delay on cancellation */
+       if (cancellable != NULL) {
+               g_cancellable_connect (cancellable,
+                                      G_CALLBACK (gs_plugin_dummy_delay_cancel_cb),
+                                      helper, NULL);
+       }
+
+       /* set up callbacks */
+       helper->app = app;
+       helper->cancellable = cancellable;
+       helper->error = error;
+       helper->loop = loop;
+       helper->percentage = 0;
+       helper->plugin = plugin;
+       g_debug ("dummy waiting for %ims", timeout_ms);
+       g_timeout_add (timeout_ms / 10, gs_plugin_dummy_delay_cb, helper);
+       g_main_loop_run (loop);
+       g_debug ("dummy done");
+       return helper->error != NULL;
+}
+
 /**
  * gs_plugin_add_updates:
  */
@@ -62,37 +139,58 @@ gs_plugin_add_updates (GsPlugin *plugin,
                       GError **error)
 {
        GsApp *app;
+       g_autoptr(AsIcon) ic = NULL;
 
        /* update UI as this might take some time */
        gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING);
 
        /* spin */
-       g_usleep (2 * G_USEC_PER_SEC);
+       if (!gs_plugin_dummy_delay (plugin, NULL, 2000, cancellable, error))
+               return FALSE;
 
-       /* add a normal application */
-       app = gs_app_new ("gnome-boxes");
-       gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Boxes");
-       gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Do not segfault when using newer versons of 
libvirt.");
-       gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+       /* use a generic stock icon */
+       ic = as_icon_new ();
+       as_icon_set_kind (ic, AS_ICON_KIND_STOCK);
+       as_icon_set_name (ic, "drive-harddisk");
+
+       /* add a live updatable normal application */
+       app = gs_app_new ("chiron.desktop");
+       gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Chiron");
+       gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "A teaching application");
+       gs_app_set_update_details (app, "Do not crash when using libvirt.");
+       gs_app_set_update_urgency (app, AS_URGENCY_KIND_HIGH);
+       gs_app_set_icon (app, ic);
        gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+       gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE);
+       gs_app_set_management_plugin (app, plugin->name);
        gs_plugin_add_app (list, app);
        g_object_unref (app);
 
-       /* add an OS update */
-       app = gs_app_new ("libvirt-glib-devel;0.0.1;noarch;fedora");
+       /* add a offline OS update */
+       app = gs_app_new (NULL);
        gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "libvirt-glib-devel");
-       gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Fix several memory leaks.");
+       gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Development files for libvirt");
+       gs_app_set_update_details (app, "Fix several memory leaks.");
+       gs_app_set_update_urgency (app, AS_URGENCY_KIND_LOW);
        gs_app_set_kind (app, AS_APP_KIND_GENERIC);
-       gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+       gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
+       gs_app_add_source (app, "libvirt-glib-devel");
+       gs_app_add_source_id (app, "libvirt-glib-devel;0.0.1;noarch;fedora");
+       gs_app_set_management_plugin (app, plugin->name);
        gs_plugin_add_app (list, app);
        g_object_unref (app);
 
-       /* add a second OS update */
-       app = gs_app_new ("gnome-boxes-libs;0.0.1;i386;updates-testing");
-       gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "gnome-boxes-libs");
-       gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Do not segfault when using newer versons of 
libvirt.");
+       /* add a live OS update */
+       app = gs_app_new (NULL);
+       gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "chiron-libs");
+       gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "library for chiron");
+       gs_app_set_update_details (app, "Do not crash when using libvirt.");
+       gs_app_set_update_urgency (app, AS_URGENCY_KIND_HIGH);
        gs_app_set_kind (app, AS_APP_KIND_GENERIC);
-       gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+       gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE);
+       gs_app_add_source (app, "chiron-libs");
+       gs_app_add_source_id (app, "chiron-libs;0.0.1;i386;updates-testing");
+       gs_app_set_management_plugin (app, plugin->name);
        gs_plugin_add_app (list, app);
        g_object_unref (app);
 
@@ -108,119 +206,187 @@ gs_plugin_add_installed (GsPlugin *plugin,
                         GCancellable *cancellable,
                         GError **error)
 {
-       g_autoptr(GsApp) app = gs_app_new ("gnome-power-manager");
-       gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Power Manager");
-       gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Power Management Program");
-       gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
-       gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
-       gs_plugin_add_app (list, app);
-       gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+       const gchar *packages[] = { "zeus", "zeus-common", NULL };
+       const gchar *app_ids[] = { "Uninstall Zeus.desktop", NULL };
+       guint i;
+
+       /* add all packages */
+       for (i = 0; packages[i] != NULL; i++) {
+               g_autoptr(GsApp) app = gs_app_new (NULL);
+               gs_app_add_source (app, packages[i]);
+               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+               gs_app_set_kind (app, AS_APP_KIND_GENERIC);
+               gs_app_set_origin (app, "london-west");
+               gs_app_set_management_plugin (app, plugin->name);
+               gs_plugin_add_app (list, app);
+       }
+
+       /* add all app-ids */
+       for (i = 0; app_ids[i] != NULL; i++) {
+               g_autoptr(GsApp) app = gs_app_new (app_ids[i]);
+               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+               gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+               gs_app_set_management_plugin (app, plugin->name);
+               gs_plugin_add_app (list, app);
+       }
 
        return TRUE;
 }
 
 /**
- * gs_plugin_add_popular:
+ * gs_plugin_app_remove:
  */
 gboolean
-gs_plugin_add_popular (GsPlugin *plugin,
-                      GList **list,
+gs_plugin_app_remove (GsPlugin *plugin,
+                     GsApp *app,
+                     GCancellable *cancellable,
+                     GError **error)
+{
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
+               return TRUE;
+
+       /* remove app */
+       if (g_strcmp0 (gs_app_get_id (app), "chiron.desktop") == 0) {
+               gs_app_set_state (app, AS_APP_STATE_REMOVING);
+               if (!gs_plugin_dummy_delay (plugin, app, 500, cancellable, error)) {
+                       gs_app_set_state_recover (app);
+                       return FALSE;
+               }
+               gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
+       }
+       return TRUE;
+}
+
+/**
+ * gs_plugin_app_install:
+ */
+gboolean
+gs_plugin_app_install (GsPlugin *plugin,
+                      GsApp *app,
                       GCancellable *cancellable,
                       GError **error)
 {
-       g_autoptr(GsApp) app = gs_app_new ("gnome-power-manager");
-       gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Power Manager");
-       gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "Power Management Program");
-       gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
-       gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
-       gs_plugin_add_app (list, app);
-       gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
+               return TRUE;
 
+       /* install app */
+       if (g_strcmp0 (gs_app_get_id (app), "chiron.desktop") == 0) {
+               gs_app_set_state (app, AS_APP_STATE_INSTALLING);
+               if (!gs_plugin_dummy_delay (plugin, app, 500, cancellable, error)) {
+                       gs_app_set_state_recover (app);
+                       return FALSE;
+               }
+               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+       }
        return TRUE;
 }
 
 /**
- * gs_plugin_refine:
+ * gs_plugin_app_update:
  */
 gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
+gs_plugin_app_update (GsPlugin *plugin,
+                     GsApp *app,
+                     GCancellable *cancellable,
+                     GError **error)
 {
-       GsApp *app;
-       GList *l;
-
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               if (gs_app_get_name (app) == NULL) {
-                       if (g_strcmp0 (gs_app_get_id (app), "gnome-boxes") == 0) {
-                               gs_app_set_license (app, GS_APP_QUALITY_NORMAL,
-                                                   "GPL-2.0+");
-                               gs_app_set_name (app, GS_APP_QUALITY_NORMAL,
-                                                "Boxes");
-                               gs_app_set_url (app, AS_URL_KIND_HOMEPAGE,
-                                               "http://www.gimp.org/";);
-                               gs_app_set_summary (app, GS_APP_QUALITY_NORMAL,
-                                                   "A simple GNOME 3 application "
-                                                   "to access remote or virtual systems");
-                               gs_app_set_description (app, GS_APP_QUALITY_NORMAL,
-                                                       "<p>long description!</p>");
-                       }
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
+               return TRUE;
+
+       /* always fail */
+       g_set_error_literal (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_NO_NETWORK,
+                            "no network connection is available");
+       return FALSE;
+}
+
+/**
+ * gs_plugin_refine_app:
+ */
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
+{
+       /* default */
+       if (g_strcmp0 (gs_app_get_id (app), "chiron.desktop") == 0 ||
+           g_strcmp0 (gs_app_get_id (app), "mate-spell.desktop") == 0 ||
+           g_strcmp0 (gs_app_get_id (app), "zeus.desktop") == 0) {
+               if (gs_app_get_state (app) == AS_APP_STATE_UNKNOWN)
+                       gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+       }
+
+       /* license */
+       if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE) {
+               if (g_strcmp0 (gs_app_get_id (app), "chiron.desktop") == 0 ||
+                   g_strcmp0 (gs_app_get_id (app), "zeus.desktop") == 0)
+                       gs_app_set_license (app, GS_APP_QUALITY_NORMAL, "GPL-2.0+");
+       }
+
+       /* homepage */
+       if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL) {
+               if (g_strcmp0 (gs_app_get_id (app), "chiron.desktop") == 0) {
+                       gs_app_set_url (app, AS_URL_KIND_HOMEPAGE,
+                                       "http://www.test.org/";);
+               }
+       }
+
+       /* description */
+       if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION) {
+               if (g_strcmp0 (gs_app_get_id (app), "chiron.desktop") == 0) {
+                       gs_app_set_description (app, GS_APP_QUALITY_NORMAL,
+                                               "<p>long description!</p>");
                }
        }
 
        /* add fake review */
        if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEWS) {
-               for (l = *list; l != NULL; l = l->next) {
-                       g_autoptr(GsReview) review1 = NULL;
-                       g_autoptr(GsReview) review2 = NULL;
-                       g_autoptr(GDateTime) dt = NULL;
-                       app = GS_APP (l->data);
-                       dt = g_date_time_new_now_utc ();
-
-                       /* set first review */
-                       review1 = gs_review_new ();
-                       gs_review_set_rating (review1, 50);
-                       gs_review_set_reviewer (review1, "Angela Avery");
-                       gs_review_set_summary (review1, "Steep learning curve, but worth it");
-                       gs_review_set_text (review1, "Best overall 3D application I've ever used overall 3D 
application I've ever used. Best overall 3D application I've ever used overall 3D application I've ever used. 
Best overall 3D application I've ever used overall 3D application I've ever used. Best overall 3D application 
I've ever used overall 3D application I've ever used.");
-                       gs_review_set_version (review1, "3.16.4");
-                       gs_review_set_date (review1, dt);
-                       gs_app_add_review (app, review1);
-
-                       /* set self review */
-                       review2 = gs_review_new ();
-                       gs_review_set_rating (review2, 100);
-                       gs_review_set_reviewer (review2, "Just Myself");
-                       gs_review_set_summary (review2, "I like this application");
-                       gs_review_set_text (review2, "I'm not very wordy myself.");
-                       gs_review_set_version (review2, "3.16.3");
-                       gs_review_set_date (review2, dt);
-                       gs_review_set_flags (review2, GS_REVIEW_FLAG_SELF);
-                       gs_app_add_review (app, review2);
-               }
+               g_autoptr(GsReview) review1 = NULL;
+               g_autoptr(GsReview) review2 = NULL;
+               g_autoptr(GDateTime) dt = NULL;
+
+               dt = g_date_time_new_now_utc ();
+
+               /* set first review */
+               review1 = gs_review_new ();
+               gs_review_set_rating (review1, 50);
+               gs_review_set_reviewer (review1, "Angela Avery");
+               gs_review_set_summary (review1, "Steep learning curve, but worth it");
+               gs_review_set_text (review1, "Best overall 3D application I've ever used overall 3D 
application I've ever used. Best overall 3D application I've ever used overall 3D application I've ever used. 
Best overall 3D application I've ever used overall 3D application I've ever used. Best overall 3D application 
I've ever used overall 3D application I've ever used.");
+               gs_review_set_version (review1, "3.16.4");
+               gs_review_set_date (review1, dt);
+               gs_app_add_review (app, review1);
+
+               /* set self review */
+               review2 = gs_review_new ();
+               gs_review_set_rating (review2, 100);
+               gs_review_set_reviewer (review2, "Just Myself");
+               gs_review_set_summary (review2, "I like this application");
+               gs_review_set_text (review2, "I'm not very wordy myself.");
+               gs_review_set_version (review2, "3.16.3");
+               gs_review_set_date (review2, dt);
+               gs_review_set_flags (review2, GS_REVIEW_FLAG_SELF);
+               gs_app_add_review (app, review2);
        }
 
        /* add fake ratings */
        if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEW_RATINGS) {
-               for (l = *list; l != NULL; l = l->next) {
-                       g_autoptr(GArray) ratings = NULL;
-                       const gint data[] = { 0, 10, 20, 30, 15, 2 };
-                       ratings = g_array_sized_new (FALSE, FALSE, sizeof (gint), 6);
-                       g_array_append_vals (ratings, data, 6);
-                       app = GS_APP (l->data);
-                       gs_app_set_review_ratings (app, ratings);
-               }
+               g_autoptr(GArray) ratings = NULL;
+               const gint data[] = { 0, 10, 20, 30, 15, 2 };
+               ratings = g_array_sized_new (FALSE, FALSE, sizeof (gint), 6);
+               g_array_append_vals (ratings, data, 6);
+               gs_app_set_review_ratings (app, ratings);
        }
 
        /* add a rating */
        if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING) {
-               for (l = *list; l != NULL; l = l->next) {
-                       app = GS_APP (l->data);
-                       gs_app_set_rating (app, 66);
-               }
+               gs_app_set_rating (app, 66);
        }
 
        return TRUE;
@@ -236,14 +402,15 @@ gs_plugin_add_category_apps (GsPlugin *plugin,
                             GCancellable *cancellable,
                             GError **error)
 {
-       g_autoptr(GsApp) app = gs_app_new ("gnome-boxes");
-       gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Boxes");
+       g_autoptr(GsApp) app = gs_app_new ("chiron.desktop");
+       gs_app_set_name (app, GS_APP_QUALITY_NORMAL, "Chiron");
        gs_app_set_summary (app, GS_APP_QUALITY_NORMAL, "View and use virtual machines");
        gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, "http://www.box.org";);
        gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
        gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
-       gs_app_set_pixbuf (app, gdk_pixbuf_new_from_file 
("/usr/share/icons/hicolor/48x48/apps/gnome-boxes.png", NULL));
+       gs_app_set_pixbuf (app, gdk_pixbuf_new_from_file 
("/usr/share/icons/hicolor/48x48/apps/chiron.desktop.png", NULL));
        gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
+       gs_app_set_management_plugin (app, plugin->name);
        gs_plugin_add_app (list, app);
        return TRUE;
 }
@@ -262,12 +429,84 @@ gs_plugin_add_distro_upgrades (GsPlugin *plugin,
        gs_app_set_kind (app, AS_APP_KIND_OS_UPGRADE);
        gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
        gs_app_set_name (app, GS_APP_QUALITY_LOWEST, "Fedora");
+       gs_app_set_summary (app, GS_APP_QUALITY_NORMAL,
+                           "A major upgrade, with new features and added polish.");
+       gs_app_set_url (app, AS_URL_KIND_HOMEPAGE,
+                       "https://fedoraproject.org/wiki/Releases/24/Schedule";);
        gs_app_set_version (app, "24");
+       gs_app_set_management_plugin (app, plugin->name);
        gs_plugin_add_app (list, app);
        return TRUE;
 }
 
 /**
+ * gs_plugin_refresh:
+ */
+gboolean
+gs_plugin_refresh (GsPlugin *plugin,
+                  guint cache_age,
+                  GsPluginRefreshFlags flags,
+                  GCancellable *cancellable,
+                  GError **error)
+{
+       guint delay_ms = 100;
+       g_autoptr(GsApp) app = gs_app_new (NULL);
+
+       /* each one takes more time */
+       if (flags & GS_PLUGIN_REFRESH_FLAGS_METADATA)
+               delay_ms += 3000;
+       if (flags & GS_PLUGIN_REFRESH_FLAGS_PAYLOAD)
+               delay_ms += 5000;
+
+       /* do delay */
+       return gs_plugin_dummy_delay (plugin, app, delay_ms, cancellable, error);
+}
+
+/**
+ * gs_plugin_app_upgrade_download:
+ */
+gboolean
+gs_plugin_app_upgrade_download (GsPlugin *plugin, GsApp *app,
+                               GCancellable *cancellable, GError **error)
+{
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
+               return TRUE;
+
+       g_debug ("starting download");
+       gs_app_set_state (app, AS_APP_STATE_INSTALLING);
+       if (!gs_plugin_dummy_delay (plugin, app, 5000, cancellable, error))
+               return FALSE;
+       gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
+       return TRUE;
+}
+
+/**
+ * gs_plugin_app_upgrade_trigger:
+ */
+gboolean
+gs_plugin_app_upgrade_trigger (GsPlugin *plugin, GsApp *app,
+                              GCancellable *cancellable, GError **error)
+{
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
+               return TRUE;
+
+       /* NOP */
+       return TRUE;
+}
+
+/**
+ * gs_plugin_offline_update_cancel:
+ */
+gboolean
+gs_plugin_offline_update_cancel (GsPlugin *plugin, GsApp *app,
+                        GCancellable *cancellable, GError **error)
+{
+       return TRUE;
+}
+
+/**
  * gs_plugin_review_submit:
  */
 gboolean
diff --git a/src/plugins/gs-plugin-epiphany.c b/src/plugins/gs-plugin-epiphany.c
index 9904354..b4690cb 100644
--- a/src/plugins/gs-plugin-epiphany.c
+++ b/src/plugins/gs-plugin-epiphany.c
@@ -234,7 +234,7 @@ gs_plugin_app_remove (GsPlugin *plugin, GsApp *app,
        g_autoptr(GFile) file_app = NULL;
 
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "Epiphany") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
        epi_desktop = gs_app_get_source_id_default (app);
        if (epi_desktop == NULL)
@@ -262,13 +262,27 @@ gs_plugin_app_remove (GsPlugin *plugin, GsApp *app,
 /**
  * gs_plugin_refine_app:
  */
-static gboolean
-gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
 {
+       const gchar *tmp;
        g_autofree gchar *fn = NULL;
        g_autofree gchar *hash = NULL;
        g_autofree gchar *id_nonfull = NULL;
 
+       /* only process this app if was created by this plugin */
+       if (gs_app_get_kind (app) != AS_APP_KIND_WEB_APP)
+               return TRUE;
+       tmp = gs_app_get_source_id_default (app);
+       if (tmp != NULL)
+               return TRUE;
+
+       gs_app_set_size (app, 4096);
+
        id_nonfull = _gs_app_get_id_nonfull (app);
        hash = g_compute_checksum_for_string (G_CHECKSUM_SHA1, gs_app_get_name (app), -1);
        fn = g_strdup_printf ("%s/epiphany/app-%s-%s/%s-%s.desktop",
@@ -280,7 +294,7 @@ gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
        if (g_file_test (fn, G_FILE_TEST_EXISTS)) {
                gs_app_set_state (app, AS_APP_STATE_INSTALLED);
                gs_app_add_source_id (app, fn);
-               gs_app_set_management_plugin (app, "Epiphany");
+               gs_app_set_management_plugin (app, plugin->name);
                return TRUE;
        }
        gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
@@ -288,34 +302,6 @@ gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
 }
 
 /**
- * gs_plugin_refine:
- */
-gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
-{
-       GList *l;
-       GsApp *app;
-       const gchar *tmp;
-
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               if (gs_app_get_kind (app) != AS_APP_KIND_WEB_APP)
-                       continue;
-               gs_app_set_size (app, 4096);
-               tmp = gs_app_get_source_id_default (app);
-               if (tmp != NULL)
-                       continue;
-               if (!gs_plugin_refine_app (plugin, app, error))
-                       return FALSE;
-       }
-       return TRUE;
-}
-
-/**
  * gs_plugin_launch:
  */
 gboolean
@@ -325,7 +311,7 @@ gs_plugin_launch (GsPlugin *plugin,
                  GError **error)
 {
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "Epiphany") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
        return gs_plugin_app_launch (plugin, app, error);
 }
diff --git a/src/plugins/gs-plugin-fedora-distro-upgrades.c b/src/plugins/gs-plugin-fedora-distro-upgrades.c
index c41a36d..a6d9b03 100644
--- a/src/plugins/gs-plugin-fedora-distro-upgrades.c
+++ b/src/plugins/gs-plugin-fedora-distro-upgrades.c
@@ -21,7 +21,6 @@
 
 #include <config.h>
 
-#include <errno.h>
 #include <json-glib/json-glib.h>
 
 #include <gs-plugin.h>
@@ -31,7 +30,9 @@
 #define FEDORA_PKGDB_COLLECTIONS_API_URI "https://admin.fedoraproject.org/pkgdb/api/collections/";
 
 struct GsPluginPrivate {
-       GPtrArray       *distros;
+       gchar           *cachefn;
+       gchar           *os_name;
+       guint64          os_version;
 };
 
 /**
@@ -64,8 +65,80 @@ gs_plugin_initialize (GsPlugin *plugin)
 void
 gs_plugin_destroy (GsPlugin *plugin)
 {
-       if (plugin->priv->distros != NULL)
-               g_ptr_array_unref (plugin->priv->distros);
+       g_free (plugin->priv->os_name);
+       g_free (plugin->priv->cachefn);
+}
+
+/**
+ * gs_plugin_setup:
+ */
+gboolean
+gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+{
+       gchar *endptr = NULL;
+       g_autofree gchar *cachedir = NULL;
+       g_autofree gchar *verstr = NULL;
+
+       /* create the cachedir */
+       cachedir = gs_utils_get_cachedir ("upgrades", error);
+       if (cachedir == NULL)
+               return FALSE;
+       plugin->priv->cachefn = g_build_filename (cachedir, "fedora.json", NULL);
+
+       /* read os-release for the current versions */
+       plugin->priv->os_name = gs_os_release_get_name (error);
+       if (plugin->priv->os_name == NULL)
+               return FALSE;
+       verstr = gs_os_release_get_version_id (error);
+       if (verstr == NULL)
+               return FALSE;
+
+       /* parse the version */
+       plugin->priv->os_version = g_ascii_strtoull (verstr, &endptr, 10);
+       if (endptr == verstr || plugin->priv->os_version > G_MAXUINT) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "Failed parse VERSION_ID: %s", verstr);
+               return FALSE;
+       }
+
+       /* success */
+       return TRUE;
+}
+
+/**
+ * gs_plugin_refresh:
+ */
+gboolean
+gs_plugin_refresh (GsPlugin *plugin,
+                  guint cache_age,
+                  GsPluginRefreshFlags flags,
+                  GCancellable *cancellable,
+                  GError **error)
+{
+       /* only for update metadata, no stored state other than setup() */
+       if ((flags & GS_PLUGIN_REFRESH_FLAGS_METADATA) == 0)
+               return TRUE;
+
+       /* check cache age */
+       if (cache_age > 0) {
+               guint tmp;
+               g_autoptr(GFile) file = g_file_new_for_path (plugin->priv->cachefn);
+               tmp = gs_utils_get_file_age (file);
+               if (tmp < cache_age) {
+                       g_debug ("%s is only %i seconds old",
+                                plugin->priv->cachefn, tmp);
+                       return TRUE;
+               }
+       }
+
+       /* download new file */
+       return gs_plugin_download_file (plugin, NULL,
+                                       FEDORA_PKGDB_COLLECTIONS_API_URI,
+                                       plugin->priv->cachefn,
+                                       cancellable,
+                                       error);
 }
 
 typedef enum {
@@ -160,9 +233,8 @@ parse_pkgdb_collections_data (const gchar *data,
                if (version_str == NULL)
                        continue;
 
-               errno = 0;
                version = g_ascii_strtoull (version_str, &endptr, 10);
-               if (errno != 0 || endptr == version_str || version > G_MAXUINT)
+               if (endptr == version_str || version > G_MAXUINT)
                        continue;
 
                distro_info = g_slice_new0 (DistroInfo);
@@ -185,67 +257,40 @@ gs_plugin_add_distro_upgrades (GsPlugin *plugin,
                               GCancellable *cancellable,
                               GError **error)
 {
-       g_autofree gchar *os_name = NULL;
-       g_autofree gchar *os_version_str = NULL;
-       g_autoptr(GPtrArray) distros = NULL;
-       g_autoptr(SoupMessage) msg = NULL;
-       gchar *endptr = NULL;
+       gsize len;
        guint i;
-       guint status_code;
-       guint64 os_version;
-
-       os_name = gs_os_release_get_name (error);
-       if (os_name == NULL)
-               return FALSE;
-       os_version_str = gs_os_release_get_version_id (error);
-       if (os_version_str == NULL)
-               return FALSE;
+       g_autofree gchar *data = NULL;
+       g_autoptr(GPtrArray) distros = NULL;
 
-       errno = 0;
-       os_version = g_ascii_strtoull (os_version_str, &endptr, 10);
-       if (errno != 0 || endptr == os_version_str || os_version > G_MAXUINT) {
-               g_set_error (error,
-                            GS_PLUGIN_ERROR,
-                            GS_PLUGIN_ERROR_FAILED,
-                            "Failed parse VERSION_ID: %s", os_version_str);
+       /* get cached file */
+       if (!g_file_get_contents (plugin->priv->cachefn, &data, &len, error))
                return FALSE;
-       }
-
-       /* create the GET data */
-       msg = soup_message_new (SOUP_METHOD_GET, FEDORA_PKGDB_COLLECTIONS_API_URI);
 
-       /* set sync request */
-       status_code = soup_session_send_message (plugin->soup_session, msg);
-       if (status_code != SOUP_STATUS_OK) {
-               g_set_error (error,
-                            GS_PLUGIN_ERROR,
-                            GS_PLUGIN_ERROR_FAILED,
-                            "Failed to download distro upgrade data: %s",
-                            soup_status_get_phrase (status_code));
+       /* parse data */
+       distros = parse_pkgdb_collections_data (data, len, error);
+       if (distros == NULL)
                return FALSE;
-       }
-
-       g_clear_pointer (&plugin->priv->distros, g_ptr_array_unref);
-       plugin->priv->distros = parse_pkgdb_collections_data (msg->response_body->data,
-                                                             msg->response_body->length,
-                                                             error);
-       for (i = 0; i < plugin->priv->distros->len; i++) {
-               DistroInfo *distro_info = g_ptr_array_index (plugin->priv->distros, i);
+       for (i = 0; i < distros->len; i++) {
+               DistroInfo *distro_info = g_ptr_array_index (distros, i);
                g_autofree gchar *app_id = NULL;
                g_autofree gchar *app_version = NULL;
+               g_autofree gchar *url = NULL;
                g_autoptr(GsApp) app = NULL;
 
                /* only interested in upgrades to the same distro */
-               if (g_strcmp0 (distro_info->name, os_name) != 0)
+               if (g_strcmp0 (distro_info->name, plugin->priv->os_name) != 0)
                        continue;
+
                /* only interested in newer versions */
-               if (distro_info->version <= os_version)
+               if (distro_info->version <= plugin->priv->os_version)
                        continue;
+
                /* only interested in non-devel distros */
                if (distro_info->status == DISTRO_STATUS_DEVEL)
                        continue;
 
-               app_id = g_strdup_printf ("org.fedoraproject.release-%d.upgrade", distro_info->version);
+               app_id = g_strdup_printf ("org.fedoraproject.release-%d.upgrade",
+                                         distro_info->version);
                app_version = g_strdup_printf ("%d", distro_info->version);
 
                /* create */
@@ -254,6 +299,14 @@ gs_plugin_add_distro_upgrades (GsPlugin *plugin,
                gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
                gs_app_set_name (app, GS_APP_QUALITY_LOWEST, distro_info->name);
                gs_app_set_version (app, app_version);
+               gs_app_set_management_plugin (app, "packagekit");
+
+               /* just use the release notes */
+               url = g_strdup_printf ("https://docs.fedoraproject.org/en-US/";
+                                      "Fedora/%i/html/Release_Notes/",
+                                      distro_info->version);
+               gs_app_set_url (app, AS_URL_KIND_HOMEPAGE, url);
+
                gs_plugin_add_app (list, app);
        }
 
diff --git a/src/plugins/gs-plugin-fedora-tagger-usage.c b/src/plugins/gs-plugin-fedora-tagger-usage.c
index a71f8a5..e2665ab 100644
--- a/src/plugins/gs-plugin-fedora-tagger-usage.c
+++ b/src/plugins/gs-plugin-fedora-tagger-usage.c
@@ -164,6 +164,8 @@ gs_plugin_app_install (GsPlugin *plugin,
                       GCancellable *cancellable,
                       GError **error)
 {
+       if (gs_app_get_state (app) != AS_APP_STATE_INSTALLED)
+               return TRUE;
        return gs_plugin_app_set_usage_app (plugin, app, TRUE, error);
 }
 
@@ -176,5 +178,7 @@ gs_plugin_app_remove (GsPlugin *plugin,
                      GCancellable *cancellable,
                      GError **error)
 {
+       if (gs_app_get_state (app) != AS_APP_STATE_AVAILABLE)
+               return TRUE;
        return gs_plugin_app_set_usage_app (plugin, app, FALSE, error);
 }
diff --git a/src/plugins/gs-plugin-fwupd.c b/src/plugins/gs-plugin-fwupd.c
index 32aa9a3..11c25a3 100644
--- a/src/plugins/gs-plugin-fwupd.c
+++ b/src/plugins/gs-plugin-fwupd.c
@@ -111,10 +111,10 @@ gs_plugin_fwupd_changed_cb (GDBusProxy *proxy,
 }
 
 /**
- * gs_plugin_startup:
+ * gs_plugin_setup:
  */
-static gboolean
-gs_plugin_startup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+gboolean
+gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
 {
        gsize len;
        g_autofree gchar *data = NULL;
@@ -207,8 +207,6 @@ gs_plugin_fwupd_set_app_from_kv (GsApp *app, const gchar *key, GVariant *val)
 {
        g_debug ("key %s", key);
 
-       gs_app_add_quirk (app, AS_APP_QUIRK_NOT_LAUNCHABLE);
-
        if (g_strcmp0 (key, "AppstreamId") == 0) {
                gs_app_set_id (app, g_variant_get_string (val, NULL));
                return;
@@ -278,7 +276,6 @@ gs_plugin_add_update_app (GsPlugin *plugin,
        g_autofree gchar *update_hash = NULL;
        g_autofree gchar *update_uri = NULL;
        g_autoptr(AsIcon) icon = NULL;
-       g_autoptr(GFile) file = NULL;
        g_autoptr(GsApp) app = NULL;
 
        app = gs_app_new (NULL);
@@ -383,14 +380,12 @@ gs_plugin_add_update_app (GsPlugin *plugin,
        }
 
        /* actually add the application */
-       gs_app_set_management_plugin (app, "fwupd");
+       gs_app_set_management_plugin (app, plugin->name);
        gs_app_set_kind (app, AS_APP_KIND_FIRMWARE);
        gs_app_add_source_id (app, filename_cache);
        gs_app_add_category (app, "System");
        gs_app_set_kind (app, AS_APP_KIND_FIRMWARE);
        gs_app_set_metadata (app, "fwupd::DeviceID", id);
-       file = g_file_new_for_path (filename_cache);
-       gs_app_set_local_file (app, file);
        gs_plugin_add_app (list, app);
 
        /* create icon */
@@ -418,14 +413,6 @@ gs_plugin_add_updates_historical (GsPlugin *plugin,
        g_autoptr(GVariantIter) iter = NULL;
        g_autoptr(GVariant) val = NULL;
 
-       /* set up plugin */
-       if (plugin->priv->proxy == NULL) {
-               if (!gs_plugin_startup (plugin, cancellable, error))
-                       return FALSE;
-       }
-       if (plugin->priv->proxy == NULL)
-               return TRUE;
-
        /* get historical updates */
        val = g_dbus_proxy_call_sync (plugin->priv->proxy,
                                      "GetResults",
@@ -480,14 +467,6 @@ gs_plugin_add_updates (GsPlugin *plugin,
        g_autoptr(GVariantIter) iter = NULL;
        g_autoptr(GVariant) val = NULL;
 
-       /* set up plugin */
-       if (plugin->priv->proxy == NULL) {
-               if (!gs_plugin_startup (plugin, cancellable, error))
-                       return FALSE;
-       }
-       if (plugin->priv->proxy == NULL)
-               return TRUE;
-
        /* get current list of updates */
        val = g_dbus_proxy_call_sync (plugin->priv->proxy,
                                      "GetUpdates",
@@ -501,10 +480,7 @@ gs_plugin_add_updates (GsPlugin *plugin,
                                     G_DBUS_ERROR,
                                     G_DBUS_ERROR_SERVICE_UNKNOWN)) {
                        /* the fwupd service might be unavailable, continue in that case */
-                       if (error) {
-                               *error = g_steal_pointer (&error_local);
-                               g_prefix_error (error, "could not get fwupd updates: ");
-                       }
+                       g_prefix_error (error, "could not get fwupd updates: ");
                        return FALSE;
                }
                if (g_error_matches (error_local,
@@ -737,14 +713,6 @@ gs_plugin_refresh (GsPlugin *plugin,
        const gchar *tmp;
        guint i;
 
-       /* set up plugin */
-       if (plugin->priv->proxy == NULL) {
-               if (!gs_plugin_startup (plugin, cancellable, error))
-                       return FALSE;
-       }
-       if (plugin->priv->proxy == NULL)
-               return TRUE;
-
        /* get the metadata and signature file */
        if (!gs_plugin_fwupd_check_lvfs_metadata (plugin, cache_age, cancellable, error))
                return FALSE;
@@ -906,13 +874,13 @@ gs_plugin_app_upgrade (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_update:
+ * gs_plugin_offline_update:
  */
 gboolean
-gs_plugin_update (GsPlugin *plugin,
-                  GList *apps,
-                  GCancellable *cancellable,
-                  GError **error)
+gs_plugin_offline_update (GsPlugin *plugin,
+                          GList *apps,
+                          GCancellable *cancellable,
+                          GError **error)
 {
        GList *l;
 
@@ -935,16 +903,15 @@ gs_plugin_fwupd_install (GsPlugin *plugin,
                         GError **error)
 {
        const gchar *install_method;
-       const gchar *device_id;
-       g_autofree gchar *filename = NULL;
-       gboolean offline = FALSE;
+       const gchar *filename;
+       gboolean offline = TRUE;
 
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "fwupd") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
-       /* not set */
-       if (gs_app_get_local_file (app) == NULL) {
+       filename = gs_app_get_source_id_default (app);
+       if (filename == NULL) {
                g_set_error (error,
                             GS_PLUGIN_ERROR,
                             GS_PLUGIN_ERROR_FAILED,
@@ -952,12 +919,6 @@ gs_plugin_fwupd_install (GsPlugin *plugin,
                             filename);
                return FALSE;
        }
-       filename = g_file_get_path (gs_app_get_local_file (app));
-
-       /* limit to single device? */
-       device_id = gs_app_get_metadata_item (app, "fwupd::DeviceID");
-       if (device_id == NULL)
-               device_id = FWUPD_DEVICE_ID_ANY;
 
        /* only offline supported */
        install_method = gs_app_get_metadata_item (app, "fwupd::InstallMethod");
@@ -966,8 +927,10 @@ gs_plugin_fwupd_install (GsPlugin *plugin,
 
        gs_app_set_state (app, AS_APP_STATE_INSTALLING);
        if (!gs_plugin_fwupd_upgrade (plugin, filename, FWUPD_DEVICE_ID_ANY, offline,
-                                     cancellable, error))
+                                     cancellable, error)) {
+               gs_app_set_state_recover (app);
                return FALSE;
+       }
        gs_app_set_state (app, AS_APP_STATE_INSTALLED);
        return TRUE;
 }
@@ -997,14 +960,6 @@ gs_plugin_fwupd_unlock (GsPlugin *plugin,
 {
        g_autoptr(GVariant) val = NULL;
 
-       /* set up plugin */
-       if (plugin->priv->proxy == NULL) {
-               if (!gs_plugin_startup (plugin, cancellable, error))
-                       return FALSE;
-       }
-       if (plugin->priv->proxy == NULL)
-               return TRUE;
-
        /* unlock device */
        val = g_dbus_proxy_call_sync (plugin->priv->proxy,
                                      "Unlock",
@@ -1019,12 +974,12 @@ gs_plugin_fwupd_unlock (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_update_app:
+ * gs_plugin_app_update:
  *
- * Called when a user clicks [Update] in the updates panel
+ * This is only called when updating device firmware live.
  */
 gboolean
-gs_plugin_update_app (GsPlugin *plugin,
+gs_plugin_app_update (GsPlugin *plugin,
                      GsApp *app,
                      GCancellable *cancellable,
                      GError **error)
@@ -1064,10 +1019,9 @@ gs_plugin_file_to_app (GsPlugin *plugin,
        GVariant *val;
        GVariant *variant;
        const gchar *key;
-       gboolean supported;
-       g_autofree gchar *content_type = NULL;
        gint fd;
        gint retval;
+       g_autofree gchar *content_type = NULL;
        g_autoptr(AsIcon) icon = NULL;
        g_autoptr(GDBusConnection) conn = NULL;
        g_autoptr(GDBusMessage) message = NULL;
diff --git a/src/plugins/gs-plugin-hardcoded-blacklist.c b/src/plugins/gs-plugin-hardcoded-blacklist.c
index 9b6741f..e9de91b 100644
--- a/src/plugins/gs-plugin-hardcoded-blacklist.c
+++ b/src/plugins/gs-plugin-hardcoded-blacklist.c
@@ -52,8 +52,12 @@ gs_plugin_order_after (GsPlugin *plugin)
 /**
  * gs_plugin_refine_app:
  */
-static gboolean
-gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
 {
        guint i;
        const gchar *app_globs[] = {
@@ -84,27 +88,3 @@ gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
 
        return TRUE;
 }
-
-/**
- * gs_plugin_refine:
- */
-gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
-{
-       GList *l;
-       GsApp *app;
-       g_autoptr(AsProfileTask) ptask = NULL;
-
-       /* are any of the packages on the blacklist? */
-       ptask = as_profile_start_literal (plugin->profile, "hardcoded-blacklist");
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               if (!gs_plugin_refine_app (plugin, app, error))
-                       return FALSE;
-       }
-       return TRUE;
-}
diff --git a/src/plugins/gs-plugin-hardcoded-featured.c b/src/plugins/gs-plugin-hardcoded-featured.c
index 1f36b54..eb10628 100644
--- a/src/plugins/gs-plugin-hardcoded-featured.c
+++ b/src/plugins/gs-plugin-hardcoded-featured.c
@@ -71,6 +71,7 @@ gs_plugin_add_featured_app (GList **list,
        /* add app */
        app = gs_app_new (id);
        gs_app_add_kudo (app, GS_APP_KUDO_FEATURED_RECOMMENDED);
+       gs_app_add_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX);
        gs_app_set_metadata (app, "Featured::background", background);
        gs_app_set_metadata (app, "Featured::stroke-color", stroke_color);
        gs_app_set_metadata (app, "Featured::text-color", text_color);
diff --git a/src/plugins/gs-plugin-icons.c b/src/plugins/gs-plugin-icons.c
index 62ae8de..e16b0c5 100644
--- a/src/plugins/gs-plugin-icons.c
+++ b/src/plugins/gs-plugin-icons.c
@@ -112,15 +112,25 @@ gs_plugin_icons_download (GsPlugin *plugin, const gchar *uri, const gchar *filen
 }
 
 /**
- * gs_plugin_refine:
+ * gs_plugin_refine_app:
  */
-static gboolean
-gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
 {
        AsIcon *ic;
        const gchar *fn;
        gchar *found;
 
+       /* invalid */
+       if (gs_app_get_pixbuf (app) != NULL)
+               return TRUE;
+       if (gs_app_get_icon (app) == NULL)
+               return TRUE;
+
        /* not applicable */
        ic = gs_app_get_icon (app);
        if (as_icon_get_url (ic) == NULL)
@@ -128,6 +138,13 @@ gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
        if (as_icon_get_filename (ic) == NULL)
                return TRUE;
 
+       /* local */
+       if (g_str_has_prefix (as_icon_get_url (ic), "file://")) {
+               as_icon_set_filename (ic, as_icon_get_url (ic) + 7);
+               as_icon_set_kind (ic, AS_ICON_KIND_LOCAL);
+               return gs_app_load_icon (app, plugin->scale, error);
+       }
+
        /* convert filename from jpg to png */
        fn = as_icon_get_filename (ic);
        found = g_strstr_len (fn, -1, ".jpg");
@@ -142,31 +159,3 @@ gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
        as_icon_set_kind (ic, AS_ICON_KIND_LOCAL);
        return gs_app_load_icon (app, plugin->scale, error);
 }
-
-/**
- * gs_plugin_refine:
- */
-gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
-{
-       GError *error_local = NULL;
-       GList *l;
-       GsApp *app;
-
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               if (gs_app_get_pixbuf (app) != NULL)
-                       continue;
-               if (gs_app_get_icon (app) == NULL)
-                       continue;
-               if (!gs_plugin_refine_app (plugin, app, &error_local)) {
-                       g_warning ("ignoring: %s", error_local->message);
-                       g_clear_error (&error_local);
-               }
-       }
-       return TRUE;
-}
diff --git a/src/plugins/gs-plugin-limba.c b/src/plugins/gs-plugin-limba.c
index adb260e..7e0729a 100644
--- a/src/plugins/gs-plugin-limba.c
+++ b/src/plugins/gs-plugin-limba.c
@@ -45,6 +45,18 @@ gs_plugin_get_name (void)
 }
 
 /**
+ * gs_plugin_order_after:
+ */
+const gchar **
+gs_plugin_order_after (GsPlugin *plugin)
+{
+       static const gchar *deps[] = { "appstream",
+                                      "packagekit",
+                                      NULL };
+       return deps;
+}
+
+/**
  * gs_plugin_initialize:
  */
 void
@@ -67,11 +79,25 @@ gs_plugin_destroy (GsPlugin *plugin)
 /**
  * gs_plugin_refine_app:
  */
-static gboolean
-gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
 {
        LiPkgInfo *pki;
        g_autoptr(GError) error_local = NULL;
+       g_autoptr(AsProfileTask) ptask = NULL;
+
+       /* not us */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
+               return TRUE;
+
+       /* profile */
+       ptask = as_profile_start (plugin->profile,
+                                 "limba::refine{%s}",
+                                 gs_app_get_id (app));
 
        /* sanity check */
        if (gs_app_get_source_default (app) == NULL)
@@ -103,36 +129,6 @@ gs_plugin_refine_app (GsPlugin *plugin, GsApp *app, GError **error)
 }
 
 /**
- * gs_plugin_refine:
- */
-gboolean
-gs_plugin_refine (GsPlugin *plugin,
-               GList **list,
-               GsPluginRefineFlags flags,
-               GCancellable *cancellable,
-               GError **error)
-{
-       GList *l;
-       GsApp *app;
-       g_autoptr(AsProfileTask) ptask = NULL;
-
-       ptask = as_profile_start_literal (plugin->profile, "limba::refine");
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-
-               /* not us */
-               if (g_strcmp0 (gs_app_get_management_plugin (app), "Limba") != 0)
-                       continue;
-
-               if (!gs_plugin_refine_app (plugin, app, error))
-                       return FALSE;
-       }
-
-       /* sucess */
-       return TRUE;
-}
-
-/**
  * GsPluginHelper:
  * Helper structure for Limba callbacks.
  */
@@ -189,7 +185,7 @@ gs_plugin_app_remove (GsPlugin *plugin,
        g_autoptr(GError) error_local = NULL;
 
        /* not us */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "Limba") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
        mgr = li_manager_new ();
@@ -235,7 +231,7 @@ gs_plugin_app_install (GsPlugin *plugin,
        g_autoptr(GError) error_local = NULL;
 
        /* not us */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "Limba") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
        /* create new installer and select remote package */
@@ -306,7 +302,7 @@ gs_plugin_refresh (GsPlugin *plugin,
        GError *error_local = NULL;
 
        /* not us */
-       if ((flags & GS_PLUGIN_REFRESH_FLAGS_UPDATES) == 0)
+       if ((flags & GS_PLUGIN_REFRESH_FLAGS_METADATA) == 0)
                return TRUE;
 
        mgr = li_manager_new ();
@@ -369,7 +365,7 @@ gs_plugin_add_updates (GsPlugin *plugin,
                        app = gs_app_new (li_pkg_info_get_name (old_pki));
                }
 
-               gs_app_set_management_plugin (app, "Limba");
+               gs_app_set_management_plugin (app, plugin->name);
                gs_app_set_state (app, AS_APP_STATE_UPDATABLE_LIVE);
                gs_app_set_kind (app, AS_APP_KIND_GENERIC);
                gs_plugin_add_app (list, app);
@@ -408,7 +404,7 @@ gs_plugin_update_app (GsPlugin *plugin,
        g_autoptr(GError) error_local = NULL;
 
        /* check if this update request is for us */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "Limba") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
        /* sanity check */
diff --git a/src/plugins/gs-plugin-menu-spec-refine.c b/src/plugins/gs-plugin-menu-spec-refine.c
index 379a5f2..c6fb49c 100644
--- a/src/plugins/gs-plugin-menu-spec-refine.c
+++ b/src/plugins/gs-plugin-menu-spec-refine.c
@@ -93,13 +93,24 @@ gs_plugin_refine_app_category (GsPlugin *plugin,
 /**
  * gs_plugin_refine_app:
  */
-static gboolean
-gs_plugin_refine_app (GsPlugin *plugin, GsApp *app)
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
 {
        const MenuSpecData *msdata;
        gboolean ret = FALSE;
        gchar *tmp;
        guint i;
+       const gchar *EMPTY[] = { "", NULL };
+
+       /* nothing to do here */
+       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_MENU_PATH) == 0)
+               return TRUE;
+       if (gs_app_get_menu_path (app) != NULL)
+               return TRUE;
 
        /* find a top level category the app has */
        msdata = menu_spec_get_data ();
@@ -114,35 +125,10 @@ gs_plugin_refine_app (GsPlugin *plugin, GsApp *app)
                        break;
                }
        }
-       return ret;
-}
 
-/**
- * gs_plugin_refine:
- */
-gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
-{
-       GList *l;
-       GsApp *app;
-       const gchar *EMPTY[] = { "", NULL };
+       /* don't keep searching for this */
+       if (!ret)
+               gs_app_set_menu_path (app, (gchar **) EMPTY);
 
-       /* nothing to do here */
-       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_MENU_PATH) == 0)
-               return TRUE;
-
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               if (gs_app_get_menu_path (app) == NULL) {
-                       if (!gs_plugin_refine_app (plugin, app)) {
-                               /* don't keep searching for this */
-                               gs_app_set_menu_path (app, (gchar **) EMPTY);
-                       }
-               }
-       }
        return TRUE;
 }
diff --git a/src/plugins/gs-plugin-moduleset.c b/src/plugins/gs-plugin-moduleset.c
index dfd8ec6..b8669e0 100644
--- a/src/plugins/gs-plugin-moduleset.c
+++ b/src/plugins/gs-plugin-moduleset.c
@@ -150,7 +150,7 @@ gs_plugin_add_categories (GsPlugin *plugin,
                                guint size;
                                g_autoptr(GsCategory) cat = NULL;
 
-                               cat = gs_category_new (parent, "featured", _("Featured"));
+                               cat = gs_category_new (parent, "featured", NULL);
                                gs_category_add_subcategory (parent, cat);
                                size = gs_moduleset_get_n_featured (plugin->priv->moduleset, id);
                                gs_category_set_size (cat, size);
@@ -201,6 +201,7 @@ gs_plugin_add_category_apps (GsPlugin *plugin,
                for (i = 0; apps[i]; i++) {
                        g_autoptr(GsApp) app = NULL;
                        app = gs_app_new (apps[i]);
+                       gs_app_add_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX);
                        gs_plugin_add_app (list, app);
                }
        }
@@ -263,6 +264,7 @@ gs_plugin_add_popular (GsPlugin *plugin,
        for (i = 0; apps[i]; i++) {
                g_autoptr(GsApp) app = NULL;
                app = gs_app_new (apps[i]);
+               gs_app_add_quirk (app, AS_APP_QUIRK_MATCH_ANY_PREFIX);
                gs_plugin_add_app (list, app);
        }
        return TRUE;
diff --git a/src/plugins/gs-plugin-xdg-app-reviews.c b/src/plugins/gs-plugin-odrs.c
similarity index 84%
rename from src/plugins/gs-plugin-xdg-app-reviews.c
rename to src/plugins/gs-plugin-odrs.c
index f63bfe9..28f3d22 100644
--- a/src/plugins/gs-plugin-xdg-app-reviews.c
+++ b/src/plugins/gs-plugin-odrs.c
@@ -33,7 +33,7 @@
 
 /*
  * SECTION:
- * Provides review data from an anonymous source.
+ * Provides review data from the Open Desktop Ratings Serice.
  */
 
 #define XDG_APP_REVIEW_CACHE_AGE_MAX           237000 /* 1 week */
@@ -52,7 +52,7 @@ struct GsPluginPrivate {
 const gchar *
 gs_plugin_get_name (void)
 {
-       return "xdg-app-reviews";
+       return "odrs";
 }
 
 /**
@@ -108,10 +108,10 @@ gs_plugin_destroy (GsPlugin *plugin)
 }
 
 /**
- * xdg_app_review_parse_review_object:
+ * gs_plugin_odrs_parse_review_object:
  */
 static GsReview *
-xdg_app_review_parse_review_object (JsonObject *item)
+gs_plugin_odrs_parse_review_object (JsonObject *item)
 {
        GsReview *rev = gs_review_new ();
 
@@ -168,12 +168,10 @@ xdg_app_review_parse_review_object (JsonObject *item)
 }
 
 /**
- * xdg_app_review_parse_reviews:
+ * gs_plugin_odrs_parse_reviews:
  */
 static GPtrArray *
-xdg_app_review_parse_reviews (const gchar *data,
-                             gsize data_len,
-                             GError **error)
+gs_plugin_odrs_parse_reviews (const gchar *data, gsize data_len, GError **error)
 {
        JsonArray *json_reviews;
        JsonNode *json_root;
@@ -237,19 +235,17 @@ xdg_app_review_parse_reviews (const gchar *data,
                }
 
                /* create review */
-               review = xdg_app_review_parse_review_object (json_item);
+               review = gs_plugin_odrs_parse_review_object (json_item);
                g_ptr_array_add (reviews, g_object_ref (review));
        }
        return g_steal_pointer (&reviews);
 }
 
 /**
- * xdg_app_review_parse_success:
+ * gs_plugin_odrs_parse_success:
  */
 static gboolean
-xdg_app_review_parse_success (const gchar *data,
-                             gsize data_len,
-                             GError **error)
+gs_plugin_odrs_parse_success (const gchar *data, gsize data_len, GError **error)
 {
        JsonNode *json_root;
        JsonObject *json_item;
@@ -311,19 +307,19 @@ xdg_app_review_parse_success (const gchar *data,
 }
 
 /**
- * gs_plugin_xdg_app_reviews_json_post:
+ * gs_plugin_odrs_json_post:
  */
 static gboolean
-gs_plugin_xdg_app_reviews_json_post (SoupSession *session,
-                                    const gchar *uri,
-                                    const gchar *data,
-                                    GError **error)
+gs_plugin_odrs_json_post (SoupSession *session,
+                         const gchar *uri,
+                         const gchar *data,
+                         GError **error)
 {
        guint status_code;
        g_autoptr(SoupMessage) msg = NULL;
 
        /* create the GET data */
-       g_debug ("xdg-app-review sending: %s", data);
+       g_debug ("odrs sending: %s", data);
        msg = soup_message_new (SOUP_METHOD_POST, uri);
        soup_message_set_request (msg, "application/json",
                                  SOUP_MEMORY_COPY, data, strlen (data));
@@ -331,24 +327,22 @@ gs_plugin_xdg_app_reviews_json_post (SoupSession *session,
        /* set sync request */
        status_code = soup_session_send_message (session, msg);
        if (status_code != SOUP_STATUS_OK) {
-               g_warning ("Failed to set rating on xdg-app-review: %s",
+               g_warning ("Failed to set rating on odrs: %s",
                           soup_status_get_phrase (status_code));
        }
 
        /* process returned JSON */
-       g_debug ("xdg-app-review returned: %s", msg->response_body->data);
-       return xdg_app_review_parse_success (msg->response_body->data,
+       g_debug ("odrs returned: %s", msg->response_body->data);
+       return gs_plugin_odrs_parse_success (msg->response_body->data,
                                             msg->response_body->length,
                                             error);
 }
 
 /**
- * xdg_app_review_parse_ratings:
+ * gs_plugin_odrs_parse_ratings:
  */
 static GArray *
-xdg_app_review_parse_ratings (const gchar *data,
-                             gsize data_len,
-                             GError **error)
+gs_plugin_odrs_parse_ratings (const gchar *data, gsize data_len, GError **error)
 {
        GArray *ratings;
        JsonNode *json_root;
@@ -408,10 +402,10 @@ xdg_app_review_parse_ratings (const gchar *data,
 }
 
 /**
- * xdg_app_review_get_ratings:
+ * gs_plugin_odrs_get_ratings:
  */
 static GArray *
-xdg_app_review_get_ratings (GsPlugin *plugin, GsApp *app, GError **error)
+gs_plugin_odrs_get_ratings (GsPlugin *plugin, GsApp *app, GError **error)
 {
        GArray *ratings;
        guint status_code;
@@ -434,7 +428,7 @@ xdg_app_review_get_ratings (GsPlugin *plugin, GsApp *app, GError **error)
                        return NULL;
                g_debug ("got ratings data for %s from %s",
                         gs_app_get_id_no_prefix (app), cachefn);
-               return xdg_app_review_parse_ratings (json_data, -1, error);
+               return gs_plugin_odrs_parse_ratings (json_data, -1, error);
        }
 
        /* create the GET data *with* the machine hash so we can later
@@ -445,7 +439,7 @@ xdg_app_review_get_ratings (GsPlugin *plugin, GsApp *app, GError **error)
        msg = soup_message_new (SOUP_METHOD_GET, uri);
        status_code = soup_session_send_message (plugin->soup_session, msg);
        if (status_code != SOUP_STATUS_OK) {
-               if (!xdg_app_review_parse_success (msg->response_body->data,
+               if (!gs_plugin_odrs_parse_success (msg->response_body->data,
                                                   msg->response_body->length,
                                                   error))
                        return NULL;
@@ -456,8 +450,8 @@ xdg_app_review_get_ratings (GsPlugin *plugin, GsApp *app, GError **error)
                                     "status code invalid");
                return NULL;
        }
-       g_debug ("xdg-app-review returned: %s", msg->response_body->data);
-       ratings = xdg_app_review_parse_ratings (msg->response_body->data,
+       g_debug ("odrs returned: %s", msg->response_body->data);
+       ratings = gs_plugin_odrs_parse_ratings (msg->response_body->data,
                                                msg->response_body->length,
                                                error);
        if (ratings == NULL)
@@ -489,7 +483,7 @@ gs_plugin_refine_ratings (GsPlugin *plugin,
        g_autoptr(GArray) array = NULL;
 
        /* get ratings */
-       array = xdg_app_review_get_ratings (plugin, app, error);
+       array = gs_plugin_odrs_get_ratings (plugin, app, error);
        if (array == NULL)
                return FALSE;
        gs_app_set_review_ratings (app, array);
@@ -509,10 +503,10 @@ gs_plugin_refine_ratings (GsPlugin *plugin,
 }
 
 /**
- * xdg_app_review_fetch_for_app:
+ * gs_plugin_odrs_fetch_for_app:
  */
 static GPtrArray *
-xdg_app_review_fetch_for_app (GsPlugin *plugin, GsApp *app, GError **error)
+gs_plugin_odrs_fetch_for_app (GsPlugin *plugin, GsApp *app, GError **error)
 {
        const gchar *version;
        guint karma_min;
@@ -540,7 +534,7 @@ xdg_app_review_fetch_for_app (GsPlugin *plugin, GsApp *app, GError **error)
                        return NULL;
                g_debug ("got review data for %s from %s",
                         gs_app_get_id_no_prefix (app), cachefn);
-               return xdg_app_review_parse_reviews (json_data, -1, error);
+               return gs_plugin_odrs_parse_reviews (json_data, -1, error);
        }
 
        /* not always available */
@@ -583,7 +577,7 @@ xdg_app_review_fetch_for_app (GsPlugin *plugin, GsApp *app, GError **error)
                                  SOUP_MEMORY_COPY, data, strlen (data));
        status_code = soup_session_send_message (plugin->soup_session, msg);
        if (status_code != SOUP_STATUS_OK) {
-               if (!xdg_app_review_parse_success (msg->response_body->data,
+               if (!gs_plugin_odrs_parse_success (msg->response_body->data,
                                                   msg->response_body->length,
                                                   error))
                        return NULL;
@@ -594,12 +588,12 @@ xdg_app_review_fetch_for_app (GsPlugin *plugin, GsApp *app, GError **error)
                                     "status code invalid");
                return NULL;
        }
-       reviews = xdg_app_review_parse_reviews (msg->response_body->data,
+       reviews = gs_plugin_odrs_parse_reviews (msg->response_body->data,
                                                msg->response_body->length,
                                                error);
        if (reviews == NULL)
                return NULL;
-       g_debug ("xdg-app-review returned: %s", msg->response_body->data);
+       g_debug ("odrs returned: %s", msg->response_body->data);
 
        /* save to the cache */
        if (!g_file_set_contents (cachefn,
@@ -626,7 +620,7 @@ gs_plugin_refine_reviews (GsPlugin *plugin,
        g_autoptr(GPtrArray) reviews = NULL;
 
        /* get from server */
-       reviews = xdg_app_review_fetch_for_app (plugin, app, error);
+       reviews = gs_plugin_odrs_fetch_for_app (plugin, app, error);
        if (reviews == NULL)
                return FALSE;
        for (i = 0; i < reviews->len; i++) {
@@ -635,7 +629,7 @@ gs_plugin_refine_reviews (GsPlugin *plugin,
                /* save this on the application object so we can use it for
                 * submitting a new review */
                if (i == 0) {
-                       gs_app_set_metadata (app, "XdgAppReviews::user_skey",
+                       gs_app_set_metadata (app, "ODRS::user_skey",
                                             gs_review_get_metadata_item (review, "user_skey"));
                }
 
@@ -656,66 +650,47 @@ gs_plugin_refine_reviews (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_refine:
+ * gs_plugin_refine_app:
  */
 gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
 {
-       GsApp *app;
-       GList *l;
+       /* not valid */
+       if (gs_app_get_kind (app) == AS_APP_KIND_ADDON)
+               return TRUE;
+       if (gs_app_get_id_no_prefix (app) == NULL)
+               return TRUE;
 
        /* add reviews if possible */
        if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEWS) {
-               for (l = *list; l != NULL; l = l->next) {
-                       g_autoptr(GError) error_local = NULL;
-                       app = GS_APP (l->data);
-                       if (gs_app_get_reviews(app)->len > 0)
-                               continue;
-                       if (gs_app_get_id_no_prefix (app) == NULL)
-                               continue;
-                       if (gs_app_get_kind (app) == AS_APP_KIND_ADDON)
-                               continue;
-                       if (!gs_plugin_refine_reviews (plugin, app,
-                                                      cancellable,
-                                                      &error_local)) {
-                               g_warning ("Failed to get reviews: %s",
-                                          error_local->message);
-                       }
-               }
+               if (gs_app_get_reviews(app)->len > 0)
+                       return TRUE;
+               if (!gs_plugin_refine_reviews (plugin, app,
+                                              cancellable, error))
+                       return FALSE;
        }
 
        /* add ratings if possible */
        if (flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEW_RATINGS) {
-               for (l = *list; l != NULL; l = l->next) {
-                       g_autoptr(GError) error_local = NULL;
-                       app = GS_APP (l->data);
-                       if (gs_app_get_review_ratings(app) != NULL)
-                               continue;
-                       if (gs_app_get_id_no_prefix (app) == NULL)
-                               continue;
-                       if (gs_app_get_kind (app) == AS_APP_KIND_ADDON)
-                               continue;
-                       if (!gs_plugin_refine_ratings (plugin, app,
-                                                      cancellable,
-                                                      &error_local)) {
-                               g_warning ("Failed to get ratings: %s",
-                                          error_local->message);
-                       }
-               }
+               if (gs_app_get_review_ratings(app) != NULL)
+                       return TRUE;
+               if (!gs_plugin_refine_ratings (plugin, app,
+                                              cancellable, error))
+                       return FALSE;
        }
 
        return TRUE;
 }
 
 /**
- * xdg_app_review_sanitize_version:
+ * gs_plugin_odrs_sanitize_version:
  */
 static gchar *
-xdg_app_review_sanitize_version (const gchar *version)
+gs_plugin_odrs_sanitize_version (const gchar *version)
 {
        gchar *tmp = g_strdup (version);
        if (tmp == NULL)
@@ -725,10 +700,10 @@ xdg_app_review_sanitize_version (const gchar *version)
 }
 
 /**
- * gs_plugin_xdg_app_reviews_invalidate_cache:
+ * gs_plugin_odrs_invalidate_cache:
  */
 static gboolean
-gs_plugin_xdg_app_reviews_invalidate_cache (GsReview *review, GError **error)
+gs_plugin_odrs_invalidate_cache (GsReview *review, GError **error)
 {
        g_autofree gchar *cachedir = NULL;
        g_autofree gchar *cachefn = NULL;
@@ -768,7 +743,7 @@ gs_plugin_review_submit (GsPlugin *plugin,
        gs_review_set_reviewer (review, g_get_real_name ());
        gs_review_add_metadata (review, "app_id", gs_app_get_id_no_prefix (app));
        gs_review_add_metadata (review, "user_skey",
-                               gs_app_get_metadata_item (app, "XdgAppReviews::user_skey"));
+                               gs_app_get_metadata_item (app, "ODRS::user_skey"));
 
        /* create object with review data */
        builder = json_builder_new ();
@@ -786,7 +761,7 @@ gs_plugin_review_submit (GsPlugin *plugin,
        json_builder_set_member_name (builder, "distro");
        json_builder_add_string_value (builder, plugin->priv->distro);
        json_builder_set_member_name (builder, "version");
-       version = xdg_app_review_sanitize_version (gs_review_get_version (review));
+       version = gs_plugin_odrs_sanitize_version (gs_review_get_version (review));
        json_builder_add_string_value (builder, version);
        json_builder_set_member_name (builder, "user_display");
        json_builder_add_string_value (builder, gs_review_get_reviewer (review));
@@ -806,21 +781,21 @@ gs_plugin_review_submit (GsPlugin *plugin,
        data = json_generator_to_data (json_generator, NULL);
 
        /* clear cache */
-       if (!gs_plugin_xdg_app_reviews_invalidate_cache (review, error))
+       if (!gs_plugin_odrs_invalidate_cache (review, error))
                return FALSE;
 
        /* POST */
        uri = g_strdup_printf ("%s/submit", plugin->priv->review_server);
-       return gs_plugin_xdg_app_reviews_json_post (plugin->soup_session,
+       return gs_plugin_odrs_json_post (plugin->soup_session,
                                                    uri, data, error);
 }
 
 /**
- * gs_plugin_xdg_app_reviews_vote:
+ * gs_plugin_odrs_vote:
  */
 static gboolean
-gs_plugin_xdg_app_reviews_vote (GsPlugin *plugin, GsReview *review,
-                               const gchar *uri, GError **error)
+gs_plugin_odrs_vote (GsPlugin *plugin, GsReview *review,
+                    const gchar *uri, GError **error)
 {
        const gchar *tmp;
        g_autofree gchar *data = NULL;
@@ -859,11 +834,11 @@ gs_plugin_xdg_app_reviews_vote (GsPlugin *plugin, GsReview *review,
                return FALSE;
 
        /* clear cache */
-       if (!gs_plugin_xdg_app_reviews_invalidate_cache (review, error))
+       if (!gs_plugin_odrs_invalidate_cache (review, error))
                return FALSE;
 
        /* send to server */
-       if (!gs_plugin_xdg_app_reviews_json_post (plugin->soup_session,
+       if (!gs_plugin_odrs_json_post (plugin->soup_session,
                                                  uri, data, error))
                return FALSE;
 
@@ -886,7 +861,7 @@ gs_plugin_review_report (GsPlugin *plugin,
 {
        g_autofree gchar *uri = NULL;
        uri = g_strdup_printf ("%s/report", plugin->priv->review_server);
-       return gs_plugin_xdg_app_reviews_vote (plugin, review, uri, error);
+       return gs_plugin_odrs_vote (plugin, review, uri, error);
 }
 
 /**
@@ -901,7 +876,7 @@ gs_plugin_review_upvote (GsPlugin *plugin,
 {
        g_autofree gchar *uri = NULL;
        uri = g_strdup_printf ("%s/upvote", plugin->priv->review_server);
-       return gs_plugin_xdg_app_reviews_vote (plugin, review, uri, error);
+       return gs_plugin_odrs_vote (plugin, review, uri, error);
 }
 
 /**
@@ -916,7 +891,7 @@ gs_plugin_review_downvote (GsPlugin *plugin,
 {
        g_autofree gchar *uri = NULL;
        uri = g_strdup_printf ("%s/downvote", plugin->priv->review_server);
-       return gs_plugin_xdg_app_reviews_vote (plugin, review, uri, error);
+       return gs_plugin_odrs_vote (plugin, review, uri, error);
 }
 
 /**
@@ -931,7 +906,7 @@ gs_plugin_review_dismiss (GsPlugin *plugin,
 {
        g_autofree gchar *uri = NULL;
        uri = g_strdup_printf ("%s/dismiss", plugin->priv->review_server);
-       return gs_plugin_xdg_app_reviews_vote (plugin, review, uri, error);
+       return gs_plugin_odrs_vote (plugin, review, uri, error);
 }
 
 /**
@@ -946,7 +921,7 @@ gs_plugin_review_remove (GsPlugin *plugin,
 {
        g_autofree gchar *uri = NULL;
        uri = g_strdup_printf ("%s/remove", plugin->priv->review_server);
-       return gs_plugin_xdg_app_reviews_vote (plugin, review, uri, error);
+       return gs_plugin_odrs_vote (plugin, review, uri, error);
 }
 
 /**
@@ -975,13 +950,11 @@ gs_plugin_add_unvoted_reviews (GsPlugin *plugin,
                               GCancellable *cancellable,
                               GError **error)
 {
-       const gchar *app_id_last = NULL;
        guint status_code;
        guint i;
        g_autofree gchar *uri = NULL;
-       g_autoptr(GFile) cachefn_file = NULL;
+       g_autoptr(GHashTable) hash = NULL;
        g_autoptr(GPtrArray) reviews = NULL;
-       g_autoptr(GsApp) app_current = NULL;
        g_autoptr(SoupMessage) msg = NULL;
 
        /* create the GET data *with* the machine hash so we can later
@@ -992,7 +965,7 @@ gs_plugin_add_unvoted_reviews (GsPlugin *plugin,
        msg = soup_message_new (SOUP_METHOD_GET, uri);
        status_code = soup_session_send_message (plugin->soup_session, msg);
        if (status_code != SOUP_STATUS_OK) {
-               if (!xdg_app_review_parse_success (msg->response_body->data,
+               if (!gs_plugin_odrs_parse_success (msg->response_body->data,
                                                   msg->response_body->length,
                                                   error))
                        return FALSE;
@@ -1003,28 +976,31 @@ gs_plugin_add_unvoted_reviews (GsPlugin *plugin,
                                     "status code invalid");
                return FALSE;
        }
-       g_debug ("xdg-app-review returned: %s", msg->response_body->data);
-       reviews = xdg_app_review_parse_reviews (msg->response_body->data,
+       g_debug ("odrs returned: %s", msg->response_body->data);
+       reviews = gs_plugin_odrs_parse_reviews (msg->response_body->data,
                                                msg->response_body->length,
                                                error);
        if (reviews == NULL)
                return FALSE;
 
        /* look at all the reviews; faking application objects */
+       hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                     g_free, (GDestroyNotify) g_object_unref);
        for (i = 0; i < reviews->len; i++) {
+               GsApp *app;
                GsReview *review;
                const gchar *app_id;
 
                /* same app? */
                review = g_ptr_array_index (reviews, i);
                app_id = gs_review_get_metadata_item (review, "app_id");
-               if (g_strcmp0 (app_id, app_id_last) != 0) {
-                       g_clear_object (&app_current);
-                       app_current = gs_plugin_create_app_dummy (app_id);
-                       gs_plugin_add_app (list, app_current);
-                       app_id_last = app_id;
+               app = g_hash_table_lookup (hash, app_id);
+               if (app == NULL) {
+                       app = gs_plugin_create_app_dummy (app_id);
+                       gs_plugin_add_app (list, app);
+                       g_hash_table_insert (hash, g_strdup (app_id), app);
                }
-               gs_app_add_review (app_current, review);
+               gs_app_add_review (app, review);
        }
 
        return TRUE;
diff --git a/src/plugins/gs-plugin-packagekit-history.c b/src/plugins/gs-plugin-packagekit-history.c
index fc545ac..2e37c9e 100644
--- a/src/plugins/gs-plugin-packagekit-history.c
+++ b/src/plugins/gs-plugin-packagekit-history.c
@@ -34,7 +34,6 @@
  */
 
 struct GsPluginPrivate {
-       gsize                    loaded;
        GDBusConnection         *connection;
 };
 
@@ -133,10 +132,10 @@ gs_plugin_packagekit_refine_add_history (GsApp *app, GVariant *dict)
 }
 
 /**
- * gs_plugin_load:
+ * gs_plugin_setup:
  */
-static gboolean
-gs_plugin_load (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+gboolean
+gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
 {
        plugin->priv->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
                                                   cancellable,
@@ -161,14 +160,6 @@ gs_plugin_packagekit_refine (GsPlugin *plugin,
        g_autoptr(GVariant) result = NULL;
        g_autoptr(GVariant) tuple = NULL;
 
-       /* already loaded */
-       if (g_once_init_enter (&plugin->priv->loaded)) {
-               ret = gs_plugin_load (plugin, cancellable, error);
-               g_once_init_leave (&plugin->priv->loaded, TRUE);
-               if (!ret)
-                       return FALSE;
-       }
-
        /* get an array of package names */
        package_names = g_new0 (const gchar *, g_list_length (list) + 1);
        for (l = list; l != NULL; l = l->next) {
diff --git a/src/plugins/gs-plugin-packagekit-offline.c b/src/plugins/gs-plugin-packagekit-offline.c
index ea5c62d..dc46087 100644
--- a/src/plugins/gs-plugin-packagekit-offline.c
+++ b/src/plugins/gs-plugin-packagekit-offline.c
@@ -193,7 +193,7 @@ gs_plugin_add_updates_historical (GsPlugin *plugin,
                split = g_strsplit (package_ids[i], ";", 4);
                gs_app_add_source (app, split[0]);
                gs_app_set_update_version (app, split[1]);
-               gs_app_set_management_plugin (app, "PackageKit");
+               gs_app_set_management_plugin (app, "packagekit");
                gs_app_add_source_id (app, package_ids[i]);
                gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
                gs_app_set_kind (app, AS_APP_KIND_GENERIC);
diff --git a/src/plugins/gs-plugin-packagekit-origin.c b/src/plugins/gs-plugin-packagekit-origin.c
index f685083..1b5cfa5 100644
--- a/src/plugins/gs-plugin-packagekit-origin.c
+++ b/src/plugins/gs-plugin-packagekit-origin.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2013-2014 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -114,8 +114,10 @@ gs_plugin_packagekit_origin_ensure_sources (GsPlugin *plugin,
                                           cancellable,
                                           NULL, plugin,
                                           error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
        array = pk_results_get_repo_detail_array (results);
        for (i = 0; i < array->len; i++) {
                rd = g_ptr_array_index (array, i);
@@ -127,18 +129,23 @@ gs_plugin_packagekit_origin_ensure_sources (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_packagekit_origin_refine_app:
- **/
-static gboolean
-gs_plugin_packagekit_origin_refine_app (GsPlugin *plugin,
-                                       GsApp *app,
-                                       GCancellable *cancellable,
-                                       GError **error)
+ * gs_plugin_refine_app:
+ */
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
 {
        const gchar *origin_id;
        const gchar *origin_ui;
 
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "PackageKit") != 0)
+       /* only run when required */
+       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN) == 0)
+               return TRUE;
+
+       if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
                return TRUE;
        if (gs_app_get_origin (app) == NULL)
                return TRUE;
@@ -168,31 +175,3 @@ gs_plugin_packagekit_origin_refine_app (GsPlugin *plugin,
                gs_app_set_origin_ui (app, origin_ui);
        return TRUE;
 }
-
-/**
- * gs_plugin_refine:
- */
-gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
-{
-       GList *l;
-       GsApp *app;
-
-       /* only run when required */
-       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN) == 0)
-               return TRUE;
-
-       /* for each app */
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               if (!gs_plugin_packagekit_origin_refine_app (plugin, app,
-                                                            cancellable,
-                                                            error))
-                       return FALSE;
-       }
-       return TRUE;
-}
diff --git a/src/plugins/gs-plugin-packagekit-proxy.c b/src/plugins/gs-plugin-packagekit-proxy.c
index 8959b03..466880c 100644
--- a/src/plugins/gs-plugin-packagekit-proxy.c
+++ b/src/plugins/gs-plugin-packagekit-proxy.c
@@ -37,7 +37,6 @@
 
 struct GsPluginPrivate {
        PkControl               *control;
-       GCancellable            *cancellable;
        GSettings               *settings;
        GSettings               *settings_http;
        GSettings               *settings_ftp;
@@ -132,7 +131,7 @@ set_proxy_cb (GObject *object, GAsyncResult *res, gpointer user_data)
 }
 
 static void
-reload_proxy_settings (GsPlugin *plugin)
+reload_proxy_settings (GsPlugin *plugin, GCancellable *cancellable)
 {
        g_autofree gchar *proxy_http = NULL;
        g_autofree gchar *proxy_ftp = NULL;
@@ -158,12 +157,25 @@ reload_proxy_settings (GsPlugin *plugin)
        pk_control_set_proxy_async (plugin->priv->control,
                                    proxy_http,
                                    proxy_ftp,
-                                   plugin->priv->cancellable,
+                                   cancellable,
                                    set_proxy_cb,
                                    plugin);
 }
 
 /**
+ * gs_plugin_packagekit_proxy_changed_cb:
+ */
+static void
+gs_plugin_packagekit_proxy_changed_cb (GSettings *settings,
+                                      const gchar *key,
+                                      GsPlugin *plugin)
+{
+       if (!plugin->enabled)
+               return;
+       reload_proxy_settings (plugin, NULL);
+}
+
+/**
  * gs_plugin_initialize:
  */
 void
@@ -171,18 +183,26 @@ gs_plugin_initialize (GsPlugin *plugin)
 {
        /* create private area */
        plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
-       plugin->priv->cancellable = g_cancellable_new ();
        plugin->priv->control = pk_control_new ();
        plugin->priv->settings = g_settings_new ("org.gnome.system.proxy");
-       g_signal_connect_swapped (plugin->priv->settings, "changed",
-                                 G_CALLBACK (reload_proxy_settings), plugin);
+       g_signal_connect (plugin->priv->settings, "changed",
+                         G_CALLBACK (gs_plugin_packagekit_proxy_changed_cb), plugin);
        plugin->priv->settings_http = g_settings_new ("org.gnome.system.proxy.http");
-       g_signal_connect_swapped (plugin->priv->settings_http, "changed",
-                                 G_CALLBACK (reload_proxy_settings), plugin);
+       g_signal_connect (plugin->priv->settings_http, "changed",
+                         G_CALLBACK (gs_plugin_packagekit_proxy_changed_cb), plugin);
        plugin->priv->settings_ftp = g_settings_new ("org.gnome.system.proxy.ftp");
-       g_signal_connect_swapped (plugin->priv->settings_ftp, "changed",
-                                 G_CALLBACK (reload_proxy_settings), plugin);
-       reload_proxy_settings (plugin);
+       g_signal_connect (plugin->priv->settings_ftp, "changed",
+                         G_CALLBACK (gs_plugin_packagekit_proxy_changed_cb), plugin);
+}
+
+/**
+ * gs_plugin_setup:
+ */
+gboolean
+gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+{
+       reload_proxy_settings (plugin, cancellable);
+       return TRUE;
 }
 
 /**
@@ -191,11 +211,6 @@ gs_plugin_initialize (GsPlugin *plugin)
 void
 gs_plugin_destroy (GsPlugin *plugin)
 {
-       if (plugin->priv->cancellable != NULL) {
-               g_cancellable_cancel (plugin->priv->cancellable);
-               g_object_unref (plugin->priv->cancellable);
-       }
-
        g_object_unref (plugin->priv->control);
        g_object_unref (plugin->priv->settings);
        g_object_unref (plugin->priv->settings_http);
diff --git a/src/plugins/gs-plugin-packagekit-refine.c b/src/plugins/gs-plugin-packagekit-refine.c
index a838875..11b67b0 100644
--- a/src/plugins/gs-plugin-packagekit-refine.c
+++ b/src/plugins/gs-plugin-packagekit-refine.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2013-2014 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -28,6 +28,7 @@
 #include <gs-utils.h>
 #include <glib/gi18n.h>
 
+#include "gs-markdown.h"
 #include "packagekit-common.h"
 
 /*
@@ -155,7 +156,7 @@ gs_plugin_packagekit_set_metadata_from_package (GsPlugin *plugin,
 {
        const gchar *data;
 
-       gs_app_set_management_plugin (app, "PackageKit");
+       gs_app_set_management_plugin (app, "packagekit");
        gs_app_add_source (app, pk_package_get_name (package));
        gs_app_add_source_id (app, pk_package_get_id (package));
        switch (pk_package_get_info (package)) {
@@ -295,8 +296,10 @@ gs_plugin_packagekit_resolve_packages (GsPlugin *plugin,
                                     cancellable,
                                     gs_plugin_packagekit_progress_cb, &data,
                                     error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
 
        /* check error code */
        error_code = pk_results_get_error_code (results);
@@ -314,7 +317,7 @@ gs_plugin_packagekit_resolve_packages (GsPlugin *plugin,
        packages = pk_results_get_package_array (results);
        for (l = list; l != NULL; l = l->next) {
                app = GS_APP (l->data);
-               if (gs_app_get_local_file (app) != NULL)
+               if (gs_app_get_metadata_item (app, "packagekit::local-filename") != NULL)
                        continue;
                gs_plugin_packagekit_resolve_packages_app (plugin, packages, app);
        }
@@ -345,8 +348,10 @@ gs_plugin_packagekit_refine_from_desktop (GsPlugin *plugin,
                                          cancellable,
                                          gs_plugin_packagekit_progress_cb, &data,
                                          error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
 
        /* check error code */
        error_code = pk_results_get_error_code (results);
@@ -374,6 +379,33 @@ gs_plugin_packagekit_refine_from_desktop (GsPlugin *plugin,
 }
 
 /**
+ * gs_plugin_packagekit_fixup_update_description:
+ *
+ * Lets assume Fedora is sending us valid markdown, but fall back to
+ * plain text if this fails.
+ */
+static gchar *
+gs_plugin_packagekit_fixup_update_description (const gchar *text)
+{
+       gchar *tmp;
+       g_autoptr(GsMarkdown) markdown = NULL;
+
+       /* nothing to do */
+       if (text == NULL)
+               return NULL;
+
+       /* try to parse */
+       markdown = gs_markdown_new (GS_MARKDOWN_OUTPUT_TEXT);
+       gs_markdown_set_smart_quoting (markdown, FALSE);
+       gs_markdown_set_autocode (markdown, FALSE);
+       gs_markdown_set_autolinkify (markdown, FALSE);
+       tmp = gs_markdown_parse (markdown, text);
+       if (tmp != NULL)
+               return tmp;
+       return g_strdup (text);
+}
+
+/**
  * gs_plugin_packagekit_refine_updatedetails:
  */
 static gboolean
@@ -411,8 +443,10 @@ gs_plugin_packagekit_refine_updatedetails (GsPlugin *plugin,
                                               cancellable,
                                               gs_plugin_packagekit_progress_cb, &data,
                                               error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
 
        /* set the update details for the update */
        array = pk_results_get_update_detail_array (results);
@@ -420,11 +454,16 @@ gs_plugin_packagekit_refine_updatedetails (GsPlugin *plugin,
                app = GS_APP (l->data);
                package_id = gs_app_get_source_id_default (app);
                for (i = 0; i < array->len; i++) {
+                       const gchar *tmp;
+                       g_autofree gchar *desc = NULL;
                        /* right package? */
                        update_detail = g_ptr_array_index (array, i);
                        if (g_strcmp0 (package_id, pk_update_detail_get_package_id (update_detail)) != 0)
                                continue;
-                       gs_app_set_update_details (app, pk_update_detail_get_update_text (update_detail));
+                       tmp = pk_update_detail_get_update_text (update_detail);
+                       desc = gs_plugin_packagekit_fixup_update_description (tmp);
+                       if (desc != NULL)
+                               gs_app_set_update_details (app, desc);
                        break;
                }
        }
@@ -544,8 +583,10 @@ gs_plugin_packagekit_refine_details (GsPlugin *plugin,
                                         cancellable,
                                         gs_plugin_packagekit_progress_cb, &data,
                                         error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
 
        /* set the update details for the update */
        array = pk_results_get_details_array (results);
@@ -584,8 +625,10 @@ gs_plugin_packagekit_refine_update_urgency (GsPlugin *plugin,
                                         cancellable,
                                         gs_plugin_packagekit_progress_cb, &data,
                                         error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
 
        /* set the update severity for the app */
        sack = pk_results_get_package_sack (results);
@@ -630,7 +673,7 @@ gs_plugin_packagekit_refine_update_urgency (GsPlugin *plugin,
 static gboolean
 gs_plugin_refine_app_needs_details (GsPlugin *plugin, GsPluginRefineFlags flags, GsApp *app)
 {
-       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE) > 0 &&
+       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE) > 0 &&
            gs_app_get_license (app) == NULL)
                return TRUE;
        if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL) > 0 &&
@@ -658,12 +701,12 @@ gs_plugin_refine_require_details (GsPlugin *plugin,
        g_autoptr(GList) list_tmp = NULL;
        g_autoptr(AsProfileTask) ptask = NULL;
 
-       ptask = as_profile_start_literal (plugin->profile, "packagekit-refine[source->licence]");
+       ptask = as_profile_start_literal (plugin->profile, "packagekit-refine[source->license]");
        for (l = list; l != NULL; l = l->next) {
                app = GS_APP (l->data);
                if (gs_app_get_kind (app) == AS_APP_KIND_WEB_APP)
                        continue;
-               if (g_strcmp0 (gs_app_get_management_plugin (app), "PackageKit") != 0)
+               if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
                        continue;
                if (gs_app_get_source_id_default (app) == NULL)
                        continue;
@@ -735,7 +778,7 @@ gs_plugin_refine_requires_package_id (GsApp *app, GsPluginRefineFlags flags)
                return FALSE;
        if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION) > 0)
                return TRUE;
-       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE) > 0)
+       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE) > 0)
                return TRUE;
        if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL) > 0)
                return TRUE;
@@ -779,8 +822,10 @@ gs_plugin_packagekit_refine_distro_upgrade (GsPlugin *plugin,
                                            cancellable,
                                            gs_plugin_packagekit_progress_cb, &data,
                                            error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
        if (!gs_plugin_packagekit_add_results (plugin, &list, results, error))
                return FALSE;
 
@@ -835,7 +880,7 @@ gs_plugin_refine (GsPlugin *plugin,
                app = GS_APP (l->data);
                if (gs_app_get_kind (app) == AS_APP_KIND_WEB_APP)
                        continue;
-               if (g_strcmp0 (gs_app_get_management_plugin (app), "PackageKit") != 0)
+               if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
                        continue;
                sources = gs_app_get_sources (app);
                if (sources->len == 0)
@@ -903,7 +948,7 @@ gs_plugin_refine (GsPlugin *plugin,
                app = GS_APP (l->data);
                if (gs_app_get_state (app) != AS_APP_STATE_UPDATABLE)
                        continue;
-               if (g_strcmp0 (gs_app_get_management_plugin (app), "PackageKit") != 0)
+               if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
                        continue;
                if (gs_plugin_refine_requires_update_details (app, flags))
                        updatedetails_all = g_list_prepend (updatedetails_all, app);
diff --git a/src/plugins/gs-plugin-packagekit-refresh.c b/src/plugins/gs-plugin-packagekit-refresh.c
index d027d25..ec272f8 100644
--- a/src/plugins/gs-plugin-packagekit-refresh.c
+++ b/src/plugins/gs-plugin-packagekit-refresh.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2014 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2014-2016 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -50,17 +50,6 @@ gs_plugin_get_name (void)
 }
 
 /**
- * gs_plugin_get_conflicts:
- */
-const gchar **
-gs_plugin_get_conflicts (GsPlugin *plugin)
-{
-       static const gchar *deps[] = {
-               NULL };
-       return deps;
-}
-
-/**
  * gs_plugin_initialize:
  */
 void
@@ -128,16 +117,11 @@ gs_plugin_refresh (GsPlugin *plugin,
                   GCancellable *cancellable,
                   GError **error)
 {
-       PkBitfield filter;
-       PkBitfield transaction_flags;
        ProgressData data;
-       g_auto(GStrv) package_ids = NULL;
-       g_autoptr(PkPackageSack) sack = NULL;
-       g_autoptr(PkResults) results2 = NULL;
        g_autoptr(PkResults) results = NULL;
 
-       /* not us */
-       if ((flags & GS_PLUGIN_REFRESH_FLAGS_UPDATES) == 0)
+       /* nothing to re-generate */
+       if (flags == 0)
                return TRUE;
 
        /* cache age of 0 is user-initiated */
@@ -146,33 +130,51 @@ gs_plugin_refresh (GsPlugin *plugin,
        data.plugin = plugin;
        data.ptask = NULL;
 
-       /* update UI as this might take some time */
-       gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING);
-
-       /* do sync call */
-       filter = pk_bitfield_value (PK_FILTER_ENUM_NONE);
-       pk_client_set_cache_age (PK_CLIENT (plugin->priv->task), cache_age);
-       results = pk_client_get_updates (PK_CLIENT (plugin->priv->task),
-                                        filter,
-                                        cancellable,
-                                        gs_plugin_packagekit_progress_cb, &data,
-                                        error);
-       if (results == NULL)
-               return FALSE;
+       /* refresh the metadata */
+       if (flags & GS_PLUGIN_REFRESH_FLAGS_METADATA ||
+           flags & GS_PLUGIN_REFRESH_FLAGS_PAYLOAD) {
+               PkBitfield filter;
+
+               filter = pk_bitfield_value (PK_FILTER_ENUM_NONE);
+               pk_client_set_cache_age (PK_CLIENT (plugin->priv->task), cache_age);
+               gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING);
+               results = pk_client_get_updates (PK_CLIENT (plugin->priv->task),
+                                                filter,
+                                                cancellable,
+                                                gs_plugin_packagekit_progress_cb, &data,
+                                                error);
+               if (results == NULL) {
+                       gs_plugin_packagekit_convert_gerror (error);
+                       return FALSE;
+               }
+       }
 
-       /* download all the updates */
-       sack = pk_results_get_package_sack (results);
-       if (pk_package_sack_get_size (sack) == 0)
-               return TRUE;
-       package_ids = pk_package_sack_get_ids (sack);
-       transaction_flags = pk_bitfield_value (PK_TRANSACTION_FLAG_ENUM_ONLY_DOWNLOAD);
-       results2 = pk_client_update_packages (PK_CLIENT (plugin->priv->task),
-                                             transaction_flags,
-                                             package_ids,
-                                             cancellable,
-                                             gs_plugin_packagekit_progress_cb, &data,
-                                             error);
-       return results2 != NULL;
+       /* download all the packages themselves */
+       if (flags & GS_PLUGIN_REFRESH_FLAGS_PAYLOAD) {
+               PkBitfield transaction_flags;
+               g_auto(GStrv) package_ids = NULL;
+               g_autoptr(PkPackageSack) sack = NULL;
+               g_autoptr(PkResults) results2 = NULL;
+
+               sack = pk_results_get_package_sack (results);
+               if (pk_package_sack_get_size (sack) == 0)
+                       return TRUE;
+               package_ids = pk_package_sack_get_ids (sack);
+               transaction_flags = pk_bitfield_value (PK_TRANSACTION_FLAG_ENUM_ONLY_DOWNLOAD);
+               gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING);
+               results2 = pk_client_update_packages (PK_CLIENT (plugin->priv->task),
+                                                     transaction_flags,
+                                                     package_ids,
+                                                     cancellable,
+                                                     gs_plugin_packagekit_progress_cb, &data,
+                                                     error);
+               if (results2 == NULL) {
+                       gs_plugin_packagekit_convert_gerror (error);
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
 }
 
 /**
@@ -237,8 +239,10 @@ gs_plugin_packagekit_refresh_guess_app_id (GsPlugin *plugin,
                                             cancellable,
                                             gs_plugin_packagekit_progress_cb, &data,
                                             error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
        array = pk_results_get_files_array (results);
        if (array->len == 0) {
                g_set_error (error,
@@ -286,7 +290,6 @@ gs_plugin_file_to_app (GsPlugin *plugin,
        g_autoptr (PkResults) results = NULL;
        g_autofree gchar *basename = NULL;
        g_autofree gchar *content_type = NULL;
-       g_autofree gchar *filename = NULL;
        g_autofree gchar *license_spdx = NULL;
        g_auto(GStrv) files = NULL;
        g_auto(GStrv) split = NULL;
@@ -310,7 +313,6 @@ gs_plugin_file_to_app (GsPlugin *plugin,
        data.ptask = NULL;
 
        /* get details */
-       filename = g_file_get_path (file);
        files = g_strsplit (filename, "\t", -1);
        pk_client_set_cache_age (PK_CLIENT (plugin->priv->task), G_MAXUINT);
        results = pk_client_get_details_local (PK_CLIENT (plugin->priv->task),
@@ -318,8 +320,10 @@ gs_plugin_file_to_app (GsPlugin *plugin,
                                               cancellable,
                                               gs_plugin_packagekit_progress_cb, &data,
                                               error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
 
        /* get results */
        array = pk_results_get_details_array (results);
@@ -345,7 +349,7 @@ gs_plugin_file_to_app (GsPlugin *plugin,
        package_id = pk_details_get_package_id (item);
        split = pk_package_id_split (package_id);
        basename = g_path_get_basename (filename);
-       gs_app_set_management_plugin (app, "PackageKit");
+       gs_app_set_management_plugin (app, "packagekit");
        gs_app_set_kind (app, AS_APP_KIND_GENERIC);
        gs_app_set_state (app, AS_APP_STATE_AVAILABLE_LOCAL);
        if (pk_details_get_summary (item))
@@ -354,6 +358,7 @@ gs_plugin_file_to_app (GsPlugin *plugin,
        else
                gs_app_set_name (app, GS_APP_QUALITY_LOWEST, split[PK_PACKAGE_ID_NAME]);
        gs_app_set_version (app, split[PK_PACKAGE_ID_VERSION]);
+       gs_app_set_metadata (app, "packagekit::local-filename", g_file_get_path (file));
        gs_app_set_origin (app, basename);
        gs_app_add_source (app, split[PK_PACKAGE_ID_NAME]);
        gs_app_add_source_id (app, package_id);
diff --git a/src/plugins/gs-plugin-packagekit.c b/src/plugins/gs-plugin-packagekit.c
index 2ce848d..db2c0b1 100644
--- a/src/plugins/gs-plugin-packagekit.c
+++ b/src/plugins/gs-plugin-packagekit.c
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -152,8 +152,10 @@ gs_plugin_add_installed (GsPlugin *plugin,
                                          cancellable,
                                          gs_plugin_packagekit_progress_cb, &data,
                                          error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
 
        /* add results */
        return gs_plugin_packagekit_add_results (plugin, list, results, error);
@@ -195,6 +197,7 @@ gs_plugin_add_sources_related (GsPlugin *plugin,
                                           gs_plugin_packagekit_progress_cb, &data,
                                           error);
        if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                ret = FALSE;
                goto out;
        }
@@ -255,8 +258,10 @@ gs_plugin_add_sources (GsPlugin *plugin,
                                           cancellable,
                                           gs_plugin_packagekit_progress_cb, &data,
                                           error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
        array = pk_results_get_repo_detail_array (results);
        for (i = 0; i < array->len; i++) {
@@ -264,7 +269,7 @@ gs_plugin_add_sources (GsPlugin *plugin,
                rd = g_ptr_array_index (array, i);
                id = pk_repo_detail_get_id (rd);
                app = gs_app_new (id);
-               gs_app_set_management_plugin (app, "PackageKit");
+               gs_app_set_management_plugin (app, plugin->name);
                gs_app_set_kind (app, AS_APP_KIND_SOURCE);
                gs_app_set_state (app, AS_APP_STATE_INSTALLED);
                gs_app_set_name (app,
@@ -308,7 +313,11 @@ gs_plugin_app_source_enable (GsPlugin *plugin,
                                         cancellable,
                                         gs_plugin_packagekit_progress_cb, &data,
                                         error);
-       return results != NULL;
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
+               return FALSE;
+       }
+       return TRUE;
 }
 
 /**
@@ -326,17 +335,16 @@ gs_plugin_app_install (GsPlugin *plugin,
        const gchar *package_id;
        guint i, j;
        g_autoptr(PkError) error_code = NULL;
-       g_autofree gchar *local_filename = NULL;
-       g_auto(GStrv) package_ids = NULL;
-       g_autoptr(GPtrArray) array_package_ids = NULL;
        g_autoptr(PkResults) results = NULL;
+       g_autoptr(GPtrArray) array_package_ids = NULL;
+       g_auto(GStrv) package_ids = NULL;
 
        data.app = app;
        data.plugin = plugin;
        data.ptask = NULL;
 
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "PackageKit") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
        /* we enable the repo */
@@ -365,13 +373,16 @@ gs_plugin_app_install (GsPlugin *plugin,
                                                         gs_plugin_packagekit_progress_cb, &data,
                                                         error);
                if (results == NULL) {
-                       gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+                       gs_plugin_packagekit_convert_gerror (error);
+                       gs_app_set_state_recover (app);
                        return FALSE;
                }
 
+               /* state is known */
+               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+
                /* no longer valid */
                gs_app_clear_source_ids (app);
-               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
                return TRUE;
        }
 
@@ -431,30 +442,43 @@ gs_plugin_app_install (GsPlugin *plugin,
                                                         cancellable,
                                                         gs_plugin_packagekit_progress_cb, &data,
                                                         error);
-               if (results == NULL)
+               if (results == NULL) {
+                       gs_plugin_packagekit_convert_gerror (error);
+                       gs_app_set_state_recover (app);
                        return FALSE;
+               }
+
+               /* state is known */
+               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+
                break;
        case AS_APP_STATE_AVAILABLE_LOCAL:
-               if (gs_app_get_local_file (app) == NULL) {
+               package_id = gs_app_get_metadata_item (app, "packagekit::local-filename");
+               if (package_id == NULL) {
                        g_set_error_literal (error,
                                             GS_PLUGIN_ERROR,
                                             GS_PLUGIN_ERROR_NOT_SUPPORTED,
                                             "local package, but no filename");
                        return FALSE;
                }
-               local_filename = g_file_get_path (gs_app_get_local_file (app));
-               package_ids = g_strsplit (local_filename, "\t", -1);
+               package_ids = g_strsplit (package_id, "\t", -1);
                gs_app_set_state (app, AS_APP_STATE_INSTALLING);
                results = pk_task_install_files_sync (plugin->priv->task,
                                                      package_ids,
                                                      cancellable,
                                                      gs_plugin_packagekit_progress_cb, &data,
                                                      error);
-               if (results == NULL)
+               if (results == NULL) {
+                       gs_plugin_packagekit_convert_gerror (error);
+                       gs_app_set_state_recover (app);
                        return FALSE;
+               }
+
+               /* state is known */
+               gs_app_set_state (app, AS_APP_STATE_INSTALLED);
 
                /* get the new icon from the package */
-               gs_app_set_local_file (app, NULL);
+               gs_app_set_metadata (app, "packagekit::local-filename", NULL);
                gs_app_set_icon (app, NULL);
                gs_app_set_pixbuf (app, NULL);
                break;
@@ -508,7 +532,11 @@ gs_plugin_app_source_disable (GsPlugin *plugin,
                                         cancellable,
                                         gs_plugin_packagekit_progress_cb, &data,
                                         error);
-       return results != NULL;
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
+               return FALSE;
+       }
+       return TRUE;
 }
 
 /**
@@ -570,7 +598,7 @@ gs_plugin_app_remove (GsPlugin *plugin,
        data.ptask = NULL;
 
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "PackageKit") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
        /* remove repo and all apps in it */
@@ -611,8 +639,14 @@ gs_plugin_app_remove (GsPlugin *plugin,
                                                cancellable,
                                                gs_plugin_packagekit_progress_cb, &data,
                                                error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
+               gs_app_set_state_recover (app);
                return FALSE;
+       }
+
+       /* state is not known: we don't know if we can re-install this app */
+       gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
 
        /* no longer valid */
        gs_app_clear_source_ids (app);
@@ -643,6 +677,10 @@ gs_plugin_app_upgrade_download (GsPlugin *plugin,
        ProgressData data;
        g_autoptr(PkResults) results = NULL;
 
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
+               return TRUE;
+
        data.app = app;
        data.plugin = plugin;
        data.ptask = NULL;
@@ -666,7 +704,15 @@ gs_plugin_app_upgrade_download (GsPlugin *plugin,
                                            cancellable,
                                            gs_plugin_packagekit_progress_cb, &data,
                                            error);
-       return results != NULL;
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
+               gs_app_set_state_recover (app);
+               return FALSE;
+       }
+
+       /* state is known */
+       gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
+       return TRUE;
 }
 
 /**
@@ -698,8 +744,10 @@ gs_plugin_add_search_files (GsPlugin *plugin,
                                          cancellable,
                                          gs_plugin_packagekit_progress_cb, &data,
                                          error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
 
        /* add results */
        return gs_plugin_packagekit_add_results (plugin, list, results, error);
@@ -734,8 +782,10 @@ gs_plugin_add_search_what_provides (GsPlugin *plugin,
                                           cancellable,
                                           gs_plugin_packagekit_progress_cb, &data,
                                           error);
-       if (results == NULL)
+       if (results == NULL) {
+               gs_plugin_packagekit_convert_gerror (error);
                return FALSE;
+       }
 
        /* add results */
        return gs_plugin_packagekit_add_results (plugin, list, results, error);
@@ -751,7 +801,7 @@ gs_plugin_launch (GsPlugin *plugin,
                  GError **error)
 {
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "PackageKit") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
        return gs_plugin_app_launch (plugin, app, error);
 }
diff --git a/src/plugins/gs-plugin-provenance.c b/src/plugins/gs-plugin-provenance.c
index bb360d3..a692345 100644
--- a/src/plugins/gs-plugin-provenance.c
+++ b/src/plugins/gs-plugin-provenance.c
@@ -46,6 +46,21 @@ gs_plugin_get_name (void)
 }
 
 /**
+ * gs_plugin_provenance_get_sources:
+ */
+static gchar **
+gs_plugin_provenance_get_sources (GsPlugin *plugin)
+{
+       const gchar *tmp;
+       tmp = g_getenv ("GS_SELF_TEST_PROVENANCE_SOURCES");
+       if (tmp != NULL) {
+               g_debug ("using custom provenance sources of %s", tmp);
+               return g_strsplit (tmp, ",", -1);
+       }
+       return g_settings_get_strv (plugin->priv->settings, "official-sources");
+}
+
+/**
  * gs_plugin_provenance_settings_changed_cb:
  */
 static void
@@ -55,8 +70,7 @@ gs_plugin_provenance_settings_changed_cb (GSettings *settings,
 {
        if (g_strcmp0 (key, "official-sources") == 0) {
                g_strfreev (plugin->priv->sources);
-               plugin->priv->sources = g_settings_get_strv (plugin->priv->settings,
-                                                            "official-sources");
+               plugin->priv->sources = gs_plugin_provenance_get_sources (plugin);
        }
 }
 
@@ -70,8 +84,7 @@ gs_plugin_initialize (GsPlugin *plugin)
        plugin->priv->settings = g_settings_new ("org.gnome.software");
        g_signal_connect (plugin->priv->settings, "changed",
                          G_CALLBACK (gs_plugin_provenance_settings_changed_cb), plugin);
-       plugin->priv->sources = g_settings_get_strv (plugin->priv->settings,
-                                                  "official-sources");
+       plugin->priv->sources = gs_plugin_provenance_get_sources (plugin);
 }
 
 /**
@@ -118,20 +131,29 @@ gs_utils_strv_fnmatch (gchar **strv, const gchar *str)
 }
 
 /**
- * gs_plugin_provenance_refine_app:
+ * gs_plugin_refine_app:
  */
-static void
-gs_plugin_provenance_refine_app (GsPlugin *plugin, GsApp *app)
+gboolean
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
 {
        const gchar *origin;
        gchar **sources;
-       guint i;
+
+       /* not required */
+       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE) == 0)
+               return TRUE;
+       if (gs_app_has_quirk (app, AS_APP_QUIRK_PROVENANCE))
+               return TRUE;
 
        /* nothing to search */
        sources = plugin->priv->sources;
        if (sources == NULL || sources[0] == NULL) {
                gs_app_add_quirk (app, AS_APP_QUIRK_PROVENANCE);
-               return;
+               return TRUE;
        }
 
        /* simple case */
@@ -140,49 +162,21 @@ gs_plugin_provenance_refine_app (GsPlugin *plugin, GsApp *app)
        if (origin != NULL && gs_utils_strv_fnmatch (sources, origin)) {
                gs_app_add_quirk (app, AS_APP_QUIRK_PROVENANCE);
                g_debug ("prov: %s", gs_app_to_string (app));
-               return;
+               return TRUE;
        }
 
        /* this only works for packages */
        origin = gs_app_get_source_id_default (app);
        if (origin == NULL)
-               return;
+               return TRUE;
        origin = g_strrstr (origin, ";");
        if (origin == NULL)
-               return;
+               return TRUE;
        if (g_str_has_prefix (origin + 1, "installed:"))
                origin += 10;
-       for (i = 0; sources[i] != NULL; i++) {
-               if (gs_utils_strv_fnmatch (sources, origin + 1)) {
-                       gs_app_add_quirk (app, AS_APP_QUIRK_PROVENANCE);
-                       break;
-               }
-       }
-}
-
-/**
- * gs_plugin_refine:
- */
-gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
-{
-       GList *l;
-       GsApp *app;
-
-       /* not required */
-       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE) == 0)
+       if (gs_utils_strv_fnmatch (sources, origin + 1)) {
+               gs_app_add_quirk (app, AS_APP_QUIRK_PROVENANCE);
                return TRUE;
-
-       /* refine apps */
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               if (gs_app_has_quirk (app, AS_APP_QUIRK_PROVENANCE))
-                       continue;
-               gs_plugin_provenance_refine_app (plugin, app);
        }
        return TRUE;
 }
diff --git a/src/plugins/gs-plugin-systemd-updates.c b/src/plugins/gs-plugin-systemd-updates.c
index ab14388..e433ca2 100644
--- a/src/plugins/gs-plugin-systemd-updates.c
+++ b/src/plugins/gs-plugin-systemd-updates.c
@@ -35,7 +35,6 @@
 
 struct GsPluginPrivate {
        GFileMonitor            *monitor;
-       gsize                    done_init;
 };
 
 /**
@@ -80,10 +79,10 @@ gs_plugin_systemd_updates_changed_cb (GFileMonitor *monitor,
 }
 
 /**
- * gs_plugin_startup:
+ * gs_plugin_setup:
  */
-static gboolean
-gs_plugin_startup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+gboolean
+gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
 {
        plugin->priv->monitor = pk_offline_get_prepared_monitor (cancellable, error);
        if (plugin->priv->monitor == NULL)
@@ -103,19 +102,10 @@ gs_plugin_add_updates (GsPlugin *plugin,
                       GCancellable *cancellable,
                       GError **error)
 {
-       gboolean ret;
        guint i;
        g_autoptr(GError) error_local = NULL;
        g_auto(GStrv) package_ids = NULL;
 
-       /* watch the file in case it comes or goes */
-       if (g_once_init_enter (&plugin->priv->done_init)) {
-               ret = gs_plugin_startup (plugin, cancellable, error);
-               g_once_init_leave (&plugin->priv->done_init, TRUE);
-               if (!ret)
-                       return FALSE;
-       }
-
        /* get the id's if the file exists */
        package_ids = pk_offline_get_prepared_ids (&error_local);
        if (package_ids == NULL) {
@@ -137,12 +127,12 @@ gs_plugin_add_updates (GsPlugin *plugin,
                g_autoptr(GsApp) app = NULL;
                g_auto(GStrv) split = NULL;
                app = gs_app_new (NULL);
-               gs_app_set_management_plugin (app, "PackageKit");
+               gs_app_set_management_plugin (app, "packagekit");
                gs_app_add_source_id (app, package_ids[i]);
                split = pk_package_id_split (package_ids[i]);
                gs_app_add_source (app, split[PK_PACKAGE_ID_NAME]);
                gs_app_set_update_version (app, split[PK_PACKAGE_ID_VERSION]);
-               gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+               gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
                gs_app_set_kind (app, AS_APP_KIND_GENERIC);
                gs_plugin_add_app (list, app);
        }
@@ -150,36 +140,41 @@ gs_plugin_add_updates (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_update:
+ * gs_plugin_offline_update:
  */
 gboolean
-gs_plugin_update (GsPlugin *plugin,
-                 GList *apps,
-                 GCancellable *cancellable,
-                 GError **error)
+gs_plugin_offline_update (GsPlugin *plugin,
+                          GList *apps,
+                          GCancellable *cancellable,
+                          GError **error)
 {
        GList *l;
 
        /* any apps to process offline */
        for (l = apps; l != NULL; l = l->next) {
                GsApp *app = GS_APP (l->data);
-               if (gs_app_get_state (app) == AS_APP_STATE_UPDATABLE) {
-                       return pk_offline_trigger (PK_OFFLINE_ACTION_REBOOT,
-                                                  cancellable, error);
-               }
+
+               /* only process this app if was created by this plugin */
+               if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
+                       continue;
+               return pk_offline_trigger (PK_OFFLINE_ACTION_REBOOT,
+                                          cancellable, error);
        }
        return TRUE;
 }
 
 /**
- * gs_plugin_update_cancel:
+ * gs_plugin_offline_update_cancel:
  */
 gboolean
-gs_plugin_update_cancel (GsPlugin *plugin,
-                        GsApp *app,
-                        GCancellable *cancellable,
-                        GError **error)
+gs_plugin_offline_update_cancel (GsPlugin *plugin,
+                                GsApp *app,
+                                GCancellable *cancellable,
+                                GError **error)
 {
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
+               return TRUE;
        return pk_offline_cancel (NULL, error);
 }
 
@@ -192,5 +187,8 @@ gs_plugin_app_upgrade_trigger (GsPlugin *plugin,
                                GCancellable *cancellable,
                                GError **error)
 {
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
+               return TRUE;
        return pk_offline_trigger_upgrade (PK_OFFLINE_ACTION_REBOOT, cancellable, error);
 }
diff --git a/src/plugins/gs-plugin-ubuntu-reviews.c b/src/plugins/gs-plugin-ubuntu-reviews.c
index 27e92da..2086fe7 100644
--- a/src/plugins/gs-plugin-ubuntu-reviews.c
+++ b/src/plugins/gs-plugin-ubuntu-reviews.c
@@ -90,6 +90,7 @@ const gchar **
 gs_plugin_order_after (GsPlugin *plugin)
 {
        static const gchar *deps[] = {
+               "odrs",
                "appstream",
                NULL };
        return deps;
@@ -807,29 +808,22 @@ refine_reviews (GsPlugin *plugin, GsApp *app, GError **error)
 }
 
 gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
 {
-       GList *l;
-       gboolean ret = TRUE;
-
-       for (l = *list; l != NULL; l = l->next) {
-               GsApp *app = GS_APP (l->data);
-
-               if ((flags & (GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING | 
GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEW_RATINGS)) != 0) {
-                       if (!refine_rating (plugin, app, error))
-                               return FALSE;
-               }
-               if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEWS) != 0) {
-                       if (!refine_reviews (plugin, app, error))
-                               return FALSE;
-               }
+       if ((flags & (GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING | GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEW_RATINGS)) 
!= 0) {
+               if (!refine_rating (plugin, app, error))
+                       return FALSE;
+       }
+       if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEWS) != 0) {
+               if (!refine_reviews (plugin, app, error))
+                       return FALSE;
        }
 
-       return ret;
+       return TRUE;
 }
 
 static void
diff --git a/src/plugins/gs-plugin-xdg-app.c b/src/plugins/gs-plugin-xdg-app.c
index 94674a3..c95c221 100644
--- a/src/plugins/gs-plugin-xdg-app.c
+++ b/src/plugins/gs-plugin-xdg-app.c
@@ -21,8 +21,8 @@
 
 /* Notes:
  *
- * All GsApp's created have management-plugin set to XgdApp
- * Some GsApp's created have have XgdApp::kind of app or runtime
+ * All GsApp's created have management-plugin set to xdg-app
+ * Some GsApp's created have have xdg-app::kind of app or runtime
  * The GsApp:origin is the remote name, e.g. test-repo
  *
  * Some outstanding notes:
@@ -93,15 +93,15 @@ gs_plugin_destroy (GsPlugin *plugin)
 }
 
 /* helpers */
-#define gs_app_get_xdgapp_kind_as_str(app)     gs_app_get_metadata_item(app,"XgdApp::kind")
-#define gs_app_get_xdgapp_name(app)            gs_app_get_metadata_item(app,"XgdApp::name")
-#define gs_app_get_xdgapp_arch(app)            gs_app_get_metadata_item(app,"XgdApp::arch")
-#define gs_app_get_xdgapp_branch(app)          gs_app_get_metadata_item(app,"XgdApp::branch")
-#define gs_app_get_xdgapp_commit(app)          gs_app_get_metadata_item(app,"XgdApp::commit")
-#define gs_app_set_xdgapp_name(app,val)                gs_app_set_metadata(app,"XgdApp::name",val)
-#define gs_app_set_xdgapp_arch(app,val)                gs_app_set_metadata(app,"XgdApp::arch",val)
-#define gs_app_set_xdgapp_branch(app,val)      gs_app_set_metadata(app,"XgdApp::branch",val)
-#define gs_app_set_xdgapp_commit(app,val)      gs_app_set_metadata(app,"XgdApp::commit",val)
+#define gs_app_get_xdgapp_kind_as_str(app)     gs_app_get_metadata_item(app,"xdg-app::kind")
+#define gs_app_get_xdgapp_name(app)            gs_app_get_metadata_item(app,"xdg-app::name")
+#define gs_app_get_xdgapp_arch(app)            gs_app_get_metadata_item(app,"xdg-app::arch")
+#define gs_app_get_xdgapp_branch(app)          gs_app_get_metadata_item(app,"xdg-app::branch")
+#define gs_app_get_xdgapp_commit(app)          gs_app_get_metadata_item(app,"xdg-app::commit")
+#define gs_app_set_xdgapp_name(app,val)                gs_app_set_metadata(app,"xdg-app::name",val)
+#define gs_app_set_xdgapp_arch(app,val)                gs_app_set_metadata(app,"xdg-app::arch",val)
+#define gs_app_set_xdgapp_branch(app,val)      gs_app_set_metadata(app,"xdg-app::branch",val)
+#define gs_app_set_xdgapp_commit(app,val)      gs_app_set_metadata(app,"xdg-app::commit",val)
 
 /**
  * gs_app_get_xdgapp_kind:
@@ -109,7 +109,7 @@ gs_plugin_destroy (GsPlugin *plugin)
 static XdgAppRefKind
 gs_app_get_xdgapp_kind (GsApp *app)
 {
-       const gchar *kind = gs_app_get_metadata_item (app, "XgdApp::kind");
+       const gchar *kind = gs_app_get_metadata_item (app, "xdg-app::kind");
        if (g_strcmp0 (kind, "app") == 0)
                return XDG_APP_REF_KIND_APP;
        if (g_strcmp0 (kind, "runtime") == 0)
@@ -125,9 +125,9 @@ static void
 gs_app_set_xdgapp_kind (GsApp *app, XdgAppRefKind kind)
 {
        if (kind == XDG_APP_REF_KIND_APP)
-               gs_app_set_metadata (app, "XgdApp::kind", "app");
+               gs_app_set_metadata (app, "xdg-app::kind", "app");
        else if (kind == XDG_APP_REF_KIND_RUNTIME)
-               gs_app_set_metadata (app, "XgdApp::kind", "runtime");
+               gs_app_set_metadata (app, "xdg-app::kind", "runtime");
        else
                g_assert_not_reached ();
 }
@@ -252,20 +252,15 @@ gs_plugin_refresh_appstream (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_ensure_installation:
+ * gs_plugin_setup:
  */
-static gboolean
-gs_plugin_ensure_installation (GsPlugin *plugin,
-                              GCancellable *cancellable,
-                              GError **error)
+gboolean
+gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
 {
        g_autofree gchar *install_path = NULL;
        g_autoptr(AsProfileTask) ptask = NULL;
        g_autoptr(GFile) install_file = NULL;
 
-       if (plugin->priv->installation != NULL)
-               return TRUE;
-
        /* If we're running INSIDE the xdg-app environment we'll have the
         * env var XDG_DATA_HOME set to "~/.var/app/org.gnome.Software/data"
         * so specify the path manually to get the real data */
@@ -306,7 +301,7 @@ gs_plugin_ensure_installation (GsPlugin *plugin,
 static void
 gs_plugin_xdg_app_set_metadata (GsApp *app, XdgAppRef *xref)
 {
-       gs_app_set_management_plugin (app, "XgdApp");
+       gs_app_set_management_plugin (app, "xdg-app");
        gs_app_set_xdgapp_kind (app, xdg_app_ref_get_kind (xref));
        gs_app_set_xdgapp_name (app, xdg_app_ref_get_name (xref));
        gs_app_set_xdgapp_arch (app, xdg_app_ref_get_arch (xref));
@@ -461,10 +456,6 @@ gs_plugin_add_installed (GsPlugin *plugin,
        g_autoptr(GPtrArray) xrefs = NULL;
        guint i;
 
-       /* ensure we can set up the repo */
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
        /* if we've never ever run before, get the AppStream data */
        if (!gs_plugin_refresh_appstream (plugin,
                                          G_MAXUINT,
@@ -512,10 +503,6 @@ gs_plugin_add_sources (GsPlugin *plugin,
        g_autoptr(GPtrArray) xremotes = NULL;
        guint i;
 
-       /* ensure we can set up the repo */
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
        xremotes = xdg_app_installation_list_remotes (plugin->priv->installation,
                                                      cancellable,
                                                      error);
@@ -531,7 +518,7 @@ gs_plugin_add_sources (GsPlugin *plugin,
                        continue;
 
                app = gs_app_new (xdg_app_remote_get_name (xremote));
-               gs_app_set_management_plugin (app, "XgdApp");
+               gs_app_set_management_plugin (app, plugin->name);
                gs_app_set_kind (app, AS_APP_KIND_SOURCE);
                gs_app_set_state (app, AS_APP_STATE_INSTALLED);
                gs_app_set_name (app,
@@ -560,10 +547,6 @@ gs_plugin_add_updates (GsPlugin *plugin,
        guint i;
        g_autoptr(GPtrArray) xrefs = NULL;
 
-       /* ensure we can set up the repo */
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
        /* get all the installed apps (no network I/O) */
        xrefs = xdg_app_installation_list_installed_refs (plugin->priv->installation,
                                                          cancellable,
@@ -618,17 +601,16 @@ gs_plugin_refresh (GsPlugin *plugin,
        guint i;
        g_autoptr(GPtrArray) xrefs = NULL;
 
-       /* not us */
-       if ((flags & GS_PLUGIN_REFRESH_FLAGS_UPDATES) == 0)
-               return TRUE;
-
-       /* ensure we can set up the repo */
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
        /* update AppStream metadata */
-       if (!gs_plugin_refresh_appstream (plugin, cache_age, cancellable, error))
-               return FALSE;
+       if (flags & GS_PLUGIN_REFRESH_FLAGS_METADATA) {
+               if (!gs_plugin_refresh_appstream (plugin, cache_age,
+                                                 cancellable, error))
+                       return FALSE;
+       }
+
+       /* no longer interesting */
+       if ((flags & GS_PLUGIN_REFRESH_FLAGS_PAYLOAD) == 0)
+               return TRUE;
 
        /* use helper: FIXME: new()&ref? */
        helper.plugin = plugin;
@@ -685,12 +667,8 @@ gs_plugin_refine_item_origin_ui (GsPlugin *plugin,
        if (origin != NULL)
                return TRUE;
 
-       /* ensure we can set up the repo */
-       ptask = as_profile_start_literal (plugin->profile, "xdg-app::refine-origin-ui");
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
        /* find list of remotes */
+       ptask = as_profile_start_literal (plugin->profile, "xdg-app::refine-origin-ui");
        xremotes = xdg_app_installation_list_remotes (plugin->priv->installation,
                                                      cancellable,
                                                      error);
@@ -725,12 +703,8 @@ gs_plugin_refine_item_origin (GsPlugin *plugin,
        if (gs_app_get_origin (app) != NULL)
                return TRUE;
 
-       /* ensure we can set up the repo */
-       ptask = as_profile_start_literal (plugin->profile, "xdg-app::refine-origin");
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
        /* ensure metadata exists */
+       ptask = as_profile_start_literal (plugin->profile, "xdg-app::refine-origin");
        if (!gs_plugin_refine_item_metadata (plugin, app, cancellable, error))
                return FALSE;
 
@@ -851,13 +825,15 @@ gs_plugin_refine_item_metadata (GsPlugin *plugin,
        g_autoptr(XdgAppRef) xref = NULL;
 
        /* already set */
-       if (gs_app_get_metadata_item (app, "XgdApp::kind") != NULL)
+       if (gs_app_get_metadata_item (app, "xdg-app::kind") != NULL)
                return TRUE;
 
        /* AppStream sets the source to appname/arch/branch, if this isn't set
         * we can't break out the fields */
-       if (gs_app_get_source_default (app) == NULL)
+       if (gs_app_get_source_default (app) == NULL) {
+               g_warning ("no source set by appstream for %s", plugin->name);
                return TRUE;
+       }
 
        /* parse the ref */
        xref = xdg_app_ref_parse (gs_app_get_source_default (app), error);
@@ -1120,19 +1096,19 @@ gs_plugin_refine_item_size (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_refine_item:
+ * gs_plugin_xdg_app_refine_app:
  */
 static gboolean
-gs_plugin_refine_item (GsPlugin *plugin,
-                      GsApp *app,
-                      GsPluginRefineFlags flags,
-                      GCancellable *cancellable,
-                      GError **error)
+gs_plugin_xdg_app_refine_app (GsPlugin *plugin,
+                             GsApp *app,
+                             GsPluginRefineFlags flags,
+                             GCancellable *cancellable,
+                             GError **error)
 {
        g_autoptr(AsProfileTask) ptask = NULL;
 
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "XgdApp") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
        /* profile */
@@ -1173,28 +1149,15 @@ gs_plugin_refine_item (GsPlugin *plugin,
 }
 
 /**
- * gs_plugin_refine:
+ * gs_plugin_refine_app:
  */
 gboolean
-gs_plugin_refine (GsPlugin *plugin,
-                 GList **list,
-                 GsPluginRefineFlags flags,
-                 GCancellable *cancellable,
-                 GError **error)
-{
-       GList *l;
-       GsApp *app;
-
-       /* ensure we can set up the repo */
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
-       for (l = *list; l != NULL; l = l->next) {
-               app = GS_APP (l->data);
-               if (!gs_plugin_refine_item (plugin, app, flags, cancellable, error))
-                       return FALSE;
-       }
-       return TRUE;
+gs_plugin_refine_app (GsPlugin *plugin,
+                     GsApp *app,
+                     GsPluginRefineFlags flags,
+                     GCancellable *cancellable,
+                     GError **error)
+{      return gs_plugin_xdg_app_refine_app (plugin, app, flags, cancellable, error);
 }
 
 /**
@@ -1209,13 +1172,9 @@ gs_plugin_launch (GsPlugin *plugin,
        const gchar *branch = NULL;
 
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "XgdApp") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
-       /* ensure we can set up the repo */
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
        branch = gs_app_get_xdgapp_branch (app);
        if (branch == NULL)
                branch = "master";
@@ -1240,26 +1199,29 @@ gs_plugin_app_remove (GsPlugin *plugin,
        GsPluginHelper helper;
 
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "XgdApp") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
-       /* ensure we can set up the repo */
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
        /* use helper: FIXME: new()&ref? */
        helper.app = app;
        helper.plugin = plugin;
 
        /* remove */
        gs_app_set_state (app, AS_APP_STATE_REMOVING);
-       return xdg_app_installation_uninstall (plugin->priv->installation,
-                                              XDG_APP_REF_KIND_APP,
-                                              gs_app_get_xdgapp_name (app),
-                                              gs_app_get_xdgapp_arch (app),
-                                              gs_app_get_xdgapp_branch (app),
-                                              gs_plugin_xdg_app_progress_cb, &helper,
-                                              cancellable, error);
+       if (!xdg_app_installation_uninstall (plugin->priv->installation,
+                                            XDG_APP_REF_KIND_APP,
+                                            gs_app_get_xdgapp_name (app),
+                                            gs_app_get_xdgapp_arch (app),
+                                            gs_app_get_xdgapp_branch (app),
+                                            gs_plugin_xdg_app_progress_cb, &helper,
+                                            cancellable, error)) {
+               gs_app_set_state_recover (app);
+               return FALSE;
+       }
+
+       /* state is not known: we don't know if we can re-install this app */
+       gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
+       return TRUE;
 }
 
 /**
@@ -1275,15 +1237,11 @@ gs_plugin_app_install (GsPlugin *plugin,
        g_autoptr(XdgAppInstalledRef) xref = NULL;
 
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "XgdApp") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
-       /* ensure we can set up the repo */
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
        /* ensure we have metadata and state */
-       if (!gs_plugin_refine_item (plugin, app, 0, cancellable, error))
+       if (!gs_plugin_xdg_app_refine_app (plugin, app, 0, cancellable, error))
                return FALSE;
 
        /* use helper: FIXME: new()&ref? */
@@ -1328,7 +1286,7 @@ gs_plugin_app_install (GsPlugin *plugin,
                                                             gs_plugin_xdg_app_progress_cb, &helper,
                                                             cancellable, error);
                        if (xref == NULL) {
-                               gs_app_set_state (runtime, AS_APP_STATE_AVAILABLE);
+                               gs_app_set_state_recover (runtime);
                                return FALSE;
                        }
                        gs_app_set_state (runtime, AS_APP_STATE_INSTALLED);
@@ -1340,8 +1298,10 @@ gs_plugin_app_install (GsPlugin *plugin,
 
        /* use the source for local apps */
        if (gs_app_get_state (app) == AS_APP_STATE_AVAILABLE_LOCAL) {
+               g_autoptr(GFile) file = NULL;
+               file = g_file_new_for_path (gs_app_get_source_default (app));
                xref = xdg_app_installation_install_bundle (plugin->priv->installation,
-                                                           gs_app_get_local_file (app),
+                                                           file,
                                                            gs_plugin_xdg_app_progress_cb,
                                                            &helper,
                                                            cancellable, error);
@@ -1356,16 +1316,23 @@ gs_plugin_app_install (GsPlugin *plugin,
                                                     gs_plugin_xdg_app_progress_cb, &helper,
                                                     cancellable, error);
        }
+       if (xref == NULL) {
+               gs_app_set_state_recover (app);
+               return FALSE;
+       }
 
-       /* now the main application */
-       return xref != NULL;
+       /* state is known */
+       gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+       return TRUE;
 }
 
 /**
- * gs_plugin_update_app:
+ * gs_plugin_app_update:
+ *
+ * This is only called when updating live.
  */
 gboolean
-gs_plugin_update_app (GsPlugin *plugin,
+gs_plugin_app_update (GsPlugin *plugin,
                      GsApp *app,
                      GCancellable *cancellable,
                      GError **error)
@@ -1374,13 +1341,9 @@ gs_plugin_update_app (GsPlugin *plugin,
        g_autoptr(XdgAppInstalledRef) xref = NULL;
 
        /* only process this app if was created by this plugin */
-       if (g_strcmp0 (gs_app_get_management_plugin (app), "XgdApp") != 0)
+       if (g_strcmp0 (gs_app_get_management_plugin (app), plugin->name) != 0)
                return TRUE;
 
-       /* ensure we can set up the repo */
-       if (!gs_plugin_ensure_installation (plugin, cancellable, error))
-               return FALSE;
-
        /* use helper: FIXME: new()&ref? */
        helper.app = app;
        helper.plugin = plugin;
@@ -1395,7 +1358,14 @@ gs_plugin_update_app (GsPlugin *plugin,
                                            gs_app_get_xdgapp_branch (app),
                                            gs_plugin_xdg_app_progress_cb, &helper,
                                            cancellable, error);
-       return xref != NULL;
+       if (xref == NULL) {
+               gs_app_set_state_recover (app);
+               return FALSE;
+       }
+
+       /* state is known */
+       gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+       return TRUE;
 }
 
 /**
@@ -1515,6 +1485,10 @@ gs_plugin_file_to_app (GsPlugin *plugin,
                gs_app_set_icon (app, icon);
        }
 
+
+       /* set the source so we can install it higher up */
+       gs_app_add_source (app, gs_file_get_path (file));
+
        /* not quite true: this just means we can update this specific app */
        if (xdg_app_bundle_ref_get_origin (xref_bundle))
                gs_app_add_quirk (app, AS_APP_QUIRK_HAS_SOURCE);
diff --git a/src/plugins/gs-self-test.c b/src/plugins/gs-self-test.c
index 6b45897..8f0a943 100644
--- a/src/plugins/gs-self-test.c
+++ b/src/plugins/gs-self-test.c
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
  * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013-2016 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -26,6 +27,7 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
+#include "gs-markdown.h"
 #include "gs-moduleset.h"
 
 static void
@@ -64,6 +66,186 @@ moduleset_func (void)
        g_assert_cmpstr (data[1], ==, NULL);
 }
 
+static void
+gs_markdown_func (void)
+{
+       gchar *text;
+       const gchar *markdown;
+       const gchar *markdown_expected;
+       g_autoptr(GsMarkdown) md = NULL;
+
+       /* get GsMarkdown object */
+       md = gs_markdown_new (GS_MARKDOWN_OUTPUT_PANGO);
+       g_assert (md);
+
+       markdown = "OEMs\n"
+                  "====\n"
+                  " - Bullett\n";
+       markdown_expected =
+                  "<big>OEMs</big>\n"
+                  "• Bullett";
+       /* markdown (type2 header) */
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
+       /* markdown (autocode) */
+       markdown = "this is http://www.hughsie.com/with_spaces_in_url inline link\n";
+       markdown_expected = "this is <tt>http://www.hughsie.com/with_spaces_in_url</tt> inline link";
+       gs_markdown_set_autocode (md, TRUE);
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
+       /* markdown some invalid header */
+       markdown = "*** This software is currently in alpha state ***\n";
+       markdown_expected = "<b><i> This software is currently in alpha state </b></i>";
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
+       /* markdown (complex1) */
+       markdown = " - This is a *very*\n"
+                  "   short paragraph\n"
+                  "   that is not usual.\n"
+                  " - Another";
+       markdown_expected =
+                  "• This is a <i>very</i> short paragraph that is not usual.\n"
+                  "• Another";
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
+       /* markdown (complex1) */
+       markdown = "*  This is a *very*\n"
+                  "   short paragraph\n"
+                  "   that is not usual.\n"
+                  "*  This is the second\n"
+                  "   bullett point.\n"
+                  "*  And the third.\n"
+                  " \n"
+                  "* * *\n"
+                  " \n"
+                  "Paragraph one\n"
+                  "isn't __very__ long at all.\n"
+                  "\n"
+                  "Paragraph two\n"
+                  "isn't much better.";
+       markdown_expected =
+                  "• This is a <i>very</i> short paragraph that is not usual.\n"
+                  "• This is the second bullett point.\n"
+                  "• And the third.\n"
+                  "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\n"
+                  "Paragraph one isn&apos;t <b>very</b> long at all.\n"
+                  "Paragraph two isn&apos;t much better.";
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
+       markdown = "This is a spec file description or\n"
+                  "an **update** description in bohdi.\n"
+                  "\n"
+                  "* * *\n"
+                  "# Big title #\n"
+                  "\n"
+                  "The *following* things 'were' fixed:\n"
+                  "- Fix `dave`\n"
+                  "* Fubar update because of \"security\"\n";
+       markdown_expected =
+                  "This is a spec file description or an <b>update</b> description in bohdi.\n"
+                  "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯\n"
+                  "<big>Big title</big>\n"
+                  "The <i>following</i> things 'were' fixed:\n"
+                  "• Fix <tt>dave</tt>\n"
+                  "• Fubar update because of \"security\"";
+       /* markdown (complex2) */
+       text = gs_markdown_parse (md, markdown);
+       if (g_strcmp0 (text, markdown_expected) == 0)
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
+       /* markdown (list with spaces) */
+       markdown = "* list seporated with spaces -\n"
+                  "  first item\n"
+                  "\n"
+                  "* second item\n"
+                  "\n"
+                  "* third item\n";
+       markdown_expected =
+                  "• list seporated with spaces - first item\n"
+                  "• second item\n"
+                  "• third item";
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
+       gs_markdown_set_max_lines (md, 1);
+
+       /* markdown (one line limit) */
+       markdown = "* list seporated with spaces -\n"
+                  "  first item\n"
+                  "* second item\n";
+       markdown_expected =
+                  "• list seporated with spaces - first item";
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
+       gs_markdown_set_max_lines (md, 1);
+
+       /* markdown (escaping) */
+       markdown = "* list & <spaces>";
+       markdown_expected =
+                  "• list &amp; &lt;spaces&gt;";
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
+       /* markdown (URLs) */
+       markdown = "this is the http://www.hughsie.com/ coolest site";
+       markdown_expected =
+                  "this is the "
+                  "<a href=\"http://www.hughsie.com/\";>http://www.hughsie.com/</a>"
+                  " coolest site";
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+
+       /* markdown (free text) */
+       gs_markdown_set_escape (md, FALSE);
+       text = gs_markdown_parse (md, "This isn't a present");
+       g_assert_cmpstr (text, ==, "This isn't a present");
+       g_free (text);
+
+       /* markdown (autotext underscore) */
+       text = gs_markdown_parse (md, "This isn't CONFIG_UEVENT_HELPER_PATH present");
+       g_assert_cmpstr (text, ==, "This isn't <tt>CONFIG_UEVENT_HELPER_PATH</tt> present");
+       g_free (text);
+
+       /* markdown (end of bullett) */
+       markdown = "*Thu Mar 12 12:00:00 2009* Dan Walsh <dwalsh redhat com> - 2.0.79-1\n"
+                  "- Update to upstream \n"
+                  " * Netlink socket handoff patch from Adam Jackson.\n"
+                  " * AVC caching of compute_create results by Eric Paris.\n"
+                  "\n"
+                  "*Tue Mar 10 12:00:00 2009* Dan Walsh <dwalsh redhat com> - 2.0.78-5\n"
+                  "- Add patch from ajax to accellerate X SELinux \n"
+                  "- Update eparis patch\n";
+       markdown_expected =
+                  "<i>Thu Mar 12 12:00:00 2009</i> Dan Walsh <tt>&lt;dwalsh redhat com&gt;</tt> - 2.0.79-1\n"
+                  "• Update to upstream\n"
+                  "• Netlink socket handoff patch from Adam Jackson.\n"
+                  "• AVC caching of compute_create results by Eric Paris.\n"
+                  "<i>Tue Mar 10 12:00:00 2009</i> Dan Walsh <tt>&lt;dwalsh redhat com&gt;</tt> - 2.0.78-5\n"
+                  "• Add patch from ajax to accellerate X SELinux\n"
+                  "• Update eparis patch";
+       gs_markdown_set_escape (md, TRUE);
+       gs_markdown_set_max_lines (md, 1024);
+       text = gs_markdown_parse (md, markdown);
+       g_assert_cmpstr (text, ==, markdown_expected);
+       g_free (text);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -75,7 +257,8 @@ main (int argc, char **argv)
        g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
 
        /* tests go here */
-       g_test_add_func ("/moduleset", moduleset_func);
+       g_test_add_func ("/gnome-software/moduleset", moduleset_func);
+       g_test_add_func ("/gnome-software/markdown", gs_markdown_func);
 
        return g_test_run ();
 }
diff --git a/src/plugins/menu-spec-common.c b/src/plugins/menu-spec-common.c
index c732baa..cbb57dc 100644
--- a/src/plugins/menu-spec-common.c
+++ b/src/plugins/menu-spec-common.c
@@ -27,194 +27,194 @@
 
 static const MenuSpecData msdata[] = {
        /* TRANSLATORS: this is the menu spec main category for Audio */
-       { "Audio",                              N_("Audio") },
-       { "Audio::AudioVideoEditing",           NC_("Menu subcategory of Audio", "Editing") },
-       { "Audio::Database",                    NC_("Menu subcategory of Audio", "Databases") },
-       { "Audio::DiscBurning",                 NC_("Menu subcategory of Audio", "Disc Burning") },
-       { "Audio::HamRadio",                    NC_("Menu subcategory of Audio", "Ham Radio") },
-       { "Audio::Midi",                        NC_("Menu subcategory of Audio", "MIDI") },
-       { "Audio::Mixer",                       NC_("Menu subcategory of Audio", "Mixer") },
-       { "Audio::Music",                       NC_("Menu subcategory of Audio", "Music") },
-       { "Audio::Player",                      NC_("Menu subcategory of Audio", "Players") },
-       { "Audio::Recorder",                    NC_("Menu subcategory of Audio", "Recorders") },
-       { "Audio::Sequencer",                   NC_("Menu subcategory of Audio", "Sequencers") },
-       { "Audio::Tuner",                       NC_("Menu subcategory of Audio", "Tuners") },
+       { "Audio",                              "folder-music-symbolic", N_("Audio") },
+       { "Audio::AudioVideoEditing",           NULL, NC_("Menu subcategory of Audio", "Editing") },
+       { "Audio::Database",                    NULL, NC_("Menu subcategory of Audio", "Databases") },
+       { "Audio::DiscBurning",                 NULL, NC_("Menu subcategory of Audio", "Disc Burning") },
+       { "Audio::HamRadio",                    NULL, NC_("Menu subcategory of Audio", "Ham Radio") },
+       { "Audio::Midi",                        NULL, NC_("Menu subcategory of Audio", "MIDI") },
+       { "Audio::Mixer",                       NULL, NC_("Menu subcategory of Audio", "Mixer") },
+       { "Audio::Music",                       NULL, NC_("Menu subcategory of Audio", "Music") },
+       { "Audio::Player",                      NULL, NC_("Menu subcategory of Audio", "Players") },
+       { "Audio::Recorder",                    NULL, NC_("Menu subcategory of Audio", "Recorders") },
+       { "Audio::Sequencer",                   NULL, NC_("Menu subcategory of Audio", "Sequencers") },
+       { "Audio::Tuner",                       NULL, NC_("Menu subcategory of Audio", "Tuners") },
        /* TRANSLATORS: this is the menu spec main category for Development */
-       { "Development",                        N_("Development Tools") },
-       { "Development::Building",              NC_("Menu subcategory of Development Tools", "Building") },
-       { "Development::Database",              NC_("Menu subcategory of Development Tools", "Databases") },
-       { "Development::Debugger",              NC_("Menu subcategory of Development Tools", "Debuggers") },
-       { "Development::GUIDesigner",           NC_("Menu subcategory of Development Tools", "GUI Designers") 
},
-       { "Development::IDE",                   NC_("Menu subcategory of Development Tools", "IDE") },
-       { "Development::Profiling",             NC_("Menu subcategory of Development Tools", "Profiling") },
-       { "Development::ProjectManagement",     NC_("Menu subcategory of Development Tools", "Project 
Management") },
-       { "Development::RevisionControl",       NC_("Menu subcategory of Development Tools", "Revision 
Control") },
-       { "Development::Translation",           NC_("Menu subcategory of Development Tools", "Translation") },
-       { "Development::WebDevelopment",        NC_("Menu subcategory of Development Tools", "Web 
Development") },
+       { "Development",                        "applications-engineering-symbolic", N_("Development Tools") 
},
+       { "Development::Building",              NULL, NC_("Menu subcategory of Development Tools", 
"Building") },
+       { "Development::Database",              NULL, NC_("Menu subcategory of Development Tools", 
"Databases") },
+       { "Development::Debugger",              NULL, NC_("Menu subcategory of Development Tools", 
"Debuggers") },
+       { "Development::GUIDesigner",           NULL, NC_("Menu subcategory of Development Tools", "GUI 
Designers") },
+       { "Development::IDE",                   NULL, NC_("Menu subcategory of Development Tools", "IDE") },
+       { "Development::Profiling",             NULL, NC_("Menu subcategory of Development Tools", 
"Profiling") },
+       { "Development::ProjectManagement",     NULL, NC_("Menu subcategory of Development Tools", "Project 
Management") },
+       { "Development::RevisionControl",       NULL, NC_("Menu subcategory of Development Tools", "Revision 
Control") },
+       { "Development::Translation",           NULL, NC_("Menu subcategory of Development Tools", 
"Translation") },
+       { "Development::WebDevelopment",        NULL, NC_("Menu subcategory of Development Tools", "Web 
Development") },
        /* TRANSLATORS: this is the menu spec main category for Education */
-       { "Education",                          N_("Education") },
-       { "Education::Art",                     NC_("Menu subcategory of Education", "Art") },
-       { "Education::ArtificialIntelligence",  NC_("Menu subcategory of Education", "Artificial 
Intelligence") },
-       { "Education::Astronomy",               NC_("Menu subcategory of Education", "Astronomy") },
-       { "Education::Biology",                 NC_("Menu subcategory of Education", "Biology") },
-       { "Education::Chemistry",               NC_("Menu subcategory of Education", "Chemistry") },
-       { "Education::ComputerScience",         NC_("Menu subcategory of Education", "Computer Science") },
-       { "Education::Construction",            NC_("Menu subcategory of Education", "Construction") },
-       { "Education::DataVisualization",       NC_("Menu subcategory of Education", "Data Visualization") },
-       { "Education::Economy",                 NC_("Menu subcategory of Education", "Economy") },
-       { "Education::Electricity",             NC_("Menu subcategory of Education", "Electricity") },
-       { "Education::Electronics",             NC_("Menu subcategory of Education", "Electronics") },
-       { "Education::Engineering",             NC_("Menu subcategory of Education", "Engineering") },
-       { "Education::Geography",               NC_("Menu subcategory of Education", "Geography") },
-       { "Education::Geology",                 NC_("Menu subcategory of Education", "Geology") },
-       { "Education::Geoscience",              NC_("Menu subcategory of Education", "Geoscience") },
-       { "Education::History",                 NC_("Menu subcategory of Education", "History") },
-       { "Education::Humanities",              NC_("Menu subcategory of Education", "Humanities") },
-       { "Education::ImageProcessing",         NC_("Menu subcategory of Education", "Image Processing") },
-       { "Education::Languages",               NC_("Menu subcategory of Education", "Languages") },
-       { "Education::Literature",              NC_("Menu subcategory of Education", "Literature") },
-       { "Education::Maps",                    NC_("Menu subcategory of Education", "Maps") },
-       { "Education::Math",                    NC_("Menu subcategory of Education", "Math") },
-       { "Education::MedicalSoftware",         NC_("Menu subcategory of Education", "Medical") },
-       { "Education::Music",                   NC_("Menu subcategory of Education", "Music") },
-       { "Education::NumericalAnalysis",       NC_("Menu subcategory of Education", "Numerical Analysis") },
-       { "Education::ParallelComputing",       NC_("Menu subcategory of Education", "Parallel Computing") },
-       { "Education::Physics",                 NC_("Menu subcategory of Education", "Physics") },
-       { "Education::Robotics",                NC_("Menu subcategory of Education", "Robotics") },
-       { "Education::Spirituality",            NC_("Menu subcategory of Education", "Spirituality") },
-       { "Education::Sports",                  NC_("Menu subcategory of Education", "Sports") },
+       { "Education",                          "system-help-symbolic", N_("Education") },
+       { "Education::Art",                     NULL, NC_("Menu subcategory of Education", "Art") },
+       { "Education::ArtificialIntelligence",  NULL, NC_("Menu subcategory of Education", "Artificial 
Intelligence") },
+       { "Education::Astronomy",               NULL, NC_("Menu subcategory of Education", "Astronomy") },
+       { "Education::Biology",                 NULL, NC_("Menu subcategory of Education", "Biology") },
+       { "Education::Chemistry",               NULL, NC_("Menu subcategory of Education", "Chemistry") },
+       { "Education::ComputerScience",         NULL, NC_("Menu subcategory of Education", "Computer 
Science") },
+       { "Education::Construction",            NULL, NC_("Menu subcategory of Education", "Construction") },
+       { "Education::DataVisualization",       NULL, NC_("Menu subcategory of Education", "Data 
Visualization") },
+       { "Education::Economy",                 NULL, NC_("Menu subcategory of Education", "Economy") },
+       { "Education::Electricity",             NULL, NC_("Menu subcategory of Education", "Electricity") },
+       { "Education::Electronics",             NULL, NC_("Menu subcategory of Education", "Electronics") },
+       { "Education::Engineering",             NULL, NC_("Menu subcategory of Education", "Engineering") },
+       { "Education::Geography",               NULL, NC_("Menu subcategory of Education", "Geography") },
+       { "Education::Geology",                 NULL, NC_("Menu subcategory of Education", "Geology") },
+       { "Education::Geoscience",              NULL, NC_("Menu subcategory of Education", "Geoscience") },
+       { "Education::History",                 NULL, NC_("Menu subcategory of Education", "History") },
+       { "Education::Humanities",              NULL, NC_("Menu subcategory of Education", "Humanities") },
+       { "Education::ImageProcessing",         NULL, NC_("Menu subcategory of Education", "Image 
Processing") },
+       { "Education::Languages",               NULL, NC_("Menu subcategory of Education", "Languages") },
+       { "Education::Literature",              NULL, NC_("Menu subcategory of Education", "Literature") },
+       { "Education::Maps",                    NULL, NC_("Menu subcategory of Education", "Maps") },
+       { "Education::Math",                    NULL, NC_("Menu subcategory of Education", "Math") },
+       { "Education::MedicalSoftware",         NULL, NC_("Menu subcategory of Education", "Medical") },
+       { "Education::Music",                   NULL, NC_("Menu subcategory of Education", "Music") },
+       { "Education::NumericalAnalysis",       NULL, NC_("Menu subcategory of Education", "Numerical 
Analysis") },
+       { "Education::ParallelComputing",       NULL, NC_("Menu subcategory of Education", "Parallel 
Computing") },
+       { "Education::Physics",                 NULL, NC_("Menu subcategory of Education", "Physics") },
+       { "Education::Robotics",                NULL, NC_("Menu subcategory of Education", "Robotics") },
+       { "Education::Spirituality",            NULL, NC_("Menu subcategory of Education", "Spirituality") },
+       { "Education::Sports",                  NULL, NC_("Menu subcategory of Education", "Sports") },
        /* TRANSLATORS: this is the menu spec main category for Games */
-       { "Game",                               N_("Games") },
-       { "Game::ActionGame",                   NC_("Menu subcategory of Games", "Action") },
-       { "Game::AdventureGame",                NC_("Menu subcategory of Games", "Adventure") },
-       { "Game::ArcadeGame",                   NC_("Menu subcategory of Games", "Arcade") },
-       { "Game::BlocksGame",                   NC_("Menu subcategory of Games", "Blocks") },
-       { "Game::BoardGame",                    NC_("Menu subcategory of Games", "Board") },
-       { "Game::CardGame",                     NC_("Menu subcategory of Games", "Card") },
-       { "Game::Emulator",                     NC_("Menu subcategory of Games", "Emulators") },
-       { "Game::KidsGame",                     NC_("Menu subcategory of Games", "Kids") },
-       { "Game::LogicGame",                    NC_("Menu subcategory of Games", "Logic") },
-       { "Game::RolePlaying",                  NC_("Menu subcategory of Games", "Role Playing") },
-       { "Game::Shooter",                      NC_("Menu subcategory of Games", "Shooter") },
-       { "Game::Simulation",                   NC_("Menu subcategory of Games", "Simulation") },
-       { "Game::SportsGame",                   NC_("Menu subcategory of Games", "Sports") },
-       { "Game::StrategyGame",                 NC_("Menu subcategory of Games", "Strategy") },
+       { "Game",                               "applications-games-symbolic", N_("Games") },
+       { "Game::ActionGame",                   NULL, NC_("Menu subcategory of Games", "Action") },
+       { "Game::AdventureGame",                NULL, NC_("Menu subcategory of Games", "Adventure") },
+       { "Game::ArcadeGame",                   NULL, NC_("Menu subcategory of Games", "Arcade") },
+       { "Game::BlocksGame",                   NULL, NC_("Menu subcategory of Games", "Blocks") },
+       { "Game::BoardGame",                    NULL, NC_("Menu subcategory of Games", "Board") },
+       { "Game::CardGame",                     NULL, NC_("Menu subcategory of Games", "Card") },
+       { "Game::Emulator",                     NULL, NC_("Menu subcategory of Games", "Emulators") },
+       { "Game::KidsGame",                     NULL, NC_("Menu subcategory of Games", "Kids") },
+       { "Game::LogicGame",                    NULL, NC_("Menu subcategory of Games", "Logic") },
+       { "Game::RolePlaying",                  NULL, NC_("Menu subcategory of Games", "Role Playing") },
+       { "Game::Shooter",                      NULL, NC_("Menu subcategory of Games", "Shooter") },
+       { "Game::Simulation",                   NULL, NC_("Menu subcategory of Games", "Simulation") },
+       { "Game::SportsGame",                   NULL, NC_("Menu subcategory of Games", "Sports") },
+       { "Game::StrategyGame",                 NULL, NC_("Menu subcategory of Games", "Strategy") },
        /* TRANSLATORS: this is the menu spec main category for Graphics */
-       { "Graphics",                           N_("Graphics") },
-       { "Graphics::2DGraphics",               NC_("Menu subcategory of Graphics", "2D Graphics") },
-       { "Graphics::3DGraphics",               NC_("Menu subcategory of Graphics", "3D Graphics") },
-       { "Graphics::OCR",                      NC_("Menu subcategory of Graphics", "OCR") },
-       { "Graphics::Photography",              NC_("Menu subcategory of Graphics", "Photography") },
-       { "Graphics::Publishing",               NC_("Menu subcategory of Graphics", "Publishing") },
-       { "Graphics::RasterGraphics",           NC_("Menu subcategory of Graphics", "Raster Graphics") },
-       { "Graphics::Scanning",                 NC_("Menu subcategory of Graphics", "Scanning") },
-       { "Graphics::VectorGraphics",           NC_("Menu subcategory of Graphics", "Vector Graphics") },
-       { "Graphics::Viewer",                   NC_("Menu subcategory of Graphics", "Viewer") },
+       { "Graphics",                           "applications-graphics-symbolic", N_("Graphics") },
+       { "Graphics::2DGraphics",               NULL, NC_("Menu subcategory of Graphics", "2D Graphics") },
+       { "Graphics::3DGraphics",               NULL, NC_("Menu subcategory of Graphics", "3D Graphics") },
+       { "Graphics::OCR",                      NULL, NC_("Menu subcategory of Graphics", "OCR") },
+       { "Graphics::Photography",              NULL, NC_("Menu subcategory of Graphics", "Photography") },
+       { "Graphics::Publishing",               NULL, NC_("Menu subcategory of Graphics", "Publishing") },
+       { "Graphics::RasterGraphics",           NULL, NC_("Menu subcategory of Graphics", "Raster Graphics") 
},
+       { "Graphics::Scanning",                 NULL, NC_("Menu subcategory of Graphics", "Scanning") },
+       { "Graphics::VectorGraphics",           NULL, NC_("Menu subcategory of Graphics", "Vector Graphics") 
},
+       { "Graphics::Viewer",                   NULL, NC_("Menu subcategory of Graphics", "Viewer") },
        /* TRANSLATORS: this is the menu spec main category for Network */
-       { "Network",                            N_("Internet") },
-       { "Network::Chat",                      NC_("Menu subcategory of Internet", "Chat") },
-       { "Network::Dialup",                    NC_("Menu subcategory of Internet", "Dialup") },
-       { "Network::Email",                     NC_("Menu subcategory of Internet", "Email") },
-       { "Network::Feed",                      NC_("Menu subcategory of Internet", "Feed") },
-       { "Network::FileTransfer",              NC_("Menu subcategory of Internet", "File Transfer") },
-       { "Network::HamRadio",                  NC_("Menu subcategory of Internet", "Ham Radio") },
-       { "Network::InstantMessaging",          NC_("Menu subcategory of Internet", "Instant Messaging") },
-       { "Network::IRCClient",                 NC_("Menu subcategory of Internet", "IRC Clients") },
-       { "Network::Monitor",                   NC_("Menu subcategory of Internet", "Monitor") },
-       { "Network::News",                      NC_("Menu subcategory of Internet", "News") },
-       { "Network::P2P",                       NC_("Menu subcategory of Internet", "P2P") },
-       { "Network::RemoteAccess",              NC_("Menu subcategory of Internet", "Remote Access") },
-       { "Network::Telephony",                 NC_("Menu subcategory of Internet", "Telephony") },
-       { "Network::VideoConference",           NC_("Menu subcategory of Internet", "Video Conference") },
-       { "Network::WebBrowser",                NC_("Menu subcategory of Internet", "Web Browser") },
-       { "Network::WebDevelopment",            NC_("Menu subcategory of Internet", "Web Development") },
+       { "Network",                            "network-wireless-symbolic", N_("Internet") },
+       { "Network::Chat",                      NULL, NC_("Menu subcategory of Internet", "Chat") },
+       { "Network::Dialup",                    NULL, NC_("Menu subcategory of Internet", "Dialup") },
+       { "Network::Email",                     NULL, NC_("Menu subcategory of Internet", "Email") },
+       { "Network::Feed",                      NULL, NC_("Menu subcategory of Internet", "Feed") },
+       { "Network::FileTransfer",              NULL, NC_("Menu subcategory of Internet", "File Transfer") },
+       { "Network::HamRadio",                  NULL, NC_("Menu subcategory of Internet", "Ham Radio") },
+       { "Network::InstantMessaging",          NULL, NC_("Menu subcategory of Internet", "Instant 
Messaging") },
+       { "Network::IRCClient",                 NULL, NC_("Menu subcategory of Internet", "IRC Clients") },
+       { "Network::Monitor",                   NULL, NC_("Menu subcategory of Internet", "Monitor") },
+       { "Network::News",                      NULL, NC_("Menu subcategory of Internet", "News") },
+       { "Network::P2P",                       NULL, NC_("Menu subcategory of Internet", "P2P") },
+       { "Network::RemoteAccess",              NULL, NC_("Menu subcategory of Internet", "Remote Access") },
+       { "Network::Telephony",                 NULL, NC_("Menu subcategory of Internet", "Telephony") },
+       { "Network::VideoConference",           NULL, NC_("Menu subcategory of Internet", "Video Conference") 
},
+       { "Network::WebBrowser",                NULL, NC_("Menu subcategory of Internet", "Web Browser") },
+       { "Network::WebDevelopment",            NULL, NC_("Menu subcategory of Internet", "Web Development") 
},
        /* TRANSLATORS: this is the menu spec main category for Office */
-       { "Office",                             N_("Office") },
-       { "Office::Calendar",                   NC_("Menu subcategory of Office", "Calendar") },
-       { "Office::Chart",                      NC_("Menu subcategory of Office", "Chart") },
-       { "Office::ContactManagement",          NC_("Menu subcategory of Office", "Contact Management") },
-       { "Office::Database",                   NC_("Menu subcategory of Office", "Database") },
-       { "Office::Dictionary",                 NC_("Menu subcategory of Office", "Dictionary") },
-       { "Office::Email",                      NC_("Menu subcategory of Office", "Email") },
-       { "Office::Finance",                    NC_("Menu subcategory of Office", "Finance") },
-       { "Office::FlowChart",                  NC_("Menu subcategory of Office", "Flow Chart") },
-       { "Office::PDA",                        NC_("Menu subcategory of Office", "PDA") },
-       { "Office::Photography",                NC_("Menu subcategory of Office", "Photography") },
-       { "Office::Presentation",               NC_("Menu subcategory of Office", "Presentation") },
-       { "Office::ProjectManagement",          NC_("Menu subcategory of Office", "Project Management") },
-       { "Office::Publishing",                 NC_("Menu subcategory of Office", "Publishing") },
-       { "Office::Spreadsheet",                NC_("Menu subcategory of Office", "Spreadsheet") },
-       { "Office::Viewer",                     NC_("Menu subcategory of Office", "Viewer") },
-       { "Office::WordProcessor",              NC_("Menu subcategory of Office", "Word Processor") },
+       { "Office",                             "text-editor-symbolic", N_("Office") },
+       { "Office::Calendar",                   NULL, NC_("Menu subcategory of Office", "Calendar") },
+       { "Office::Chart",                      NULL, NC_("Menu subcategory of Office", "Chart") },
+       { "Office::ContactManagement",          NULL, NC_("Menu subcategory of Office", "Contact Management") 
},
+       { "Office::Database",                   NULL, NC_("Menu subcategory of Office", "Database") },
+       { "Office::Dictionary",                 NULL, NC_("Menu subcategory of Office", "Dictionary") },
+       { "Office::Email",                      NULL, NC_("Menu subcategory of Office", "Email") },
+       { "Office::Finance",                    NULL, NC_("Menu subcategory of Office", "Finance") },
+       { "Office::FlowChart",                  NULL, NC_("Menu subcategory of Office", "Flow Chart") },
+       { "Office::PDA",                        NULL, NC_("Menu subcategory of Office", "PDA") },
+       { "Office::Photography",                NULL, NC_("Menu subcategory of Office", "Photography") },
+       { "Office::Presentation",               NULL, NC_("Menu subcategory of Office", "Presentation") },
+       { "Office::ProjectManagement",          NULL, NC_("Menu subcategory of Office", "Project Management") 
},
+       { "Office::Publishing",                 NULL, NC_("Menu subcategory of Office", "Publishing") },
+       { "Office::Spreadsheet",                NULL, NC_("Menu subcategory of Office", "Spreadsheet") },
+       { "Office::Viewer",                     NULL, NC_("Menu subcategory of Office", "Viewer") },
+       { "Office::WordProcessor",              NULL, NC_("Menu subcategory of Office", "Word Processor") },
        /* TRANSLATORS: this is the menu spec main category for Science */
-       { "Science",                            N_("Science") },
-       { "Science::Art",                       NC_("Menu subcategory of Science", "Art") },
-       { "Science::ArtificialIntelligence",    NC_("Menu subcategory of Science", "Artificial Intelligence") 
},
-       { "Science::Astronomy",                 NC_("Menu subcategory of Science", "Astronomy") },
-       { "Science::Biology",                   NC_("Menu subcategory of Science", "Biology") },
-       { "Science::Chemistry",                 NC_("Menu subcategory of Science", "Chemistry") },
-       { "Science::ComputerScience",           NC_("Menu subcategory of Science", "Computer Science") },
-       { "Science::Construction",              NC_("Menu subcategory of Science", "Construction") },
-       { "Science::DataVisualization",         NC_("Menu subcategory of Science", "Data Visualization") },
-       { "Science::Economy",                   NC_("Menu subcategory of Science", "Economy") },
-       { "Science::Electricity",               NC_("Menu subcategory of Science", "Electricity") },
-       { "Science::Electronics",               NC_("Menu subcategory of Science", "Electronics") },
-       { "Science::Engineering",               NC_("Menu subcategory of Science", "Engineering") },
-       { "Science::Geography",                 NC_("Menu subcategory of Science", "Geography") },
-       { "Science::Geology",                   NC_("Menu subcategory of Science", "Geology") },
-       { "Science::Geoscience",                NC_("Menu subcategory of Science", "Geoscience") },
-       { "Science::History",                   NC_("Menu subcategory of Science", "History") },
-       { "Science::Humanities",                NC_("Menu subcategory of Science", "Humanities") },
-       { "Science::ImageProcessing",           NC_("Menu subcategory of Science", "Image Processing") },
-       { "Science::Languages",                 NC_("Menu subcategory of Science", "Languages") },
-       { "Science::Literature",                NC_("Menu subcategory of Science", "Literature") },
-       { "Science::Maps",                      NC_("Menu subcategory of Science", "Maps") },
-       { "Science::Math",                      NC_("Menu subcategory of Science", "Math") },
-       { "Science::MedicalSoftware",           NC_("Menu subcategory of Science", "Medical") },
-       { "Science::NumericalAnalysis",         NC_("Menu subcategory of Science", "Numerical Analysis") },
-       { "Science::ParallelComputing",         NC_("Menu subcategory of Science", "Parallel Computing") },
-       { "Science::Physics",                   NC_("Menu subcategory of Science", "Physics") },
-       { "Science::Robotics",                  NC_("Menu subcategory of Science", "Robotics") },
-       { "Science::Spirituality",              NC_("Menu subcategory of Science", "Spirituality") },
-       { "Science::Sports",                    NC_("Menu subcategory of Science", "Sports") },
+       { "Science",                            "applications-science-symbolic", N_("Science") },
+       { "Science::Art",                       NULL, NC_("Menu subcategory of Science", "Art") },
+       { "Science::ArtificialIntelligence",    NULL, NC_("Menu subcategory of Science", "Artificial 
Intelligence") },
+       { "Science::Astronomy",                 NULL, NC_("Menu subcategory of Science", "Astronomy") },
+       { "Science::Biology",                   NULL, NC_("Menu subcategory of Science", "Biology") },
+       { "Science::Chemistry",                 NULL, NC_("Menu subcategory of Science", "Chemistry") },
+       { "Science::ComputerScience",           NULL, NC_("Menu subcategory of Science", "Computer Science") 
},
+       { "Science::Construction",              NULL, NC_("Menu subcategory of Science", "Construction") },
+       { "Science::DataVisualization",         NULL, NC_("Menu subcategory of Science", "Data 
Visualization") },
+       { "Science::Economy",                   NULL, NC_("Menu subcategory of Science", "Economy") },
+       { "Science::Electricity",               NULL, NC_("Menu subcategory of Science", "Electricity") },
+       { "Science::Electronics",               NULL, NC_("Menu subcategory of Science", "Electronics") },
+       { "Science::Engineering",               NULL, NC_("Menu subcategory of Science", "Engineering") },
+       { "Science::Geography",                 NULL, NC_("Menu subcategory of Science", "Geography") },
+       { "Science::Geology",                   NULL, NC_("Menu subcategory of Science", "Geology") },
+       { "Science::Geoscience",                NULL, NC_("Menu subcategory of Science", "Geoscience") },
+       { "Science::History",                   NULL, NC_("Menu subcategory of Science", "History") },
+       { "Science::Humanities",                NULL, NC_("Menu subcategory of Science", "Humanities") },
+       { "Science::ImageProcessing",           NULL, NC_("Menu subcategory of Science", "Image Processing") 
},
+       { "Science::Languages",                 NULL, NC_("Menu subcategory of Science", "Languages") },
+       { "Science::Literature",                NULL, NC_("Menu subcategory of Science", "Literature") },
+       { "Science::Maps",                      NULL, NC_("Menu subcategory of Science", "Maps") },
+       { "Science::Math",                      NULL, NC_("Menu subcategory of Science", "Math") },
+       { "Science::MedicalSoftware",           NULL, NC_("Menu subcategory of Science", "Medical") },
+       { "Science::NumericalAnalysis",         NULL, NC_("Menu subcategory of Science", "Numerical 
Analysis") },
+       { "Science::ParallelComputing",         NULL, NC_("Menu subcategory of Science", "Parallel 
Computing") },
+       { "Science::Physics",                   NULL, NC_("Menu subcategory of Science", "Physics") },
+       { "Science::Robotics",                  NULL, NC_("Menu subcategory of Science", "Robotics") },
+       { "Science::Spirituality",              NULL, NC_("Menu subcategory of Science", "Spirituality") },
+       { "Science::Sports",                    NULL, NC_("Menu subcategory of Science", "Sports") },
        /* TRANSLATORS: this is the menu spec main category for System */
-       { "System",                             N_("System") },
-       { "System::Emulator",                   NC_("Menu subcategory of System", "Emulator") },
-       { "System::FileManager",                NC_("Menu subcategory of System", "File Manager") },
-       { "System::Filesystem",                 NC_("Menu subcategory of System", "File System") },
-       { "System::FileTools",                  NC_("Menu subcategory of System", "File Tools") },
-       { "System::Monitor",                    NC_("Menu subcategory of System", "Monitor") },
-       { "System::Security",                   NC_("Menu subcategory of System", "Security") },
-       { "System::TerminalEmulator",           NC_("Menu subcategory of System", "Terminal Emulator") },
+       { "System",                             "applications-system-symbolic", N_("System") },
+       { "System::Emulator",                   NULL, NC_("Menu subcategory of System", "Emulator") },
+       { "System::FileManager",                NULL, NC_("Menu subcategory of System", "File Manager") },
+       { "System::Filesystem",                 NULL, NC_("Menu subcategory of System", "File System") },
+       { "System::FileTools",                  NULL, NC_("Menu subcategory of System", "File Tools") },
+       { "System::Monitor",                    NULL, NC_("Menu subcategory of System", "Monitor") },
+       { "System::Security",                   NULL, NC_("Menu subcategory of System", "Security") },
+       { "System::TerminalEmulator",           NULL, NC_("Menu subcategory of System", "Terminal Emulator") 
},
        /* TRANSLATORS: this is the menu spec main category for Utility */
-       { "Utility",                            N_("Utilities") },
-       { "Utility::Accessibility",             NC_("Menu subcategory of Utilities", "Accessibility") },
-       { "Utility::Archiving",                 NC_("Menu subcategory of Utilities", "Archiving") },
-       { "Utility::Calculator",                NC_("Menu subcategory of Utilities", "Calculator") },
-       { "Utility::Clock",                     NC_("Menu subcategory of Utilities", "Clock") },
-       { "Utility::Compression",               NC_("Menu subcategory of Utilities", "Compression") },
-       { "Utility::FileTools",                 NC_("Menu subcategory of Utilities", "File Tools") },
-       { "Utility::Maps",                      NC_("Menu subcategory of Utilities", "Maps") },
-       { "Utility::Spirituality",              NC_("Menu subcategory of Utilities", "Spirituality") },
-       { "Utility::TelephonyTools",            NC_("Menu subcategory of Utilities", "Telephony Tools") },
-       { "Utility::TextEditor",                NC_("Menu subcategory of Utilities", "Text Editor") },
+       { "Utility",                            "applications-utilities-symbolic", N_("Utilities") },
+       { "Utility::Accessibility",             NULL, NC_("Menu subcategory of Utilities", "Accessibility") },
+       { "Utility::Archiving",                 NULL, NC_("Menu subcategory of Utilities", "Archiving") },
+       { "Utility::Calculator",                NULL, NC_("Menu subcategory of Utilities", "Calculator") },
+       { "Utility::Clock",                     NULL, NC_("Menu subcategory of Utilities", "Clock") },
+       { "Utility::Compression",               NULL, NC_("Menu subcategory of Utilities", "Compression") },
+       { "Utility::FileTools",                 NULL, NC_("Menu subcategory of Utilities", "File Tools") },
+       { "Utility::Maps",                      NULL, NC_("Menu subcategory of Utilities", "Maps") },
+       { "Utility::Spirituality",              NULL, NC_("Menu subcategory of Utilities", "Spirituality") },
+       { "Utility::TelephonyTools",            NULL, NC_("Menu subcategory of Utilities", "Telephony Tools") 
},
+       { "Utility::TextEditor",                NULL, NC_("Menu subcategory of Utilities", "Text Editor") },
        /* TRANSLATORS: this is the menu spec main category for Video */
-       { "Video",                              N_("Video") },
-       { "Video::AudioVideoEditing",           NC_("Menu subcategory of Video", "Editing") },
-       { "Video::Database",                    NC_("Menu subcategory of Video", "Database") },
-       { "Video::DiscBurning",                 NC_("Menu subcategory of Video", "Disc Burning") },
-       { "Video::Player",                      NC_("Menu subcategory of Video", "Players") },
-       { "Video::Recorder",                    NC_("Menu subcategory of Video", "Recorders") },
-       { "Video::TV",                          NC_("Menu subcategory of Video", "TV") },
+       { "Video",                              "folder-videos-symbolic", N_("Video") },
+       { "Video::AudioVideoEditing",           NULL, NC_("Menu subcategory of Video", "Editing") },
+       { "Video::Database",                    NULL, NC_("Menu subcategory of Video", "Database") },
+       { "Video::DiscBurning",                 NULL, NC_("Menu subcategory of Video", "Disc Burning") },
+       { "Video::Player",                      NULL, NC_("Menu subcategory of Video", "Players") },
+       { "Video::Recorder",                    NULL, NC_("Menu subcategory of Video", "Recorders") },
+       { "Video::TV",                          NULL, NC_("Menu subcategory of Video", "TV") },
        /* TRANSLATORS: this is the main category for Add-ons */
-       { "Addons",                             N_("Add-ons") },
-       { "Addons::Fonts",                      NC_("Menu subcategory of Add-ons", "Fonts") },
-       { "Addons::Codecs",                     NC_("Menu subcategory of Add-ons", "Codecs") },
-       { "Addons::InputSources",               NC_("Menu subcategory of Add-ons", "Input Sources") },
-       { "Addons::LanguagePacks",              NC_("Menu subcategory of Add-ons", "Language Packs") },
-       { "Addons::ShellExtensions",            NC_("Menu subcategory of Add-ons", "Shell Extensions") },
-       { "Addons::Localization",               NC_("Menu subcategory of Add-ons", "Localization") },
-       { NULL,                                 NULL }
+       { "Addons",                             "list-add-symbolic", N_("Add-ons") },
+       { "Addons::Fonts",                      NULL, NC_("Menu subcategory of Add-ons", "Fonts") },
+       { "Addons::Codecs",                     NULL, NC_("Menu subcategory of Add-ons", "Codecs") },
+       { "Addons::InputSources",               NULL, NC_("Menu subcategory of Add-ons", "Input Sources") },
+       { "Addons::LanguagePacks",              NULL, NC_("Menu subcategory of Add-ons", "Language Packs") },
+       { "Addons::ShellExtensions",            NULL, NC_("Menu subcategory of Add-ons", "Shell Extensions") 
},
+       { "Addons::Localization",               NULL, NC_("Menu subcategory of Add-ons", "Localization") },
+       { NULL,                                 NULL, NULL }
 };
 
 /**
diff --git a/src/plugins/menu-spec-common.h b/src/plugins/menu-spec-common.h
index 0d98308..a05a127 100644
--- a/src/plugins/menu-spec-common.h
+++ b/src/plugins/menu-spec-common.h
@@ -29,6 +29,7 @@ G_BEGIN_DECLS
 
 typedef struct {
        const gchar *path;
+       const gchar *icon;
        const gchar *text;
 } MenuSpecData;
 
diff --git a/src/plugins/packagekit-common.c b/src/plugins/packagekit-common.c
index 4f3eecd..c4722a4 100644
--- a/src/plugins/packagekit-common.c
+++ b/src/plugins/packagekit-common.c
@@ -85,6 +85,78 @@ packagekit_status_enum_to_plugin_status (PkStatusEnum status)
 }
 
 /**
+ * gs_plugin_packagekit_convert_gerror:
+ */
+gboolean
+gs_plugin_packagekit_convert_gerror (GError **error)
+{
+       GError *error_tmp;
+
+       if (error == NULL)
+               return FALSE;
+       error_tmp = *error;
+       if (error_tmp == NULL)
+               return FALSE;
+
+       /* get a local version */
+       if (error_tmp->domain != PK_CLIENT_ERROR)
+               return FALSE;
+
+       /* daemon errors */
+       if (error_tmp->code <= 0xff) {
+               switch (error_tmp->code) {
+               case PK_CLIENT_ERROR_CANNOT_START_DAEMON:
+               case PK_CLIENT_ERROR_INVALID_FILE:
+               case PK_CLIENT_ERROR_NOT_SUPPORTED:
+                       error_tmp->code = GS_PLUGIN_ERROR_NOT_SUPPORTED;
+                       break;
+               default:
+                       error_tmp->code = GS_PLUGIN_ERROR_FAILED;
+                       break;
+               }
+
+       /* backend errors */
+       } else {
+               switch (error_tmp->code - 0xff) {
+               case PK_ERROR_ENUM_INVALID_PACKAGE_FILE:
+               case PK_ERROR_ENUM_NOT_SUPPORTED:
+               case PK_ERROR_ENUM_PACKAGE_INSTALL_BLOCKED:
+                       error_tmp->code = GS_PLUGIN_ERROR_NOT_SUPPORTED;
+                       break;
+               case PK_ERROR_ENUM_CANNOT_FETCH_SOURCES:
+               case PK_ERROR_ENUM_NO_CACHE:
+               case PK_ERROR_ENUM_NO_MORE_MIRRORS_TO_TRY:
+               case PK_ERROR_ENUM_NO_NETWORK:
+               case PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED:
+                       error_tmp->code = GS_PLUGIN_ERROR_NO_NETWORK;
+                       break;
+               case PK_ERROR_ENUM_BAD_GPG_SIGNATURE:
+               case PK_ERROR_ENUM_CANNOT_INSTALL_REPO_UNSIGNED:
+               case PK_ERROR_ENUM_CANNOT_UPDATE_REPO_UNSIGNED:
+               case PK_ERROR_ENUM_GPG_FAILURE:
+               case PK_ERROR_ENUM_MISSING_GPG_SIGNATURE:
+               case PK_ERROR_ENUM_NO_LICENSE_AGREEMENT:
+               case PK_ERROR_ENUM_NOT_AUTHORIZED:
+               case PK_ERROR_ENUM_RESTRICTED_DOWNLOAD:
+                       error_tmp->code = GS_PLUGIN_ERROR_NO_SECURITY;
+                       break;
+               case PK_ERROR_ENUM_NO_SPACE_ON_DEVICE:
+                       error_tmp->code = GS_PLUGIN_ERROR_NO_SPACE;
+                       break;
+               case PK_ERROR_ENUM_CANCELLED_PRIORITY:
+               case PK_ERROR_ENUM_TRANSACTION_CANCELLED:
+                       error_tmp->code = GS_PLUGIN_ERROR_CANCELLED;
+                       break;
+               default:
+                       error_tmp->code = GS_PLUGIN_ERROR_FAILED;
+                       break;
+               }
+       }
+       error_tmp->domain = GS_PLUGIN_ERROR;
+       return TRUE;
+}
+
+/**
  * gs_plugin_packagekit_add_results:
  */
 gboolean
@@ -153,7 +225,7 @@ gs_plugin_packagekit_add_results (GsPlugin *plugin,
                gs_app_set_summary (app,
                                    GS_APP_QUALITY_LOWEST,
                                    pk_package_get_summary (package));
-               gs_app_set_management_plugin (app, "PackageKit");
+               gs_app_set_management_plugin (app, "packagekit");
                gs_app_set_version (app, pk_package_get_version (package));
                switch (pk_package_get_info (package)) {
                case PK_INFO_ENUM_INSTALLED:
diff --git a/src/plugins/packagekit-common.h b/src/plugins/packagekit-common.h
index c99390b..fda96ab 100644
--- a/src/plugins/packagekit-common.h
+++ b/src/plugins/packagekit-common.h
@@ -36,6 +36,7 @@ gboolean      gs_plugin_packagekit_add_results        (GsPlugin       *plugin,
                                                         GList          **list,
                                                         PkResults      *results,
                                                         GError         **error);
+gboolean       gs_plugin_packagekit_convert_gerror     (GError         **error);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]