commit/readFeeds: 3 new changesets

  • From: commits-noreply@xxxxxxxxxxxxx
  • To: nvda-addons-commits@xxxxxxxxxxxxx
  • Date: Sun, 28 Jul 2019 17:34:47 +0000 (UTC)

3 new commits in readFeeds:

https://bitbucket.org/nvdaaddonteam/readfeeds/commits/2ff7b3b7ed6f/
Changeset:   2ff7b3b7ed6f
Branch:      None
User:        norrumar
Date:        2019-07-14 06:33:08+00:00
Summary:     Merge branch 'stable'

Affected #:  1 file

diff --git a/addon/locale/pl/LC_MESSAGES/nvda.po 
b/addon/locale/pl/LC_MESSAGES/nvda.po
index 915aff8..ad1aec7 100644
--- a/addon/locale/pl/LC_MESSAGES/nvda.po
+++ b/addon/locale/pl/LC_MESSAGES/nvda.po
@@ -8,7 +8,7 @@ msgstr ""
 "Project-Id-Version: readFeeds 1.0-dev\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2013-11-16 13:26+0100\n"
-"PO-Revision-Date: 2018-09-22 17:09+0100\n"
+"PO-Revision-Date: 2019-07-06 22:16+0100\n"
 "Last-Translator: Zvonimir Stanečić <zvonimirek222@xxxxxxxxxxxxx>\n"
 "Language-Team: Polish <killer@xxxxxxxxxxxx>\n"
 "Language: pl\n"
@@ -99,9 +99,8 @@ msgid "S&et default"
 msgstr "U&staw domyślnie"
 
 #. Translators: The label of a button to open a folder containing a backup of 
feeds.
-#, fuzzy
 msgid "Open &folder containing a backup of feeds"
-msgstr "Wybierz katalog do zapisywania kopii swoich kanałów osobistych"
+msgstr "otwórz &folder zawierający kopię twoich osobistych kanałów"
 
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"


https://bitbucket.org/nvdaaddonteam/readfeeds/commits/abea2030657e/
Changeset:   abea2030657e
Branch:      None
User:        norrumar
Date:        2019-07-28 11:15:44+00:00
Summary:     Merge branch 'master' into xmltree

Affected #:  45 files

diff --git a/addon/doc/bg/readme.md b/addon/doc/bg/readme.md
index 2f0af22..8bf4d0f 100644
--- a/addon/doc/bg/readme.md
+++ b/addon/doc/bg/readme.md
@@ -1,6 +1,7 @@
 # Четене на емисии (Read Feeds) #
 
 * Автори: Noelia Ruiz Martínez, Mesar Hameed
+* Съвместимост с NVDA: от 2018.3 до 2019.1
 * Изтегляне на [стабилна версия][1]
 * Изтегляне на [тестова версия][2]
 
@@ -14,7 +15,7 @@ RSS формат с NVDA.  Източниците няма да бъдат оп
 Ако сте използвали предишна версия на тази добавка и вече имате папка с име
 RSS или personalFeeds във вашата папка с потребителски настройки за NVDA,
 когато инсталирате текущата версия, ще попаднете на диалог, който ще ви
-попита дали искате да обновите вашата добавка или да инсталирате на чисто.
+попита дали искате да обновите добавката или да инсталирате на чисто.
 Изберете обновяване, за да съхраните вашите запазени източници и да
 продължите да ги използвате в новоинсталираната версия на readFeeds.
 
@@ -31,17 +32,18 @@ RSS или personalFeeds във вашата папка с потребител
 
 * Филтриране по: Текстово поле за търсене на предходно запазени емисии.
 * Списък на запазените емисии.
-* List of articles: Opens a dialog which presents the articles list from
-  your current feed. Select the article you want to read and press Enter or
-  Open web page of selected article button to open the corresponding page in
-  your browser. Press About article button to open a dialog showing title
-  and link of the selected article; from this dialog, you'll be able to copy
-  this info to the clipboard.
+* Списък със статиите: Отваря диалогов прозорец, който представя списъка със
+  статии от текущата ви емисия. Изберете статията, която искате да
+  прочетете, и натиснете ENTER или задействайте бутона "Отвори уеб
+  страницата на избраната статия", за да отворите съответната страница във
+  вашия браузър. Задействайте бутона "Относно статията", за да отворите
+  диалогов прозорец, показващ заглавието и връзката на избраната статия. От
+  този диалогов прозорец ще можете да копирате информацията в клипборда.
 * Отвори емисията: Отваря избраната емисия в приложението по подразбиране.
 * Нов: Отваря се диалогов прозорец с текстово поле за въвеждане адреса на
-  нова емисия. Ако адресът е валиден и емисията може да бъдат записани,
-  името й, въз основа на заглавието на емисията, ще се появи в дъното на
-  списъка с информационни канали.
+  нова емисия. Ако адресът е валиден и емисията може да бъде записана, името
+  й, въз основа на заглавието на емисията, ще се появи в дъното на списъка с
+  информационни канали.
 * Преименувай: Отваря диалогов прозорец с текстово поле за преименуване на
   избраната емисия.
 * Изтрий: Отваря диалогов прозорец за изтриване на избраните емисии след
@@ -49,6 +51,9 @@ RSS или personalFeeds във вашата папка с потребител
 * Задай по подразбиране: Задава избраната емисия като такава по
   подразбиране, така че нейните статии могат да бъдат достъпвани посредством
   жестовете на NVDA.
+* Open folder containing a backup of feeds: Opens a folder which may contain
+  a backup of feeds. This can be useful to explore and delete feeds which
+  shouldn't be imported when the add-on is updated.
 * Затвори: Затваря диалоговия прозорец с емисиите.
 
 ##### Бележки #####
@@ -56,13 +61,13 @@ RSS или personalFeeds във вашата папка с потребител
 * Ако бъде създадена емисия с име "tempFeed", моля, преименувайте я, тъй
   като този файл може да бъде заместен при необходимост от създаването на
   емисия с вече съществуващо име.
-* Емисията зададена по подразбиране, не може да бъде премахната. Емисията
+* Емисията, зададена по подразбиране, не може да бъде премахната. Емисията
   "addressFile" ще бъде използвана като такава по подразбиране при нулиране
   на настройките, затова тя не може да бъде премахната.
 
 ####Копирай папката с емисиите... ####
 
-Отваря диалогов прозорец за да изберете папка, където можете да запишете
+Отваря диалогов прозорец, за да изберете папка, където можете да запишете
 папката "personalFeeds" с вашите информационни канали. По подразбиране
 избраната папка е директорията с конфигурационния файл на NVDA, където ще се
 създаде папката "personalFeeds".
@@ -70,7 +75,7 @@ RSS или personalFeeds във вашата папка с потребител
 #### Възстанови емисиите... ####
 
 Отваря диалогов прозорец за избор на папка, която заменя вашите емисии в
-папката "personalFeeds". Уверете се, че указвате папка съдържаща URL адреси
+папката "personalFeeds". Уверете се, че указвате папка, съдържаща URL адреси
 на емисии.
 
 ### Клавишни команди: ###
@@ -87,20 +92,39 @@ RSS или personalFeeds във вашата папка с потребител
 
 ## Уведомления: ##
 
-* Когато заглавието или URL адреса са били копирани.
+* Когато заглавието или URL адресът са били копирани.
 * Когато не може да се осъществи свързване/обновяване на емисиите, или URL
-  адреса не съответства на валидна емисия.
+  адресът не съответства на валидна емисия.
 * NVDA ще изведе съобщение за грешка, ако не е възможно да се архивира или
   възстанови папката "personalFeeds".
 * Заглавието на диалога за списъка със статиите показва името на избраната
   емисия и номера на наличните статии.
 
-## Changes for 5.0 ##
+## Changes for 7.0 ##
 
-* The articles list dialog has been enhanced.
-* Compatible with NVDA 2018.3 or later (required).
-* If needed, you can download the [last version compatible with NVDA
-  2017.3][3].
+* The Feeds dialog includes a button to open a folder which may contain a
+  backup of feeds.
+* When using the edit box to filter feeds, if no results are found, the list
+  of feeds and other controls are disabled, so that NVDA doesn't report
+  "unknown" in the empty list.
+* If the list of articles dialog can't be shown, for example due to errors
+  in the feed, NVDA will raise an error, so that the feeds dialog can be
+  used without restarting NVDA.
+
+## Промени във версия 6.0 ##
+
+* Когато е обновена емисията по подразбиране и тя спре да работи поради
+  проблеми със сървъра, предишните статии не биват изтрити и могат да бъдат
+  прочетени със съответните клавишни комбинации.
+* Отстранен е проявил се отново проблем (регресия): Емисията по подразбиране
+  пак може да се актуализира два пъти.
+
+## Промени във версия 5.0 ##
+
+* Диалогът за списъците със статии е подобрен.
+* Съвместима с NVDA 2018.3 и по-нови версии (изисква се).
+* Ако е необходимо, можете да изтеглите [последната версия, съвместима с
+  NVDA 2017.3][3].
 
 ## Промени във версия 4.0 ##
 

diff --git a/addon/doc/da/readme.md b/addon/doc/da/readme.md
index f47480c..7eef854 100644
--- a/addon/doc/da/readme.md
+++ b/addon/doc/da/readme.md
@@ -1,6 +1,7 @@
 # Read Feeds #
 
 * Forfattere: Noelia Ruiz Martínez, Mesar Hameed
+* NVDA-kompatibilitet: 2018.3 til 2019.1
 * Download [stabil version][1]
 * download [udviklingsversion][2]
 
@@ -32,12 +33,12 @@ de følgende menupunkter er tilgængelige:
 * Filtrér efter: Et redigeringsfelt til at søge i tidligere gemte
   nyhedskanaler.
 * En liste over de gemte nyhedskanaler.
-* List of articles: Opens a dialog which presents the articles list from
-  your current feed. Select the article you want to read and press Enter or
-  Open web page of selected article button to open the corresponding page in
-  your browser. Press About article button to open a dialog showing title
-  and link of the selected article; from this dialog, you'll be able to copy
-  this info to the clipboard.
+* Liste over artikler: Åbner en dialog, der præsenterer artikellisten fra
+  din nuværende kanal. Vælg den artikel, du vil læse, og tryk på Enter eller
+  Åbn webside for den valgte artikelknap for at åbne den tilsvarende side i
+  din browser. Tryk på Om artiklen knap for at åbne en dialog med titel og
+  link for den valgte artikel; Fra denne dialog kan du kopiere denne
+  information til udklipsholderen.
 * Åbn nyhedskanal: Åbner den markerede kanal i standardprogrammet.
 * Ny: Åbner en dialogboks med et redigeringsfelt til at indtaste adressen på
   en ny nyhedskanal. Hvis adressen er gyldig og kanalen kan gemmes, vises
@@ -48,6 +49,10 @@ de følgende menupunkter er tilgængelige:
   bekræftelse.
 * Sæt som standard: Indstiller den valgte nyhedskanal som standard, så dens
   artikler kan tilgås med NVDAs inputbevægelser.
+* Åbn mappen med sikkerhedskopierne for dine nyhedskanaler: Åbner en mappe,
+  der indeholder sikkerhedskopier af dine nyhedskanaler. Dette kan være
+  nyttigt, hvis du evt. vil slette kanaler der ikke skal importeres, når
+  tilføjelsen opdateres.
 * Luk: Lukker dialogen Nyhedskanaler.
 
 ##### Noter #####
@@ -94,11 +99,29 @@ URL-adresser på nyhedskanaler.
 * Titlen på dialogen der viser listen over artikler viser navnet på den
   aktuelle kanal, samt antallet af artikler til rådighed.
 
-## Changes for 5.0 ##
+## Ændringer i7.0 ##
 
-* The articles list dialog has been enhanced.
-* Compatible with NVDA 2018.3 or later (required).
-* If needed, you can download the [last version compatible with NVDA
+* Dialogboksen "Nyhedskanaler" indeholder en knap for at åbne en mappe, der
+  indeholder en sikkerhedskopi af nyhedskanaler.
+* Når du bruger redigeringsboksen til at filtrere feeds, og hvis der ikke
+  findes nogen resultater, er listen over kanaler og andre kontroller
+  deaktiveret, så NVDA ikke rapporterer "ukendt" i den tomme liste.
+* Hvis dialogen "Liste over artikler" ikke kan vises, for eksempel på grund
+  af fejl med kanalen, vil NVDA fejle, så dialogen kan bruges uden at
+  genstarte NVDA.
+
+## Ændringer i 6.0 ##
+
+* Når standardkanalen er opdateret, og det ophører med at fungere på grund
+  af serverproblemer, fjernes de tidligere artikler ikke og kan læses med de
+  tilsvarende tastetryk.
+* Rettede regression: Standardkanalen kan opdateres to gange igen.
+
+## Ændringer i 5.0 ##
+
+* Dialogen med listen over artikler er blevet forbedret.
+* Kompatibel med NVDA 2018.3 eller nyere (påkrævet).
+* Hvis nødvendigt, kan du hente [den sidste version kompatibel med NVDA
   2017.3][3].
 
 ## Ændringer i4.0  ##

diff --git a/addon/doc/de/readme.md b/addon/doc/de/readme.md
index 41b30e6..34c18f1 100644
--- a/addon/doc/de/readme.md
+++ b/addon/doc/de/readme.md
@@ -1,8 +1,9 @@
 # RSS-Feed-Reader #
 
 * Authors: Noelia Ruiz Martínez, Mesar Hameed
+* NVDA-Kompatibilität: 2018.3 bis 2019.1
 * [Stabile Version herunterladen][1]
-* [Entwicklungsversion herunterladen][2]
+* [Entwicklerversion herunterladen][2]
 
 Diese Erweiterung bietet eine einfache Möglichkeit, RSS-Feeds in den
 Formaten Atom oder RSS mit NVDA zu lesen. Die Feeds werden nicht automatisch
@@ -15,15 +16,15 @@ Wenn Sie eine frühere Version dieser Erweiterung verwendet 
haben und in
 Ihrem persönlichen NVDA-Konfigurationsordner ein RSS- oder
 personalFeeds-Ordner vorhanden ist, wird bei der Installation der aktuellen
 Version ein Dialogfeld angezeigt. In diesem Dialog werden Sie gefragt, ob
-Sie ein Upgrade oder eine Installation durchführen möchten.  Wählen Sie
-update, um Ihre gespeicherten Feeds zu behalten und sie in der neu
-installierten Version von RSS-Feed-Reader weiter zu verwenden.
+Sie eine Aktualisierung oder eine Installation durchführen möchten.  Wählen
+Sie aktualisieren, um Ihre gespeicherten Feeds zu behalten und sie in der
+neu installierten Version von RSS-Feed-Reader weiter zu verwenden.
 
 ## Befehle: ##
 
 ### Feed-Reader-Menü ###
 
-Sie können auf das Untermenü RSS-Feed-Reader aus dem nvda-Menü, Untermenü
+Sie können auf das Untermenü RSS-Feed-Reader aus dem NVDA-Menü, Untermenü
 Extras zugreifen. Es stehen folgende Menüoptionen zur Verfügung:
 
 #### RSS-Feeds... ####
@@ -50,34 +51,39 @@ Extras zugreifen. Es stehen folgende Menüoptionen zur 
Verfügung:
 * Als standard festlegen: Legt den ausgewählten RSS-Feed als Standard fest,
   so dass auf seine Artikel mit den Tastenkürzel von NVDA zugegriffen werden
   kann.
+* Backup Ordner öffnen: Öffnet einen Ordner, in welchem eine Sicherung der
+  RSS Feeds enthalten sein kann. Nützlich um vorhandene RSS Feeds zu prüfen
+  und diejenigen  zu löschen, die bei einer Aktualisierung der Erweiterung
+  nicht importiert werden sollen. 
 * Schließen: Schließt den Dialog.
 
 ##### Hinweise #####
 
 * Wenn ein Feed namens tempFeed erstellt wird, benennen Sie ihn bitte
-  um. Sie könnten diese Datei bei Bedarf ersetzen, um einen Feed zu
-  erstellen, dessen Name bereits existiert.
+  um. Andernfalls könnte er ersetzt werden, wenn erneut ein Ordner mit
+  diesem Namen erstellt wird. 
 * Der als Standard eingestellte Feed kann nicht entfernt werden. Der
   AddressFile-Feed wird als Standard verwendet, wenn die Konfiguration
   zurückgesetzt wird. Daher kann dieser Ordner nicht gelöscht werden.
 
 ####Artikelordner kopieren...####
 
-Öffnet einen Dialog zur Auswahl eines Ordners, in dem Sie das
-personalFeeds-Verzeichnis Ihrer Artikel speichern können. Standardmäßig ist
-der ausgewählte Ordner das Konfigurationsverzeichnis von NVDA.
+Öffnet einen Dialog, in dem Sie einen Ordner auswählen können, um Ihre
+persönlichen RSS Feed Artikel zu speichern. Standardmäßig ist der
+ausgewählte Ordner das Konfigurationsverzeichnis von NVDA und der Ordner
+heißt personalFeeds.
 
 #### RSS-Feeds wiederherstellen... ####
 
-Öffnet einen Dialog zur Auswahl eines Ordners, der Ihre Feeds im
-personalFeeds-Ordner ersetzt. Stellen Sie sicher, dass Sie einen Ordner mit
-Feed-URLs auswählen.
+Öffnet einen Dialog um einen Ordner zu wählen, der ihren Ordner mit
+persönlichen FEEDS ersetzt. Stellen Sie sicher, dass Sie einen Ordner
+wählen, der URLs von RSS Feeds enthält.
 
 ### Tastenkombinationen: ###
 
 * STRG+Umschalt+NVDA+Leertaste: Sagt die aktuelle Adresse des Artikels
   an. Zweimaliges Drücken öffnet die Webseite des Artikels.
-* STRG+Umschalt+NVDA+8: Das ausgewählte RSS-Feed wir neugeladen und der
+* STRG+Umschalt+NVDA+8: Der ausgewählte RSS-Feed wird neu geladen und der
   aktuellste Titel wird angesagt.
 * Strg+Umschalt+NVDA+I: Sagt den aktuellen Feed-Titel und -Link an. Durch
   zweimaliges Drücken wird der Titel und der zugehörige Link in die
@@ -95,6 +101,26 @@ Feed-URLs auswählen.
 * Im Titel des Dialogs für die Artikellisten werden der Name des
   ausgewählten Feeds und die Anzahl der verfügbaren Artikel angezeigt.
 
+## Änderungen bis 7.0 ##
+
+* Der RSS Feeds Dialog wird mit einen Schalter erweitert, um einen
+  Backup-Ordner zu öffnen, der gesicherte Feeds enthalten kann. 
+* Wenn Sie das Eingabeveld verwenden, um RSS Feeds zu filtern und keine
+  Ergebnisse gefunden werden, sind die Liste der Feeds und andere
+  Dialogelemente nicht vorhanden so dass NVDA nicht mehr die Meldung
+  "unbekannt" in der leeren Liste nennt. 
+* Wenn die Artikelliste nicht gezeigt werden kann, beispielsweise wegen
+  Fehlern beim Rss Feed, wird NVDA einen Fehler auslösen. Dadurch können Sie
+  den RSS Feed Dialog nutzen, ohne NVDA neu starten zu müssen. 
+
+## Änderungen bis 6.0 ##
+
+* Wenn der Standardfeed aktualisiert wurde und er aufgrund von
+  Serverproblemen nicht mehr funktioniert, werden die vorherigen Artikel
+  nicht gelöscht und können mit den entsprechenden Tastenkombinationen
+  gelesen werden.
+* Fehler behoben: Der Standardfeed kann noch zweimal aktualisiert werden.
+
 ## Änderungen für 5.0 ##
 
 * Der Dialog der Artikelliste wurde erweitert.

diff --git a/addon/doc/es/readme.md b/addon/doc/es/readme.md
index 1b24822..8f85226 100644
--- a/addon/doc/es/readme.md
+++ b/addon/doc/es/readme.md
@@ -1,6 +1,7 @@
 # Read Feeds #
 
-* Authors: Noelia Ruiz Martínez, Mesar Hameed
+* Autores: Noelia Ruiz Martínez, Mesar Hameed
+* Compatibilidad con NVDA: de 2018.3 a 2019.1
 * Descargar [versión estable][1]
 * Descargar [versión de desarrollo][2]
 
@@ -50,6 +51,10 @@ Abre un diálogo con los siguientes controles:
   una confirmación.
 * Configurar predeterminado: configura el feed seleccionado como el
   predeterminado, así que su artículo puede accederse con gestos de NVDA.
+* Abrir carpeta que contiene una copia de seguridad de las fuentes: Abre una
+  carpeta que podría contener una copia de seguridad de las fuentes. Esto
+  puede ser útil para explorar y eliminar fuentes que no deberían importarse
+  cuando el complemento se actualice.
 * Cerrar: cierra el diálogo Feeds.
 
 ##### Notas #####
@@ -57,7 +62,7 @@ Abre un diálogo con los siguientes controles:
 * Si se crea un feed llamado tempFeed, por favor renómbralo, ya que este
   fichero podría reemplazarse cuando sea necesario crear un feed cuyo nombre
   ya exista.
-*  El feed configurado como el predeterminado puede eliminarse. el feed
+* El feed configurado como el predeterminado puede eliminarse. el feed
   addressFile se utilizará como el predeterminado cuando la configuración se
   reinicie, así no puede eliminarse.
 
@@ -95,6 +100,25 @@ feeds.
 * El título del diálogo de lista de artículos muestra el nombre del feed
   seleccionado y el número de elementos disponibles.
 
+## Cambios para 7.0 ##
+
+* El diálogo Fuentes incluye un botón para abrir una carpeta que podría
+  contener una copia de seguridad de las fuentes.
+* Al usar el cuadro de edición para filtrar fuentes, si no se encuentran
+  resultados, la lista de fuentes y otros controles están deshabilitados, de
+  manera que NVDA no anuncie "desconocido" en la lista vacía.
+* Si el diálogo de lista de artículos no se puede mostrar, por ejemplo
+  debido a errores en la fuente, NVDA disparará un error, de forma que el
+  diálogo de fuentes pueda usarse sin reiniciar NVDA.
+
+## Cambios para 6.0 ##
+
+* Cuando se refresca el feed por defecto y deja de funcionar por errores en
+  el servidor, los artículos anteriores no se borran y pueden leerse con los
+  atajos correspondientes.
+* Solucionada regresión: El feed por defecto puede actualizarse dos veces
+  nuevamente.
+
 ## Cambios para 5.0 ##
 
 * El diálogo lista de artículos se ha mejorado.

diff --git a/addon/doc/fi/readme.md b/addon/doc/fi/readme.md
index 6b45a3e..ffa520d 100644
--- a/addon/doc/fi/readme.md
+++ b/addon/doc/fi/readme.md
@@ -1,6 +1,7 @@
 # Lue syötteet #
 
 * Tekijät: Noelia Ruiz Martínez, Mesar Hameed
+* NVDA-yhteensopivuus: 2018.3-2019.1
 * Lataa [vakaa versio][1]
 * Lataa [kehitysversio][2]
 
@@ -47,6 +48,10 @@ Avaa valintaikkunan, jossa on seuraavat säätimet:
   valitun syötteen.
 * Aseta oletukseksi: Asettaa valitun syötteen oletukseksi, jotta sen
   artikkeleihin pääsee NVDA:n syötekomennoilla.
+* Avaa syötteiden varmuuskopiokansio: Avaa kansion, joka saattaa sisältää
+  syötteiden varmuuskopion. Tästä voi olla hyötyä sellaisten syötteiden
+  tutkimisessa ja poistamisessa, joita ei haluta tuotavan lisäosaa
+  päivitettäessä.
 * Sulje: Sulkee Syötteet-valintaikkunan.
 
 ##### Huomautuksia #####
@@ -90,6 +95,26 @@ vain syötteiden URL-osoitteita sisältävän kansion.
 * Valitun syötteen nimi ja saatavilla olevien artikkeleiden määrä näytetään
   Artikkeliluettelo-valintaikkunan otsikossa.
 
+## Muutokset versiossa 7.0 ##
+
+* Syötteet-valintaikkunassa on painike, jolla voidaan avata mahdollisen
+  syöttteiden varmuuskopion sisältävä kansio.
+* Kun muokkauskenttää käytetään syötteiden suodattamiseen ja jos
+  hakutuloksia ei löydy, syötteiden luettelo sekä muut säätimet poistetaan
+  käytöstä, jottei NVDA sano "tuntematon" kohdistuksen siirtyessä tähän
+  tyhjään luetteloon.
+* Mikäli Artikkeliluettelo-valintaikkunaa ei voida näyttää, esim. syötteessä
+  olevien virheiden vuoksi, NVDA ilmoittaa virheestä, jotta
+  Syötteet-valintaikkunaa voidaan käyttää ilman NVDA:n
+  uudelleenkäynnistystä.
+
+## Muutokset versiossa 6.0 ##
+
+* Kun oletussyöte on päivitetty ja se lakkaa toimimasta palvelinongelmien
+  vuoksi, aiempia artikkeleita ei poisteta, vaan niitä voidaan lukea
+  tarkoitukseen varatuilla näppäinkomennoilla.
+* Oletussyöte voidaan taas päivittää kahdesti.
+
 ## Muutokset versiossa 5.0 ##
 
 * Artikkeliluettelovalintaikkunaa on paranneltu.

diff --git a/addon/doc/fr/readme.md b/addon/doc/fr/readme.md
index c4e5e62..487b486 100644
--- a/addon/doc/fr/readme.md
+++ b/addon/doc/fr/readme.md
@@ -1,22 +1,23 @@
 # Read Feeds #
 
 * Auteurs : Noelia Ruiz Martínez, Mesar Hameed
+* Compatibilité NVDA: 2018.3 à 2019.1
 * Télécharger [version stable][1]
 * Télécharger [version de développement][2]
 
-Ce module complémentaire fournit un moyen simple de lire les flux aux
-formats Atom ou RSS à l'aide de NVDA. Les flux ne sont pas actualisées
-automatiquement.  Ci-dessous lorsque nous mentionnons flux, nous voulons
-dire que les deux signifient flux RSS et ATOM.
+Cette extension fournit un moyen simple de lire les flux aux formats Atom ou
+RSS à l'aide de NVDA. Les flux ne sont pas actualisés automatiquement.
+Ci-dessous lorsque nous mentionnons flux, nous voulons dire que les deux
+signifient flux RSS et ATOM.
 
 ## Installation ou Mise à jour : ##
 
-Si vous utilisiez une version antérieure de ce module complémentaire, il y a
-un dossier RSS ou personalFeeds dans votre dossier de configuration
-personnel de NVDA, lorsque vous installez la version actuelle, une boîte de
-dialogue vous demandera si vous souhaitez mettre à jour ou installer.
-Choisissez mise à jour pour préserver vos flux enregistrés et pour continuer
-à les utiliser dans la nouvelle version installée de readFeeds.
+Si vous utilisiez une version antérieure de cette extension, il y a un
+dossier RSS ou personalFeeds dans votre dossier de configuration personnel
+de NVDA, lorsque vous installez la version actuelle, une boîte de dialogue
+vous demandera si vous souhaitez mettre à jour ou installer.  Choisissez
+mise à jour pour préserver vos flux enregistrés et pour continuer à les
+utiliser dans la nouvelle version installée de readFeeds.
 
 ## Commandes : ##
 
@@ -51,6 +52,9 @@ Ouvre une boîte de dialogue avec les contrôles suivants :
   après confirmation.
 * Définir par défaut : Définit le flux sélectionné comme valeur par défaut,
   afin que ses articles soient accessibles avec les gestes de NVDA.
+* Open folder containing a backup of feeds: Opens a folder which may contain
+  a backup of feeds. This can be useful to explore and delete feeds which
+  shouldn't be imported when the add-on is updated.
 * Fermer : Ferme la boîte de dialogue Flux.
 
 ##### Notes #####
@@ -95,6 +99,25 @@ contenant des URL de flux.
 * La boîte de dialogue affiche Le titre de la Liste de l'article le nom de
   flux sélectionné et le nombre d'éléments disponibles.
 
+## Changes for 7.0 ##
+
+* The Feeds dialog includes a button to open a folder which may contain a
+  backup of feeds.
+* When using the edit box to filter feeds, if no results are found, the list
+  of feeds and other controls are disabled, so that NVDA doesn't report
+  "unknown" in the empty list.
+* If the list of articles dialog can't be shown, for example due to errors
+  in the feed, NVDA will raise an error, so that the feeds dialog can be
+  used without restarting NVDA.
+
+## Changements pour la version 6.0 ##
+
+* Lorsque le flux par défaut a été mis à jour et qu'il cesse de fonctionner
+  en raison de problèmes de serveur, les articles précédents ne sont pas
+  supprimés et peuvent être lus à l'aide des frappes correspondantes.
+* Correction de la régression : Le flux par défaut peut être mis à jour deux
+  fois.
+
 ## Changements pour la version 5.0 ##
 
 * La boîte de dialogue Liste des articles a été améliorée.
@@ -122,8 +145,8 @@ contenant des URL de flux.
 
 ## Changements pour la version 2.0 ##
 
-* L'aide du module complémentaire est disponible à partir du Gestionnaire de
-  modules complémentaires.
+* L'aide de l'extension est disponible à partir du Gestionnaire
+  d'extensions.
 
 ## Changements pour la version 1.0 ##
 

diff --git a/addon/doc/gl/readme.md b/addon/doc/gl/readme.md
index 8b5e809..ceda41a 100644
--- a/addon/doc/gl/readme.md
+++ b/addon/doc/gl/readme.md
@@ -1,6 +1,7 @@
 # Read Feeds #
 
 * Autores: Noelia Ruiz Martínez, Mesar Hameed
+* Compatibilidade con NVDA: da 2018.3 á 2019.1
 * Descargar [versión estable][1]
 * Descargar [versión de desenvolvemento][2]
 
@@ -48,6 +49,10 @@ Abre un diálogo cos seguintes controis:
   confirmación.
 * Configurar predeterminado: configura o feed selecionado coma o
   predeterminado, así que o seu artigo pode acederse cos xestos do NVDA.
+* Abrir cartafol que contén unha copia de seguridade das fontes: Abre un
+  cartafol que podería conter unha copia de seguridade das fontes. Isto
+  podería ser útil para explorar e eliminar fontes que non deberían
+  importarse cando o complemento se actualice.
 * Pechar: pecha o diálogo Feeds.
 
 ##### Notas #####
@@ -93,6 +98,25 @@ feeds.
 * O título do diálogo da listaxe de artigos amopsa o nome do feed
   selecionado e o número de elementos dispoñibles.
 
+## Cambios para 7.0 ##
+
+* O diálogo Fontes contén un botón para abrir un cartafol que podería conter
+  unha copia de seguridade das fontes.
+* Ao usar a caixa de edición para filtrar fontes, se non se atopan
+  resultados, amosaranse a lista de feeds e outros controis, de tal modo que
+  NVDA non anuncie "Descoñecido" na lista baleira.
+* Se o diálogo lista de artículos non se pode amosar, debido a erros no
+  feed, por exemplo, NVDA disparará un erro, de modo que o diálogo de fontes
+  se poida usar sen reiniciar NVDA.
+
+## Cambios para 6.0 ##
+
+* Cando se refresca o feed por omisión e deixa de funcionar por problemas no
+  servidor, os artigos anteriores non se borran e poden lerse coas ordes
+  correspondentes.
+* Solucionada regresión: O feed por defecto pódese actualizar dúas veces
+  novamente.
+
 ## Cambios para 5.0 ##
 
 * Mellorouse o diálogo listaxe de artigos.

diff --git a/addon/doc/hr/readme.md b/addon/doc/hr/readme.md
index 0834a6a..0ee317d 100644
--- a/addon/doc/hr/readme.md
+++ b/addon/doc/hr/readme.md
@@ -1,6 +1,7 @@
 # Čitaj sažetke #
 
 * Autori: Noelia Ruiz Martínez, Mesar Hameed 
+* NVDA compatibility: 2018.3 to 2019.1
 * Preuzmi [stabilnu inačicu][1]
 * Preuzmi [razvojnu inačicu][2]
 
@@ -47,6 +48,9 @@ Otvara dijaloški okvir sa sljedećim kontrolama:
   brisanja.
 * Postavi kao zadani: Postavlja odabrani sažetak kao zadani, tako da se tim
   člancima može pristupiti koristeći NVDA geste.
+* Open folder containing a backup of feeds: Opens a folder which may contain
+  a backup of feeds. This can be useful to explore and delete feeds which
+  shouldn't be imported when the add-on is updated.
 * Zatvori: Zatvara dijaloški okvir Sažetaka.
 
 ##### Napomene #####
@@ -90,6 +94,24 @@ sažeci. Provjerite jeste li učitali mapu koja sadrži adrese 
sažetaka.
 * Popis naslova članaka prikazuje ime odabranog sažetka i broj dostupnih
   stavki.
 
+## Changes for 7.0 ##
+
+* The Feeds dialog includes a button to open a folder which may contain a
+  backup of feeds.
+* When using the edit box to filter feeds, if no results are found, the list
+  of feeds and other controls are disabled, so that NVDA doesn't report
+  "unknown" in the empty list.
+* If the list of articles dialog can't be shown, for example due to errors
+  in the feed, NVDA will raise an error, so that the feeds dialog can be
+  used without restarting NVDA.
+
+## Changes for 6.0 ##
+
+* When the default feed has been updated and it stops working due to server
+  issues, the previous articles aren't deleted and can be read with the
+  corresponding keystrokes.
+* Fix regression: The default feed can be updated twice again.
+
 ## Changes for 5.0 ##
 
 * The articles list dialog has been enhanced.

diff --git a/addon/doc/it/readme.md b/addon/doc/it/readme.md
new file mode 100644
index 0000000..6f9caf4
--- /dev/null
+++ b/addon/doc/it/readme.md
@@ -0,0 +1,153 @@
+# Read Feeds #
+
+* Autori: Noelia Ruiz Martínez, Mesar Hameed
+* Compatibilità con NVDA: dalla 2018.3 alla  2019.1
+* Scarica la [versione stabile][1]
+* Scarica la [versione in sviluppo][2]
+
+Questo componente aggiuntivo fornisce un modo semplice per leggere i feed
+nel formato Atom o RSS usando NVDA. I feed non verranno aggiornati
+automaticamente. Quando si menzionano i feed, si intendono sia i feed RSS
+che feed ATOM.
+
+## Installazione e aggiornamento: ##
+
+Se avete installato una versione precedente di questo componente aggiuntivo,
+e sono presenti le cartelle personalFeed o RSS nella cartella di
+configurazione di NVDA, un messaggio di dialogo vi chiederà se si vuol
+importare le cartelle personali durante l'aggiornamento.
+
+## Comandi rapidi: ##
+
+### Il Menu di Read Feeds ###
+
+Si può accedere al sottomenu Gestore Feed dal menu NVDA, Strumenti.  Le voci
+del sottomenu sono:
+
+#### Feeds... ####
+
+Apre una finestra con i seguenti controlli:
+
+* Filtra per: un campo editazione per la ricerca tra i feed salvati.
+* Un elenco dei feed salvati.
+* Elenco degli articoli: apre una finestra che presenta l'elenco degli
+  articoli del feed selezionato. Seleziona l'articolo che ti interessa
+  leggere, quindi premere Invio o il pulsante Apri feed per aprire
+  l'articolo con il tuo browser predefinito. Premendo il pulsante
+  Informazioni Articolo è possibile visualizzare il link ed il titolo
+  dell'articolo selezionato. Queste informazioni possono essere copiate
+  negli appunti. 
+* Apri feed: apre il feed nell'aplicazione predefinita.
+* Nuovo: apre una finestra per inserire un nuovo indirizzo feed. Se
+  l'indirizzo è valido ed il feed può esser salvato, il nome del  feed
+  appare nel fondo dell'elenco feed.
+* Rinomina: apre una finestra dove è possibile rinominare il feed.
+* Elimina: apre una finestra che consente di eliminare un feed con previa
+  converma.
+* Imposta predefinito: permette di impostare il feed selezionato come
+  predefinito, in modo che il feed selezionato si potrà anche aprire con i
+  comandi di NVDA.
+* Cartella backup: apre una cartella che contiene feed precedentemente
+  salvati. Può essere utile per cancellare feed non più necessari che non si
+  vogliono caricare durante l'aggiornamento del componente.
+* Chiudi: chiude la finestra dei feed.
+
+##### Nota: #####
+
+* Se è presente un feed chiamato tempFeed, si consiglia di rinominarlo,
+  visto che il feed potrà esser sostituito da un feed che ha lo stesso nome.
+* Il feed impostato come predefinito non può essere rimosso. Il file
+  addressFile  potrà esser usato come predefinito quando si ripristina alla
+  configurazione iniziale, in questo caso potrà esser rimosso.
+
+####Cartella Copia feed ####
+
+Apre una finestra dove è possibile scegliere il percorso per salvare la
+cartella dei vostri feed. Il percorso predefinito è la cartella di
+configurazione di NVDA,  dove verrà salvata una cartella nominata
+personalFeeds.
+
+#### Ripristina feed ####
+
+Apre una finestra che consente selezionare una cartella di feed
+precedentemente salvati e che sostituiranno i feed nella cartella
+personalFeeds. Assicurarsi di selezionare una cartella che contiene file con
+l'URL dei feed.
+
+### Comandi da tastiera:  ###
+
+* Ctrl+Shift+NVDA+Space: Legge il link dell'articolo selezionato. Premuto
+  due volte apre la pagina web dell'articolo.
+* Ctrl+Shift+NVDA+8: Aggiorna il feed selezionato e annuncia l'articolo più
+  recente.
+* Ctrl+Shift+NVDA+I: legge il titolo del feed e del link
+  selezionato. Premendo due volte verrà copiato il titolo e il relativo link
+  negli appunti. 
+* Ctrl+Shift+NVDA+U: legge il titolo del precedente feed.
+* Ctrl+Shift+NVDA+O: legge il titolo del feed successivo.
+
+## Avvisi vocali: ##
+
+* Quando si copia un titolo o un link.
+* Quando non è possibile connettersi o aggiornare un feed, o l'URL non
+  corrisponde ad un feed valido.
+* NVDA visualizza un avviso di errore segnalando che non è stato possibile
+  ripristinare o aggiornare la cartella personalFeeds.
+* Nel titolo della finestra elenco articoli viene indicato il feed
+  selezionato ed il numero di elementi disponibili.
+
+## Changes for 7.0 ##
+
+* Aggiunto un pulsante Nella finestra Feed che consente di aprire una
+  cartella di backup. 
+* Quando non si trova nessun risultato dal campo editazione, l'elenco Feed e
+  gli altri controlli vengono disattivati. In questo modo NVDA non
+  annuncierà più Sconosciuto in elenchi vuoti.
+* Se l'elenco degli articoli non può essere visualizzato, dovuto per esempio
+  ad un problema di feed, verrà rilasciato un errore. In questo modo non
+  sarà più necessario riavviare NVDA per usare la finestra Feed.
+
+## Changes for 6.0 ##
+
+* Quando il feed predefinito è stato aggiornato, ma per problemi del server
+  non si connette, gli articoli precedenti non vengono eliminati e possono
+  essere letti con i comandi assegnati.
+* Il feed predefinito può essere aggiornato nuovamente (Fix regression).
+
+## Changes for 5.0 ##
+
+* Migliorata la finestra per l'elenco articoli.
+* Compatibilità con NVDA 2018.3 o superiore(required).
+* Se è necessario, è possibile scaricare la versione [compatibile con NVDA
+  2017.3][3].
+
+## Changes for 4.0 ##
+
+* Aggiunto un pulsante per aprire il feed selezionato dalla finestra Feeds. 
+
+## Changes for 3.0 ##
+
+* La finestra per gestire i file dei feed è stata rimossa. Questa funzione
+  verrà eseguita dalla finestra Feeds.
+* The visual presentation of the dialogs has been enhanced, adhering to the
+  appearance of the dialogs shown in NVDA.
+* The default feed is saved on the NVDA's configuration. Therefore, it's
+  possible to set different default feeds in configuration profiles.
+* Requires NVDA 2016.4.
+
+
+## Changes for 2.0 ##
+
+* Add-on help is available from the Add-ons Manager.
+
+## Changes for 1.0 ##
+
+* Initial version.
+
+[[!tag dev stable]]
+
+[1]: https://addons.nvda-project.org/files/get.php?file=rf
+
+[2]: https://addons.nvda-project.org/files/get.php?file=rf-dev
+
+[3]: https://addons.nvda-project.org/files/get.php?file=rf-o

diff --git a/addon/doc/pl/readme.md b/addon/doc/pl/readme.md
index edd724c..c1a86b8 100644
--- a/addon/doc/pl/readme.md
+++ b/addon/doc/pl/readme.md
@@ -1,6 +1,7 @@
 # Read Feeds #
 
 * Autorzy: Noelia Ruiz Martínez, Mesar Hameed
+* NVDA compatibility: 2018.3 to 2019.1
 * Pobierz [Wersja stabilna][1]
 * Pobierz [Wersja rozwojowa][2]
 
@@ -48,6 +49,9 @@ Otwiera dialog z następującymi kontrolkami:
   osobistego po potwierdzeniu.
 * Ustaw jako domyślny: Ustawia kanał osobisty jako domyślny, aby można było
   się dostać do artykułów za pomocą gestów NVDA.
+* Open folder containing a backup of feeds: Opens a folder which may contain
+  a backup of feeds. This can be useful to explore and delete feeds which
+  shouldn't be imported when the add-on is updated.
 * Zamknij: Zamyka dialog kanały osobiste.
 
 ##### Uwagi #####
@@ -94,6 +98,24 @@ katalog zawierający kanały osobiste.
 * Dialog Spisu nagłówków artykułów Wyświetla nazwę oznaczonego kanału
   osobistego i ilość dostępnych artykułów.
 
+## Changes for 7.0 ##
+
+* The Feeds dialog includes a button to open a folder which may contain a
+  backup of feeds.
+* When using the edit box to filter feeds, if no results are found, the list
+  of feeds and other controls are disabled, so that NVDA doesn't report
+  "unknown" in the empty list.
+* If the list of articles dialog can't be shown, for example due to errors
+  in the feed, NVDA will raise an error, so that the feeds dialog can be
+  used without restarting NVDA.
+
+## Changes for 6.0 ##
+
+* When the default feed has been updated and it stops working due to server
+  issues, the previous articles aren't deleted and can be read with the
+  corresponding keystrokes.
+* Fix regression: The default feed can be updated twice again.
+
 ## Changes for 5.0 ##
 
 * The articles list dialog has been enhanced.

diff --git a/addon/doc/pt_BR/readme.md b/addon/doc/pt_BR/readme.md
index e279483..0eacbb4 100644
--- a/addon/doc/pt_BR/readme.md
+++ b/addon/doc/pt_BR/readme.md
@@ -1,6 +1,7 @@
 # Leitor de feeds #
 
 * Autores: Noelia Ruiz Martínez, Mesar Hameed
+* NVDA compatibility: 2018.3 to 2019.1
 * Baixe a [versão estável][1]
 * Baixe a [versão em desenvolvimento][2]
 
@@ -46,6 +47,9 @@ Abre um diálogo com os seguintes controles:
 * Excluir: Abre um diálogo para excluir o feed selecionado após confirmação.
 * Definir padrão: define o feed selecionado como padrão, para que seus
   artigos possam ser acessados com os gestos — comandos — do NVDA.
+* Open folder containing a backup of feeds: Opens a folder which may contain
+  a backup of feeds. This can be useful to explore and delete feeds which
+  shouldn't be imported when the add-on is updated.
 * Fechar: Fecha o diálogo feeds.
 
 ##### Notas #####
@@ -90,6 +94,25 @@ URLs de feeds.
 * O título do diálogo Lista de artigos mostra o nome do feed selecionado e o
   número de itens disponíveis.
 
+## Changes for 7.0 ##
+
+* The Feeds dialog includes a button to open a folder which may contain a
+  backup of feeds.
+* When using the edit box to filter feeds, if no results are found, the list
+  of feeds and other controls are disabled, so that NVDA doesn't report
+  "unknown" in the empty list.
+* If the list of articles dialog can't be shown, for example due to errors
+  in the feed, NVDA will raise an error, so that the feeds dialog can be
+  used without restarting NVDA.
+
+## Mudanças na 6.0 ##
+
+* Quando o feed padrão é atualizado e ele para de funcionar devido a
+  problemas do servidor, os artigos anteriores não são excluídos e podem ser
+  lidos com os pressionamentos de teclas correspondentes.
+* Correção de regressão: o feed padrão pode ser atualizado duas vezes
+  novamente.
+
 ## Mudanças na 5.0 ##
 
 * A caixa de diálogo da lista de artigos foi aprimorada.

diff --git a/addon/doc/pt_PT/readme.md b/addon/doc/pt_PT/readme.md
index d866089..02df0b3 100644
--- a/addon/doc/pt_PT/readme.md
+++ b/addon/doc/pt_PT/readme.md
@@ -1,6 +1,7 @@
 # Leitor de RSS #
 
 * Autores: Noelia Ruiz Martínez, Mesar Hameed
+* Compatibilidade com o NVDA: 2018.3 até 2019.1
 * Baixar [versão estável][1]
 * Baixar [versão de desenvolvimento][2]
 
@@ -48,6 +49,9 @@ Abre um diálogo com os seguintes controlos:
   confirmação.
 * Definir por defeito: define o feed seleccionado como padrão, para que os
   seus artigos possam ser acedidos ​​com os comandos do NVDA.
+* Abrir pasta que contenha um backup de feeds: Abre uma pasta que pode
+  conter um backup de feeds. Isto pode ser útil para explorar e excluir
+  feeds que não devam ser importados quando o extra é actualizado.
 * Fechar: fecha o diálogo de RSS;
 
 ##### Notas: #####
@@ -93,6 +97,25 @@ URLs de feeds.
 * O título da caixa de diálogo da lista de artigos mostra o nome do feed
   selecionado e o número de itens disponíveis.
 
+## Alterações para 7.0: ##
+
+* A caixa de diálogo Feeds inclui um botão para abrir uma pasta que pode
+  conter um backup de feeds.
+* Ao usar a caixa de edição para filtrar os feeds, se não for encontrado
+  qualquer resultado, a lista de feeds e outros controlos será desactivada,
+  para que o NVDA não diga "desconhecido", na lista vazia.
+* Se o diálogo de lista de artigos não puder ser mostrado, por exemplo,
+  devido a erros no feed, o NVDA irá gerar um erro, para que o diálogo de
+  feeds possa ser usado sem reiniciar o NVDA.
+
+## Alterações para 6.0: ##
+
+* Quando o feed padrão é actualizado e para de funcionar devido a problemas
+  do servidor, os artigos anteriores não são excluídos e podem ser lidos,
+  pelo uso das teclas correspondentes.
+* Corrigida regressão: o feed padrão pode ser atualizado duas vezes,
+  novamente.
+
 ## Alterações para 5.0: ##
 
 * A caixa de diálogo da lista de artigos foi melhorada.

diff --git a/addon/doc/ro/readme.md b/addon/doc/ro/readme.md
index 3bcb454..0bf4a41 100644
--- a/addon/doc/ro/readme.md
+++ b/addon/doc/ro/readme.md
@@ -1,6 +1,7 @@
 # Read Feeds #
 
 * Autori: Noelia Ruiz Martínez, Mesar Hameed
+* Compatibilitate NVDA: 2018.3 - 2019.1
 * Descărcați [versiunea stabilă][1]
 * Descărcați [versiunea în dezvoltare][2]
 
@@ -50,6 +51,9 @@ Deschide un dialog cu următoarele controale:
   confirmare.
 * Setare ca implicit: Setează fluxul selectat ca implicit, așa că articolele
   sale pot fi accesate cu gesturile NVDA-ului.
+* Open folder containing a backup of feeds: Opens a folder which may contain
+  a backup of feeds. This can be useful to explore and delete feeds which
+  shouldn't be imported when the add-on is updated.
 * Închidere: Închide dialogul fluxurilor.
 
 ##### Note #####
@@ -95,6 +99,24 @@ ce conține URL-urile fluxurilor.
 * Dialogul titlului listei articolelor afișează numele fluxului selectat și
   numărul elementelor disponibile.
 
+## Changes for 7.0 ##
+
+* The Feeds dialog includes a button to open a folder which may contain a
+  backup of feeds.
+* When using the edit box to filter feeds, if no results are found, the list
+  of feeds and other controls are disabled, so that NVDA doesn't report
+  "unknown" in the empty list.
+* If the list of articles dialog can't be shown, for example due to errors
+  in the feed, NVDA will raise an error, so that the feeds dialog can be
+  used without restarting NVDA.
+
+## Modificări în 6.0 ##
+
+* Când fluxul implicit a fost actualizat și nu se nu mai funcționează
+  datorită problemelor de server, articolele precedente nu sunt șterse și
+  pot fi citite cu combinații de taste corespondente.
+* rezolvare: fluxul implicit poate fi actualizat de două ori.
+
 ## Modificări în 5.0 ##
 
 * A fost îmbunătățit dialogul listei articolelor.

diff --git a/addon/doc/ru/readme.md b/addon/doc/ru/readme.md
index 18a803f..0294872 100644
--- a/addon/doc/ru/readme.md
+++ b/addon/doc/ru/readme.md
@@ -1,6 +1,7 @@
 # Read Feeds #
 
 * Авторы: Noelia Ruiz Martínez, Mesar Hameed
+* NVDA compatibility: 2018.3 to 2019.1
 * Загрузить [стабильную версию][1]
 * Загрузить [разрабатываемую версию][2]
 
@@ -50,6 +51,9 @@ readFeeds.
   подтверждения.
 * Установить по умолчанию: устанавливает выбранную новостную ленту по
   умолчанию, и её статьи могут быть доступны с помощью жестов NVDA.
+* Open folder containing a backup of feeds: Opens a folder which may contain
+  a backup of feeds. This can be useful to explore and delete feeds which
+  shouldn't be imported when the add-on is updated.
 * Закрыть: закрывает диалог новостных лент.
 
 ##### Примечания #####
@@ -94,6 +98,24 @@ URL-адреса новостных лент.
 * Диалог с названием списка статей отображает имя выбранной новостной ленты
   с количеством доступных элементов.
 
+## Changes for 7.0 ##
+
+* The Feeds dialog includes a button to open a folder which may contain a
+  backup of feeds.
+* When using the edit box to filter feeds, if no results are found, the list
+  of feeds and other controls are disabled, so that NVDA doesn't report
+  "unknown" in the empty list.
+* If the list of articles dialog can't be shown, for example due to errors
+  in the feed, NVDA will raise an error, so that the feeds dialog can be
+  used without restarting NVDA.
+
+## Changes for 6.0 ##
+
+* When the default feed has been updated and it stops working due to server
+  issues, the previous articles aren't deleted and can be read with the
+  corresponding keystrokes.
+* Fix regression: The default feed can be updated twice again.
+
 ## Changes for 5.0 ##
 
 * The articles list dialog has been enhanced.

diff --git a/addon/doc/zh_CN/readme.md b/addon/doc/zh_CN/readme.md
index 7254e48..31f52de 100644
--- a/addon/doc/zh_CN/readme.md
+++ b/addon/doc/zh_CN/readme.md
@@ -1,6 +1,7 @@
 # Read Feeds-NVDA-RSS阅读插件 #
 
 * 作者: Noelia Ruiz Martínez, Mesar Hameed
+* NVDA兼容版本: 2018.3至2019.1
 * 下载 [稳定版][1]
 * 下载 [开发板][2]
 
@@ -10,7 +11,7 @@
 
 
如果您使用此插件的先前版本,并且个人NVDA配置文件夹中有RSS或personalFeeds文件夹,则在安装当前版本时,会出现一个对话框,询问您是要升级还是安装。选择更新以保留已保存的源,并在新安装的readFeeds版本中继续使用它们。
 
-## 快捷键 ##
+## 快捷键: ##
 
 ### 阅读Feed菜单 ###
 
@@ -28,6 +29,7 @@
 * 重命名:打开一个带有编辑框的对话框,以重命名所选的源。
 * 删除:打开确认后删除所选feed的对话框。
 * 设置默认值:将选定的Feed设置为默认值,以便可以使用NVDA的快捷键访问其文章。
+* 打开包含RSS源备份的文件夹: 打开一个可能包含RSS源备份的文件夹。可以用于在更新插件后浏览和删除不应导入的源。
 * 关闭:关闭“源”对话框。
 
 ##### 注意 #####
@@ -43,21 +45,32 @@
 
 打开一个对话框,选择一个替换personalFeeds文件夹中的Feed的文件夹。确保加载包含feed网址的文件夹。
 
-### 快捷键 ###
+### 键盘快捷键: ###
 
-* Ctrl + Shift + NVDA + Space:宣布当前文章的URL。按两次将打开网页。
-* Ctrl + Shift + NVDA + 8:刷新选定的Feed并宣布其最新的标题。
-* Ctrl + Shift + NVDA + I:宣布当前的Feed标题和链接。按两次将标题和相关链接复制到剪贴板。
-* Ctrl + Shift + NVDA + U:宣布以前的Feed标题。
-* Ctrl + Shift + NVDA + O:宣布下一个Feed标题。
+* Ctrl + Shift + NVDA + Space:朗读当前文章的URL。按两次将打开网页。
+* Ctrl + Shift + NVDA + 8:刷新选定的Feed并朗读其最新的标题。
+* Ctrl + Shift + NVDA + I:朗读当前RSS源的标题和链接。按两次将标题和相关链接复制到剪贴板。
+* Ctrl + Shift + NVDA + U:朗读当前源的上一个的标题。
+* Ctrl + Shift + NVDA + O:朗读当前源的下一个标题。
 
-## 通知 ##
+## 通知: ##
 
 * 复制标题或URL时。
 * 无法连接/刷新Feed时,或者URL与有效Feed不对应。
 * 如果无法备份或还原personalFeeds文件夹,NVDA将显示错误消息。
 * “文章列表”对话框的标题显示所选的源名称和可用项目数。
 
+## 版本7.0 ##
+
+* "源" 对话框中包含一个按钮, 用于打开可能包含源备份的文件夹。
+* 使用编辑框筛选源时, 如果未找到任何结果, 则会禁用源和其他控件的列表, 以便 NVDA 不会在空列表中朗读 "未知"。
+* 如果无法显示文章对话框列表 (例如, RSS的摘要有错误), 直接报错, 这样可以在不重新启动 NVDA 的情况下继续使用RSS源对话框。
+
+## 版本6.0 ##
+
+* 当默认RSS源已更新并且由于服务器问题而停止工作时,之前的文章不会被删除,并且可以使用相应的按键进行读取。
+* 修复错误:默认RSS源可以更新两次了。
+
 ## 版本5.0 ##
 
 * 文章列表对话框已得到增强。
@@ -82,7 +95,7 @@
 
 ## 版本1.0 ##
 
-* 发布初始版本
+* 发布初始版本。
 
 [[!tag dev stable]]
 

diff --git a/addon/globalPlugins/readFeeds/__init__.py 
b/addon/globalPlugins/readFeeds/__init__.py
index 7c5b395..4664e38 100644
--- a/addon/globalPlugins/readFeeds/__init__.py
+++ b/addon/globalPlugins/readFeeds/__init__.py
@@ -1,7 +1,7 @@
 # -*- coding: UTF-8 -*-
 
 # Read feeds: A simple plugin for reading feeds with NVDA
-#Copyright (C) 2012-2018 Noelia Ruiz Martínez, Mesar Hameed
+#Copyright (C) 2012-2019 Noelia Ruiz Martínez, Mesar Hameed
 # Released under GPL 2
 
 import os
@@ -17,6 +17,7 @@ from scriptHandler import script
 import api
 import gui
 from gui import guiHelper
+import core
 import wx
 import ui
 from logHandler import log
@@ -56,10 +57,15 @@ def getActiveProfile():
        return activeProfile
 
 def doCopy(copyDirectory):
+       # to ensure that the removed directory will not be one of the main 
directories such as documents or music or other important ones
+       if not os.path.basename(copyDirectory)== "personalFeeds":
+               copyDirectory=os.path.join(copyDirectory, "personalFeeds")
        try:
-               shutil.rmtree(copyDirectory, ignore_errors=True)
+               if os.path.exists(copyDirectory):
+                       #if it exists, only personalFeeds folder will be 
removed, which is the base name of copyDirectory path
+                       shutil.rmtree(copyDirectory, ignore_errors=True)
                shutil.copytree(FEEDS_PATH, copyDirectory)
-               wx.CallLater(100, ui.message,
+               core.callLater(100, ui.message,
                        # Translators: Message presented when feeds have been 
copied.
                        _("Feeds copied"))
        except Exception as e:
@@ -75,7 +81,7 @@ def doRestore(restoreDirectory):
        try:
                shutil.rmtree(FEEDS_PATH, ignore_errors=True)
                shutil.copytree(restoreDirectory, FEEDS_PATH)
-               wx.CallLater(100, ui.message,
+               core.callLater(100, ui.message,
                        # Translators: Message presented when feeds have been 
restored.
                        _("Feeds restored"))
        except Exception as e:
@@ -154,6 +160,10 @@ class FeedsDialog(wx.Dialog):
                self.defaultButton = buttonHelper.addButton(self, label=_("S&et 
default"))
                self.defaultButton.Bind(wx.EVT_BUTTON, self.onDefault)
 
+               # Translators: The label of a button to open a folder 
containing a backup of feeds.
+               self.openFolderButton = buttonHelper.addButton(self, 
label=_("Open &folder containing a backup of feeds"))
+               self.openFolderButton.Bind(wx.EVT_BUTTON, self.onOpenFolder)
+               
                feedsListGroupContents.Add(buttonHelper.sizer)
                feedsListGroupSizer.Add(feedsListGroupContents, 
border=guiHelper.BORDER_FOR_DIALOGS, flag=wx.ALL)
                sHelper.addItem(feedsListGroupSizer)
@@ -195,10 +205,14 @@ class FeedsDialog(wx.Dialog):
                        if filter and not filterReg.match(choice):
                                continue
                        self.feedsList.Append(choice)
-               self.feedsList.Selection = 0
-               self.onFeedsListChoice(None)
+               try:
+                       self.feedsList.Selection = 0
+                       self.onFeedsListChoice(None)
+               except:
+                       [control.Disable() for control in self.feedsList, 
self.articlesButton, self.openButton, self.renameButton, self.deleteButton, 
self.defaultButton]
 
        def onFeedsListChoice(self, evt):
+               self.feedsList.Enable()
                self.sel = self.feedsList.Selection
                self.stringSel = self.feedsList.StringSelection
                self.articlesButton.Enabled = self.sel>= 0
@@ -218,7 +232,11 @@ class FeedsDialog(wx.Dialog):
                        f.close()
                self.feed = Feed(address)
                self.Disable()
-               ArticlesDialog(self).Show()
+               try:
+                       ArticlesDialog(self).Show()
+               except Exception as e:
+                       self.Enable()
+                       raise e
 
        def onOpen(self, evt):
                with open(os.path.join(FEEDS_PATH, "%s.txt" % self.stringSel), 
"r") as f:
@@ -272,6 +290,12 @@ class FeedsDialog(wx.Dialog):
                self.Destroy()
                FeedsDialog._instance = None
 
+       def onOpenFolder(self, evt):
+               path = os.path.join(CONFIG_PATH, "personalFeeds")
+               if not os.path.isdir(path):
+                       os.makedirs(path)
+               os.startfile(path)
+
 class ArticlesDialog(wx.Dialog):
 
        def __init__(self, parent):

diff --git a/addon/installTasks.py b/addon/installTasks.py
index 4a4729e..5488cda 100644
--- a/addon/installTasks.py
+++ b/addon/installTasks.py
@@ -1,7 +1,7 @@
 # -*- coding: UTF-8 -*-
 
 # installTasks for the readFeeds add-on
-#Copyright (C) 2013-2016 Noelia Ruiz Martínez, other contributors
+#Copyright (C) 2013-2019 Noelia Ruiz Martínez, other contributors
 # Released under GPL2
 
 import addonHandler
@@ -48,3 +48,12 @@ def onInstall():
                                                shutil.copy(file, FEEDS_PATH)
                                        except IOError:
                                                pass
+                               return
+       previousFeedsPath = os.path.join(CONFIG_PATH, "addons", "readFeeds", 
"globalPlugins", "readFeeds", "personalFeeds")
+       if os.path.isdir(previousFeedsPath):
+               validFiles = glob.glob(previousFeedsPath+"\\*.txt")
+               for file in validFiles:
+                       try:
+                               shutil.copy(file, FEEDS_PATH)
+                       except IOError:
+                               pass

diff --git a/addon/locale/ar/LC_MESSAGES/nvda.po 
b/addon/locale/ar/LC_MESSAGES/nvda.po
index a007734..484585d 100644
--- a/addon/locale/ar/LC_MESSAGES/nvda.po
+++ b/addon/locale/ar/LC_MESSAGES/nvda.po
@@ -8,14 +8,17 @@ msgstr ""
 "Project-Id-Version: readFeeds 1.0-dev\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2013-11-16 13:26+0100\n"
-"PO-Revision-Date: 2017-04-20 13:53+0200\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@xxxxxx>\n"
+"PO-Revision-Date: 2018-12-22 16:46+0200\n"
+"Last-Translator: wafiqtaher <wafiqtaher@xxxxxxxxx>\n"
+"Language-Team: arabic <wafiqtaher@xxxxxxxxx fatmamehanna@xxxxxxxxx>\n"
 "Language: ar\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.5.7\n"
+"X-Generator: Poedit 1.6.11\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
+"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
 
 #. Translators: the label of a message box dialog.
 msgid ""
@@ -66,20 +69,19 @@ msgstr "تم استرجاع التلقيمات"
 #. Translators: The title of a dialog.
 #, python-brace-format
 msgid "Feeds: {defaultFeed} ({configProfile})"
-msgstr ""
+msgstr "الخلاصات: {defaultFeed} ({configProfile})"
 
 #. Label of a dialog (message translated in NVDA core in different contexts).
 msgid "&Filter by:"
-msgstr ""
+msgstr "ت&صفية حسب:"
 
 #. Translators: The label of a button to open the list of articles of a feed.
 msgid "List of &articles..."
 msgstr "قائمة ال&مقالات..."
 
 #. Translators: The label of a button to open a feed.
-#, fuzzy
 msgid "&Open feed"
-msgstr "تلقيم جديد"
+msgstr "&فتح المقال"
 
 #. Translators: The label of a button to add a new feed.
 msgid "&New..."
@@ -95,7 +97,12 @@ msgstr "&حذف..."
 
 #. Translators: The label of a button to set a feed as default.
 msgid "S&et default"
-msgstr "إ&عداد الافتراضي"
+msgstr "إست&عادة الافتراضي"
+
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+#, fuzzy
+msgid "Open &folder containing a backup of feeds"
+msgstr "حدد مجلد لحفظ نسخة احطياطية من تلقيماتك الحالية"
 
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
@@ -118,19 +125,16 @@ msgid "Rename feed"
 msgstr "إعادة تسمية التلقيم"
 
 #. Translators: The label of the articles list in the articles dialog.
-#, fuzzy
 msgid "List of articles"
-msgstr "قائمة ال&مقالات..."
+msgstr "قائمة من المقالات"
 
 #. Translators: The label of a button to open the selected article of a feed.
-#, fuzzy
 msgid "Open &web page of selected article."
-msgstr "افتح صفحة المقال المحدد"
+msgstr "ا&فتح صفحة المقال المحدد"
 
 #. Translators: The label of a button to show information of a feed article.
-#, fuzzy
 msgid "&About article..."
-msgstr "قائمة ال&مقالات..."
+msgstr "&حول..."
 
 #. Translators: the label of a message box dialog.
 #, python-format
@@ -139,22 +143,21 @@ msgid ""
 "\r\n"
 "Do you want to copy article title and link to the clipboard?"
 msgstr ""
+"%s\r\n"
+" \r\n"
+" هل تريد نسخ عنوان المقال و الرابط إلى الحافظة?"
 
 #. Translators: the title of a message box dialog.
 msgid "Article information"
-msgstr ""
+msgstr "معلومات المادة"
 
 #. Translators: The title of the Copy dialog.
 msgid "Copy feeds"
 msgstr "نسخ التلقيمات"
 
 #. Translators: An informational message displayed in the Copy dialog.
-#, fuzzy
 msgid "Select a folder to save a backup of your current feeds"
-msgstr ""
-"حدد مجلد لحفظ نسخة احطياطية من تلقيماتك الحالية.\n"
-"\n"
-"\t\tسيتم نسخهم من %s."
+msgstr "حدد مجلد لحفظ نسخة احطياطية من تلقيماتك الحالية"
 
 #. Translators: The label of a grouping containing controls to select the 
destination directory in the Copy dialog.
 msgid "directory for backup:"
@@ -169,12 +172,8 @@ msgid "Restore feeds"
 msgstr "استرجاع التلقيمات"
 
 #. Translators: An informational message displayed in the Restore dialog.
-#, fuzzy
 msgid "Select a folder to restore a backup of your previous copied feeds"
-msgstr ""
-"اختر مجلد لاسترجاع تلقيماتك الشخصية به.\n"
-"\n"
-"\t\tسيتم النسخ إلى %s."
+msgstr "اختر مجلد لاسترجاع تلقيماتك الشخصية"
 
 #. Translators: The label of a grouping containing controls to select the 
destination directory in the Restore dialog.
 msgid "directory containing backup:"
@@ -194,7 +193,7 @@ msgstr "تعذر تحديد رابط المقال"
 
 #. Translators: the name of a submenu.
 msgid "&Read Feeds"
-msgstr "&قراءة التلقيمات"
+msgstr "&قراءة الخلاصات"
 
 #. Translators: the name of a menu item.
 msgid "&Feeds..."
@@ -261,24 +260,9 @@ msgstr "نسخ عنوان ورابط المقال الحالي للحافظة."
 #. Add-on summary, usually the user visible name of the addon.
 #. Translators: Summary for this add-on to be shown on installation and add-on 
information.
 msgid "Read Feeds"
-msgstr "Read Feeds"
+msgstr "قراءة الخلاصات"
 
 #. Add-on description
 #. Translators: Long description to be shown for this add-on on add-on 
information from add-ons manager
 msgid "Add-on for using NVDA as a feed reader."
 msgstr "إضافة برمجية تمكن من استخدام NVDA كقارئ للتلقيمات"
-
-#~ msgid "Feeds"
-#~ msgstr "تلقيمات"
-
-#~ msgid "Manage feeds."
-#~ msgstr "إدارة التلقيمات"
-
-#~ msgid "View and manage feeds"
-#~ msgstr "عرض وإدارة التلقيمات"
-
-#~ msgid "Backup of feeds"
-#~ msgstr "نسخة احطياطية من التلقيمات"
-
-#~ msgid "Restore previously saved feeds"
-#~ msgstr "استرجاع التلقيمات المحفوظة من قبل"

diff --git a/addon/locale/bg/LC_MESSAGES/nvda.po 
b/addon/locale/bg/LC_MESSAGES/nvda.po
index 269eedf..967d8df 100644
--- a/addon/locale/bg/LC_MESSAGES/nvda.po
+++ b/addon/locale/bg/LC_MESSAGES/nvda.po
@@ -9,7 +9,7 @@ msgstr ""
 "Project-Id-Version: readFeeds 1.0-dev\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2013-11-16 13:26+0100\n"
-"PO-Revision-Date: 2018-09-24 22:16+0300\n"
+"PO-Revision-Date: 2019-03-29 14:40+0200\n"
 "Last-Translator: Kostadin Kolev <k_kolev1985@xxxxxxx>\n"
 "Language-Team: Български <>\n"
 "Language: bg\n"
@@ -17,7 +17,7 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n!=1);\n"
-"X-Generator: Poedit 2.1.1\n"
+"X-Generator: Poedit 2.2.1\n"
 
 #. Translators: the label of a message box dialog.
 msgid ""
@@ -101,6 +101,10 @@ msgstr "&Изтрий..."
 msgid "S&et default"
 msgstr "&Задай по подразбиране"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+msgid "Open &folder containing a backup of feeds"
+msgstr "Отвори &папката с резервното копие на емисиите"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Адрес на нов източник:"
@@ -112,7 +116,7 @@ msgstr "Нов източник"
 #. Translators: The confirmation prompt displayed when the user requests to 
delete a feed.
 msgid "Are you sure you want to delete this feed? This cannot be undone."
 msgstr ""
-"Сигурен ли сте, че искате да изтриете този източник? Това действие не може "
+"Сигурни ли сте, че искате да изтриете този източник? Това действие не може "
 "да бъде отменено."
 
 #. Translators: The label of a field to enter a new name for a feed.

diff --git a/addon/locale/da/LC_MESSAGES/nvda.po 
b/addon/locale/da/LC_MESSAGES/nvda.po
index e3c95aa..1f0ac5d 100644
--- a/addon/locale/da/LC_MESSAGES/nvda.po
+++ b/addon/locale/da/LC_MESSAGES/nvda.po
@@ -8,14 +8,14 @@ msgstr ""
 "Project-Id-Version: readFeeds 1.0-dev\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2013-11-23 12:28+0100\n"
-"PO-Revision-Date: 2018-10-30 20:13+0100\n"
+"PO-Revision-Date: 2019-04-04 21:13+0200\n"
 "Last-Translator: Nicolai Svendsen <chojiro1990@xxxxxxxxx>\n"
-"Language-Team: Danish <dansk@xxxxxxx>\n"
+"Language-Team: Dansk NVDA <dansk@xxxxxxx>\n"
 "Language: da\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.2\n"
+"X-Generator: Poedit 2.2.1\n"
 
 #. Translators: the label of a message box dialog.
 msgid ""
@@ -99,6 +99,10 @@ msgstr "&Slet..."
 msgid "S&et default"
 msgstr "Sæt som st&andard"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+msgid "Open &folder containing a backup of feeds"
+msgstr "Åbn &mappen med sikkerhedskopierne for dine nyhedskanaler"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Adresse på ny nyhedskanal:"

diff --git a/addon/locale/de/LC_MESSAGES/nvda.po 
b/addon/locale/de/LC_MESSAGES/nvda.po
index 9737188..6383d7c 100644
--- a/addon/locale/de/LC_MESSAGES/nvda.po
+++ b/addon/locale/de/LC_MESSAGES/nvda.po
@@ -8,14 +8,14 @@ msgstr ""
 "Project-Id-Version: readFeeds 1.0-dev\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2013-11-16 13:26+0100\n"
-"PO-Revision-Date: 2018-09-24 11:33+0200\n"
-"Last-Translator: René Linke <rene.linke@xxxxxxxxxx>\n"
+"PO-Revision-Date: 2019-06-02 20:12+0100\n"
+"Last-Translator: Waldschmetterling <a.r.waldschmetterling@xxxxxx>\n"
 "Language-Team: \n"
 "Language: de\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.1.1\n"
+"X-Generator: Poedit 1.5.7\n"
 
 #. Translators: the label of a message box dialog.
 msgid ""
@@ -66,7 +66,6 @@ msgid "Feeds restored"
 msgstr "RSS-Feeds wiederhergestellt"
 
 #. Translators: The title of a dialog.
-#, python-brace-format
 msgid "Feeds: {defaultFeed} ({configProfile})"
 msgstr "Feeds: {defaultFeed} ({configProfile})"
 
@@ -98,6 +97,10 @@ msgstr "&Löschen..."
 msgid "S&et default"
 msgstr "Als Standard &festlegen"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+msgid "Open &folder containing a backup of feeds"
+msgstr "ö&ffnen Sie einen Ordner der gesicherte Feeds enthält"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Neue Adresse des RSS-Feeds:"
@@ -173,8 +176,8 @@ msgstr "RSS-Feeds wiederherstellen"
 #. Translators: An informational message displayed in the Restore dialog.
 msgid "Select a folder to restore a backup of your previous copied feeds"
 msgstr ""
-"Bitte wählen Sie einen Ordner zum wiederherstellen des Backups Ihrer vorig "
-"kopierten RSS-Feeds aus"
+"Bitte wählen Sie einen Ordner zum wiederherstellen des Backups Ihrer "
+"vorherigen kopierten RSS-Feeds aus"
 
 #. Translators: The label of a grouping containing controls to select the 
destination directory in the Restore dialog.
 msgid "directory containing backup:"

diff --git a/addon/locale/de_CH/LC_MESSAGES/nvda.po 
b/addon/locale/de_CH/LC_MESSAGES/nvda.po
index 8a2ad34..9cf6ba7 100644
--- a/addon/locale/de_CH/LC_MESSAGES/nvda.po
+++ b/addon/locale/de_CH/LC_MESSAGES/nvda.po
@@ -98,6 +98,15 @@ msgstr "&Löschen..."
 msgid "S&et default"
 msgstr "Als Standard &festlegen"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+#, fuzzy
+msgid "Open &folder containing a backup of feeds"
+msgstr ""
+"Bitte wählen Sie einen Ordner zum Speichern des Backups Ihrer aktuellen Rss-"
+"Feeds aus:\n"
+"\n"
+"\t\tSie werden aus %s gesichert."
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Neue Adresse des Rss-Feeds:"

diff --git a/addon/locale/es/LC_MESSAGES/nvda.po 
b/addon/locale/es/LC_MESSAGES/nvda.po
index f90d854..4a1f9a8 100644
--- a/addon/locale/es/LC_MESSAGES/nvda.po
+++ b/addon/locale/es/LC_MESSAGES/nvda.po
@@ -8,14 +8,14 @@ msgstr ""
 "Project-Id-Version: readFeeds 1.0-dev\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2013-11-16 13:26+0100\n"
-"PO-Revision-Date: 2018-09-22 11:28+0100\n"
+"PO-Revision-Date: 2019-03-29 09:24+0100\n"
 "Last-Translator: Iván Novegil <ivan.novegil.cancelas@xxxxxxxxx>\n"
 "Language-Team: spanish NVDA add-ons translation team <oprisniki@xxxxxxxxx>\n"
 "Language: es\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.6.11\n"
+"X-Generator: Poedit 2.2.1\n"
 
 #. Translators: the label of a message box dialog.
 msgid ""
@@ -98,6 +98,10 @@ msgstr "&Eliminar..."
 msgid "S&et default"
 msgstr "&Configurar como predeterminado"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+msgid "Open &folder containing a backup of feeds"
+msgstr "Abrir &carpeta que contiene una copia de seguridad de las fuentes"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Dirección de un feed nuevo:"

diff --git a/addon/locale/fi/LC_MESSAGES/nvda.po 
b/addon/locale/fi/LC_MESSAGES/nvda.po
index 84289c3..77e90ff 100644
--- a/addon/locale/fi/LC_MESSAGES/nvda.po
+++ b/addon/locale/fi/LC_MESSAGES/nvda.po
@@ -8,8 +8,8 @@ msgstr ""
 "Project-Id-Version: readFeeds\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2013-11-16 13:26+0100\n"
-"PO-Revision-Date: 2018-09-21 11:18+0200\n"
-"Last-Translator: Jani Kinnunen <jani.kinnunen@xxxxxxxxxx>\n"
+"PO-Revision-Date: 2019-03-29 13:49+0200\n"
+"Last-Translator: Jani Kinnunen <janikinnunen340@xxxxxxxxx>\n"
 "Language-Team: Finnish <jani.kinnunen@xxxxxxxxxx>\n"
 "Language: fi\n"
 "MIME-Version: 1.0\n"
@@ -99,6 +99,10 @@ msgstr "&Poista..."
 msgid "S&et default"
 msgstr "A&seta oletukseksi"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+msgid "Open &folder containing a backup of feeds"
+msgstr "Avaa s&yötteiden varmuuskopiokansio"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Uuden syötteen osoite:"

diff --git a/addon/locale/fr/LC_MESSAGES/nvda.po 
b/addon/locale/fr/LC_MESSAGES/nvda.po
index 92c6021..58829a9 100644
--- a/addon/locale/fr/LC_MESSAGES/nvda.po
+++ b/addon/locale/fr/LC_MESSAGES/nvda.po
@@ -101,6 +101,12 @@ msgstr "&Supprimer..."
 msgid "S&et default"
 msgstr "Définir par d&éfaut"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+#, fuzzy
+msgid "Open &folder containing a backup of feeds"
+msgstr ""
+"Sélectionnez le dossier afin d'enregistrer une sauvegarde de vos flux actuels"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Adresse d'un nouveau flux:"

diff --git a/addon/locale/gl/LC_MESSAGES/nvda.po 
b/addon/locale/gl/LC_MESSAGES/nvda.po
index 0d91684..323ccdd 100644
--- a/addon/locale/gl/LC_MESSAGES/nvda.po
+++ b/addon/locale/gl/LC_MESSAGES/nvda.po
@@ -8,14 +8,14 @@ msgstr ""
 "Project-Id-Version: readFeeds 1.0-dev\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2013-11-16 13:26+0100\n"
-"PO-Revision-Date: 2018-09-22 11:29+0100\n"
+"PO-Revision-Date: 2019-03-29 09:25+0100\n"
 "Last-Translator: Iván Novegil <ivan.novegil.cancelas@xxxxxxxxx>\n"
 "Language-Team: galician NVDA add-ons translation team <oprisniki@xxxxxxxxx>\n"
 "Language: gl\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.6.11\n"
+"X-Generator: Poedit 2.2.1\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
 #. Translators: the label of a message box dialog.
@@ -99,6 +99,10 @@ msgstr "&Borrar..."
 msgid "S&et default"
 msgstr "&Configurar predeterminado"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+msgid "Open &folder containing a backup of feeds"
+msgstr "Abrir &cartafol que contén unha copia de seguridade das fontes"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Enderezo dun feed novo:"

diff --git a/addon/locale/he/LC_MESSAGES/nvda.po 
b/addon/locale/he/LC_MESSAGES/nvda.po
index ac3c4d9..57ea596 100644
--- a/addon/locale/he/LC_MESSAGES/nvda.po
+++ b/addon/locale/he/LC_MESSAGES/nvda.po
@@ -8,14 +8,14 @@ msgstr ""
 "Project-Id-Version: readFeeds 2.5\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2015-09-12 04:00+1000\n"
-"PO-Revision-Date: 2018-02-13 02:39+0100\n"
-"Last-Translator: shmuel_naaman@xxxxxxxxx\n"
+"PO-Revision-Date: 2018-12-06 16:58+0200\n"
+"Last-Translator: shmuel naaman <shmuel_naaman@xxxxxxxxx>\n"
 "Language-Team: \n"
 "Language: he\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.0.6\n"
+"X-Generator: Poedit 1.6.10\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
 #. Translators: the label of a message box dialog.
@@ -69,7 +69,7 @@ msgstr "התיקייה שוחזרה"
 #. Translators: The title of a dialog.
 #, python-brace-format
 msgid "Feeds: {defaultFeed} ({configProfile})"
-msgstr ""
+msgstr "הזנות: {defaultFeed} ({configProfile})"
 
 #. Label of a dialog (message translated in NVDA core in different contexts).
 msgid "&Filter by:"
@@ -99,6 +99,11 @@ msgstr "&מחק..."
 msgid "S&et default"
 msgstr "&בחר ברירת מחדל"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+#, fuzzy
+msgid "Open &folder containing a backup of feeds"
+msgstr "בחר תיקייה לשמור את גיבוי ההזנות הנוכחי"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "כתובת להזנה חדשה:"
@@ -120,19 +125,16 @@ msgid "Rename feed"
 msgstr "שנה שם הזנה"
 
 #. Translators: The label of the articles list in the articles dialog.
-#, fuzzy
 msgid "List of articles"
-msgstr "רשימת &מאמרים..."
+msgstr "רשימת מאמרים"
 
 #. Translators: The label of a button to open the selected article of a feed.
-#, fuzzy
 msgid "Open &web page of selected article."
-msgstr "פתיחת דף האינטרנט של המאמר שנבחר."
+msgstr "פתיחת &דף האינטרנט של המאמר שנבחר."
 
 #. Translators: The label of a button to show information of a feed article.
-#, fuzzy
 msgid "&About article..."
-msgstr "רשימת &מאמרים..."
+msgstr "אודות המאמר..."
 
 #. Translators: the label of a message box dialog.
 #, python-format
@@ -141,22 +143,21 @@ msgid ""
 "\r\n"
 "Do you want to copy article title and link to the clipboard?"
 msgstr ""
+"%s \n"
+"\r\n"
+"\rהאם ברצונך להעתיק את כותרת המאמר ולקשר ללוח הגזירים?"
 
 #. Translators: the title of a message box dialog.
 msgid "Article information"
-msgstr ""
+msgstr "מידע על המאמר"
 
 #. Translators: The title of the Copy dialog.
 msgid "Copy feeds"
 msgstr "העתק הזנה"
 
 #. Translators: An informational message displayed in the Copy dialog.
-#, fuzzy
 msgid "Select a folder to save a backup of your current feeds"
-msgstr ""
-"בחר תיקייה לשמור את גיבוי ההזנות הנוכחי..\n"
-"\n"
-"\t\t הם יועתקו  מ %s."
+msgstr "בחר תיקייה לשמור את גיבוי ההזנות הנוכחי"
 
 #. Translators: The label of a grouping containing controls to select the 
destination directory in the Copy dialog.
 msgid "directory for backup:"
@@ -171,12 +172,8 @@ msgid "Restore feeds"
 msgstr "שחזור ההזנות"
 
 #. Translators: An informational message displayed in the Restore dialog.
-#, fuzzy
 msgid "Select a folder to restore a backup of your previous copied feeds"
-msgstr ""
-"בחר תיקייה לשחזור ההזנות מהגיבוי האחרון שהועתק..\n"
-"\n"
-"\t\tהם יועתקו ל %s."
+msgstr "בחר תיקייה לשחזור ההזנות מהגיבוי האחרון שהועתק"
 
 #. Translators: The label of a grouping containing controls to select the 
destination directory in the Restore dialog.
 msgid "directory containing backup:"

diff --git a/addon/locale/hr/LC_MESSAGES/nvda.po 
b/addon/locale/hr/LC_MESSAGES/nvda.po
index 034c18d..3446a41 100644
--- a/addon/locale/hr/LC_MESSAGES/nvda.po
+++ b/addon/locale/hr/LC_MESSAGES/nvda.po
@@ -8,7 +8,7 @@ msgstr ""
 "Project-Id-Version: readFeeds 1.1-dev\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2014-02-08 17:08+0100\n"
-"PO-Revision-Date: 2017-02-21 19:57+0100\n"
+"PO-Revision-Date: 2018-11-25 19:01+0100\n"
 "Last-Translator: zwonimir Stanecic <zvonimirek222@xxxxxxxxxx>\n"
 "Language-Team: hr <LL@xxxxxx>\n"
 "Language: hr\n"
@@ -68,20 +68,19 @@ msgstr "Feedovi su vraćeni"
 #. Translators: The title of a dialog.
 #, python-brace-format
 msgid "Feeds: {defaultFeed} ({configProfile})"
-msgstr ""
+msgstr "Feedovi: {defaultFeed} ({configProfile})"
 
 #. Label of a dialog (message translated in NVDA core in different contexts).
 msgid "&Filter by:"
-msgstr ""
+msgstr "&Filtriraj:"
 
 #. Translators: The label of a button to open the list of articles of a feed.
 msgid "List of &articles..."
 msgstr "Popis &Članaka..."
 
 #. Translators: The label of a button to open a feed.
-#, fuzzy
 msgid "&Open feed"
-msgstr "Novi feed"
+msgstr "&Otvoriti feed"
 
 #. Translators: The label of a button to add a new feed.
 msgid "&New..."
@@ -99,6 +98,12 @@ msgstr "&Izbriši..."
 msgid "S&et default"
 msgstr "&postavi kao zadano"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+#, fuzzy
+msgid "Open &folder containing a backup of feeds"
+msgstr ""
+"Odaberite mapu u koju želite pospremiti sigurnosnu kopiju vaših feedova. "
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Adresa novog feeda:"
@@ -121,19 +126,16 @@ msgid "Rename feed"
 msgstr "Preimenuj feed"
 
 #. Translators: The label of the articles list in the articles dialog.
-#, fuzzy
 msgid "List of articles"
-msgstr "Popis &Članaka..."
+msgstr "Popis članaka"
 
 #. Translators: The label of a button to open the selected article of a feed.
-#, fuzzy
 msgid "Open &web page of selected article."
-msgstr "Otvori web stranicu trenutnog članka."
+msgstr "Otvoriti &web stranicu trenutnog članka."
 
 #. Translators: The label of a button to show information of a feed article.
-#, fuzzy
 msgid "&About article..."
-msgstr "Popis &Članaka..."
+msgstr "&O članku..."
 
 #. Translators: the label of a message box dialog.
 #, python-format
@@ -142,22 +144,22 @@ msgid ""
 "\r\n"
 "Do you want to copy article title and link to the clipboard?"
 msgstr ""
+"%s\r\n"
+"\r\n"
+"Želite li kopirati naslov i poveznicu do članka u međuspremnik?"
 
 #. Translators: the title of a message box dialog.
 msgid "Article information"
-msgstr ""
+msgstr "Informacije o članku"
 
 #. Translators: The title of the Copy dialog.
 msgid "Copy feeds"
 msgstr "Kopiraj feedove"
 
 #. Translators: An informational message displayed in the Copy dialog.
-#, fuzzy
 msgid "Select a folder to save a backup of your current feeds"
 msgstr ""
-"Odaberite mapu u koju želite spremiti sigurnosnu kopiju vaših feedova.\n"
-"\n"
-"\t\tOni će biti kopirani iz %s."
+"Odaberite mapu u koju želite pospremiti sigurnosnu kopiju vaših feedova. "
 
 #. Translators: The label of a grouping containing controls to select the 
destination directory in the Copy dialog.
 msgid "directory for backup:"
@@ -172,12 +174,8 @@ msgid "Restore feeds"
 msgstr "Vrati feedove"
 
 #. Translators: An informational message displayed in the Restore dialog.
-#, fuzzy
 msgid "Select a folder to restore a backup of your previous copied feeds"
-msgstr ""
-"Odaberite folder iz kojeg ću vratiti vaše feedove.\n"
-"\n"
-"\t\tThey will be copied to %s."
+msgstr "Označite mapu u koju želite vratiti vašu sigurnosnu kopiju feedova. "
 
 #. Translators: The label of a grouping containing controls to select the 
destination directory in the Restore dialog.
 msgid "directory containing backup:"

diff --git a/addon/locale/hu/LC_MESSAGES/nvda.po 
b/addon/locale/hu/LC_MESSAGES/nvda.po
index cbb5c1e..c6886d9 100644
--- a/addon/locale/hu/LC_MESSAGES/nvda.po
+++ b/addon/locale/hu/LC_MESSAGES/nvda.po
@@ -99,6 +99,13 @@ msgstr "&Törlés."
 msgid "S&et default"
 msgstr "A&lapértelmezett beállítás"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+#, fuzzy
+msgid "Open &folder containing a backup of feeds"
+msgstr ""
+"Kérem válasszon ki egy mappát a hírek másolásához, amelyek a következőből "
+"lesznek másolva %s."
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Új hírcsatorna címe:"

diff --git a/addon/locale/it/LC_MESSAGES/nvda.po 
b/addon/locale/it/LC_MESSAGES/nvda.po
index fdc3d32..b366b7d 100644
--- a/addon/locale/it/LC_MESSAGES/nvda.po
+++ b/addon/locale/it/LC_MESSAGES/nvda.po
@@ -3,8 +3,8 @@ msgstr ""
 "Project-Id-Version: ReadFeeds 3.0-dev\n"
 "Report-Msgid-Bugs-To: 'nvda-translations@xxxxxxxxxxxxx'\n"
 "POT-Creation-Date: 2015-07-24 10:22+0200\n"
-"PO-Revision-Date: 2018-11-02 10:06+0100\n"
-"Last-Translator: Simone Dal Maso <simone.dalmaso@xxxxxxxxx>\n"
+"PO-Revision-Date: 2019-04-01 12:27+0100\n"
+"Last-Translator: Chris Leo Mameli <llajta2012@xxxxxxxxx>\n"
 "Language-Team: Italian <simone.dalmaso@xxxxxxxxx>\n"
 "Language: it_IT\n"
 "MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
 "X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
 "X-Poedit-Basepath: .\n"
 "X-Poedit-SourceCharset: UTF-8\n"
-"X-Generator: Poedit 1.8.7\n"
+"X-Generator: Poedit 1.6.3\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Poedit-SearchPath-0: .\n"
 
@@ -98,6 +98,10 @@ msgstr "&Elimina..."
 msgid "S&et default"
 msgstr "Impo&sta predefinito"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+msgid "Open &folder containing a backup of feeds"
+msgstr "Cartella Bac&kup"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Indirizzo di un nuovo feed:"

diff --git a/addon/locale/pl/LC_MESSAGES/nvda.po 
b/addon/locale/pl/LC_MESSAGES/nvda.po
index 8e45005..ad1aec7 100644
--- a/addon/locale/pl/LC_MESSAGES/nvda.po
+++ b/addon/locale/pl/LC_MESSAGES/nvda.po
@@ -8,7 +8,7 @@ msgstr ""
 "Project-Id-Version: readFeeds 1.0-dev\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2013-11-16 13:26+0100\n"
-"PO-Revision-Date: 2018-09-22 17:09+0100\n"
+"PO-Revision-Date: 2019-07-06 22:16+0100\n"
 "Last-Translator: Zvonimir Stanečić <zvonimirek222@xxxxxxxxxxxxx>\n"
 "Language-Team: Polish <killer@xxxxxxxxxxxx>\n"
 "Language: pl\n"
@@ -98,6 +98,10 @@ msgstr "&Usuń..."
 msgid "S&et default"
 msgstr "U&staw domyślnie"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+msgid "Open &folder containing a backup of feeds"
+msgstr "otwórz &folder zawierający kopię twoich osobistych kanałów"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Adres nowego kanału osobistego:"

diff --git a/addon/locale/pt_BR/LC_MESSAGES/nvda.po 
b/addon/locale/pt_BR/LC_MESSAGES/nvda.po
index 32c058b..8c83923 100644
--- a/addon/locale/pt_BR/LC_MESSAGES/nvda.po
+++ b/addon/locale/pt_BR/LC_MESSAGES/nvda.po
@@ -100,6 +100,12 @@ msgstr "&Apagar..."
 msgid "S&et default"
 msgstr "D&efinir como padrão"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+#, fuzzy
+msgid "Open &folder containing a backup of feeds"
+msgstr ""
+"Selecione uma pasta para salvar cópia de segurança dos seus feeds atuais"
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Endereço do novo feed:"

diff --git a/addon/locale/pt_PT/LC_MESSAGES/nvda.po 
b/addon/locale/pt_PT/LC_MESSAGES/nvda.po
index 8fbb37a..47f4f65 100644
--- a/addon/locale/pt_PT/LC_MESSAGES/nvda.po
+++ b/addon/locale/pt_PT/LC_MESSAGES/nvda.po
@@ -8,7 +8,7 @@ msgstr ""
 "Project-Id-Version: readFeeds 1.0-dev\n"
 "Report-Msgid-Bugs-To: nvda-translations@xxxxxxxxxxxxx\n"
 "POT-Creation-Date: 2013-11-16 13:26+0100\n"
-"PO-Revision-Date: 2018-09-21 11:48+0100\n"
+"PO-Revision-Date: 2019-04-02 09:21+0100\n"
 "Last-Translator: Ângelo Miguel Abrantes <ampa4374@xxxxxxxxx>\n"
 "Language-Team: Equipa portuguesa de tradução do NVDA "
 "<angelomiguelabrantes@xxxxxxx>\n"
@@ -101,6 +101,10 @@ msgstr "&Apagar..."
 msgid "S&et default"
 msgstr "&Definir por padrão"
 
+#. Translators: The label of a button to open a folder containing a backup of 
feeds.
+msgid "Open &folder containing a backup of feeds"
+msgstr "Abrir uma pasta que contém um backup dos seus RSS actuais."
+
 #. Translators: The label of a field to enter an address for a new feed.
 msgid "Address of a new feed:"
 msgstr "Endereço de um RSS novo:"

This diff is so big that we needed to truncate the remainder.

https://bitbucket.org/nvdaaddonteam/readfeeds/commits/e16af5c54a51/
Changeset:   e16af5c54a51
Branch:      xmltree
User:        norrumar
Date:        2019-07-28 17:34:01+00:00
Summary:     Updated for future 2019.3

Affected #:  63 files

diff --git a/addon/globalPlugins/readFeeds/__init__.py 
b/addon/globalPlugins/readFeeds/__init__.py
index 4664e38..19bbba0 100644
--- a/addon/globalPlugins/readFeeds/__init__.py
+++ b/addon/globalPlugins/readFeeds/__init__.py
@@ -11,7 +11,7 @@ import addonHandler
 import globalPluginHandler
 import globalVars
 import config
-import urllib
+import urllib.request
 import scriptHandler
 from scriptHandler import script
 import api
@@ -24,9 +24,8 @@ from logHandler import log
 import re
 from .skipTranslation import translate
 
-sys.path.append(os.path.join(os.path.dirname(__file__), "..", ".."))
-from xml2.dom import minidom
-from xml2.etree import ElementTree
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", 
"..")))
+from xml.etree import ElementTree
 del sys.path[-1]
 
 addonHandler.initTranslation()
@@ -34,7 +33,7 @@ addonHandler.initTranslation()
 ### Constants
 
 ADDON_SUMMARY = addonHandler.getCodeAddon().manifest['summary']
-FEEDS_PATH = os.path.join(os.path.dirname(__file__), 
"personalFeeds").decode("mbcs")
+FEEDS_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 
"personalFeeds"))
 CONFIG_PATH = globalVars.appArgs.configPath
 DEFAULT_ADDRESS_FILE = "addressFile"
 # Translators: message presented when feeds cannot be reported.
@@ -192,7 +191,6 @@ class FeedsDialog(wx.Dialog):
                        feedName = "tempFeed"
                with open(os.path.join(FEEDS_PATH, "%s.txt" % feedName), "w") 
as f:
                        f.write(address)
-                       f.close()
                return feedName
 
        def onSearchEditTextChange(self, evt):
@@ -209,7 +207,8 @@ class FeedsDialog(wx.Dialog):
                        self.feedsList.Selection = 0
                        self.onFeedsListChoice(None)
                except:
-                       [control.Disable() for control in self.feedsList, 
self.articlesButton, self.openButton, self.renameButton, self.deleteButton, 
self.defaultButton]
+                       for control in (self.feedsList, self.articlesButton, 
self.openButton, self.renameButton, self.deleteButton, self.defaultButton):
+                               control.disable
 
        def onFeedsListChoice(self, evt):
                self.feedsList.Enable()
@@ -229,7 +228,6 @@ class FeedsDialog(wx.Dialog):
        def onArticles(self, evt):
                with open(os.path.join(FEEDS_PATH, "%s.txt" % self.stringSel), 
"r") as f:
                        address = f.read()
-                       f.close()
                self.feed = Feed(address)
                self.Disable()
                try:
@@ -241,7 +239,6 @@ class FeedsDialog(wx.Dialog):
        def onOpen(self, evt):
                with open(os.path.join(FEEDS_PATH, "%s.txt" % self.stringSel), 
"r") as f:
                        address = f.read()
-                       f.close()
                os.startfile(address)
 
        def onNew(self, evt):
@@ -307,7 +304,7 @@ class ArticlesDialog(wx.Dialog):
 
                # Translators: The label of the articles list in the articles 
dialog.
                articlesText = _("List of articles")
-               articlesChoices = [parent.feed.getArticleTitle(index) for index 
in xrange(parent.feed.getNumberOfArticles())]
+               articlesChoices = [parent.feed.getArticleTitle(index) for index 
in range(parent.feed.getNumberOfArticles())]
                self.articlesList = sHelper.addLabeledControl(articlesText, 
wx.ListBox, choices=articlesChoices)
                self.articlesList.Selection = 0
                self.articlesList.Bind(wx.EVT_CHOICE, self.onArticlesListChoice)
@@ -495,20 +492,19 @@ class Feed(object):
 
        def refresh(self):
                try:
-                       #self._document = 
minidom.parse(urllib.urlopen(self._url))
-                       self._document = 
ElementTree.parse(urllib.urlopen(self._url))
+                       self._document = 
ElementTree.parse(urllib.request.urlopen(self._url))
                except Exception as e:
                        raise e
                tag = self._document.getroot().tag
                self.ns = "%s}" % tag.split("}", 1)[0] if "}" in tag else None
                # Check if we are dealing with an rss or atom feed.
                if tag.endswith("rss"):
-                       main = 
self._document.getroot().find(self.buildTag("channel", self.ns))
-                       self._articles = main.findall(self.buildTag("item", 
self.ns))
+                       self._main = 
self._document.getroot().find(self.buildTag("channel", self.ns))
+                       self._articles = 
self._main.findall(self.buildTag("item", self.ns))
                        self._feedType = "rss"
                elif tag.endswith("feed"):
-                       main = self._document.getroot()
-                       self._articles = main.findall(self.buildTag("entry", 
self.ns))
+                       self._main = self._document.getroot()
+                       self._articles = 
self._main.findall(self.buildTag("entry", self.ns))
                        self._feedType = "atom"
                else:
                        log.debugWarning("Unknown type of current feed", 
exc_info=True)
@@ -523,7 +519,7 @@ class Feed(object):
 
        def getFeedName(self):
                try:
-                       return 
self._document.getroot().find(self.buildTag("title", self.ns)).text
+                       return self._main.find(self.buildTag("title", 
self.ns)).text
                except:
                        return ""
 
@@ -563,7 +559,7 @@ class Feed(object):
 
 class GlobalPlugin(globalPluginHandler.GlobalPlugin):
 
-       scriptCategory = unicode(ADDON_SUMMARY)
+       scriptCategory = ADDON_SUMMARY
 
        def __init__(self):
                super(GlobalPlugin, self).__init__()
@@ -633,7 +629,6 @@ class GlobalPlugin(globalPluginHandler.GlobalPlugin):
                addressFile = "%s.txt" % config.conf["readFeeds"]["addressFile"]
                with open(os.path.join(FEEDS_PATH, addressFile), "r") as f:
                        address = f.read()
-                       f.close()
                if self.feed and self.feed.getFeedUrl() == address:
                        curFeed = self.feed
                else:

diff --git a/addon/installTasks.py b/addon/installTasks.py
index 5488cda..4462c97 100644
--- a/addon/installTasks.py
+++ b/addon/installTasks.py
@@ -12,7 +12,7 @@ import glob
 import gui
 import wx
 
-ADDON_DIR = os.path.dirname(__file__).decode("mbcs")
+ADDON_DIR = os.path.abspath(os.path.dirname(__file__))
 FEEDS_PATH = os.path.join(ADDON_DIR, "globalPlugins", "readFeeds", 
"personalFeeds")
 CONFIG_PATH = globalVars.appArgs.configPath
 

diff --git a/addon/xml/__init__.py b/addon/xml/__init__.py
new file mode 100644
index 0000000..bf6d8dd
--- /dev/null
+++ b/addon/xml/__init__.py
@@ -0,0 +1,20 @@
+"""Core XML support for Python.
+
+This package contains four sub-packages:
+
+dom -- The W3C Document Object Model.  This supports DOM Level 1 +
+       Namespaces.
+
+parsers -- Python wrappers for XML parsers (currently only supports Expat).
+
+sax -- The Simple API for XML, developed by XML-Dev, led by David
+       Megginson and ported to Python by Lars Marius Garshol.  This
+       supports the SAX 2 API.
+
+etree -- The ElementTree XML library.  This is a subset of the full
+       ElementTree XML release.
+
+"""
+
+
+__all__ = ["dom", "parsers", "sax", "etree"]

diff --git a/addon/xml/dom/NodeFilter.py b/addon/xml/dom/NodeFilter.py
new file mode 100644
index 0000000..640e0bf
--- /dev/null
+++ b/addon/xml/dom/NodeFilter.py
@@ -0,0 +1,27 @@
+# This is the Python mapping for interface NodeFilter from
+# DOM2-Traversal-Range. It contains only constants.
+
+class NodeFilter:
+    """
+    This is the DOM2 NodeFilter interface. It contains only constants.
+    """
+    FILTER_ACCEPT = 1
+    FILTER_REJECT = 2
+    FILTER_SKIP   = 3
+
+    SHOW_ALL                    = 0xFFFFFFFF
+    SHOW_ELEMENT                = 0x00000001
+    SHOW_ATTRIBUTE              = 0x00000002
+    SHOW_TEXT                   = 0x00000004
+    SHOW_CDATA_SECTION          = 0x00000008
+    SHOW_ENTITY_REFERENCE       = 0x00000010
+    SHOW_ENTITY                 = 0x00000020
+    SHOW_PROCESSING_INSTRUCTION = 0x00000040
+    SHOW_COMMENT                = 0x00000080
+    SHOW_DOCUMENT               = 0x00000100
+    SHOW_DOCUMENT_TYPE          = 0x00000200
+    SHOW_DOCUMENT_FRAGMENT      = 0x00000400
+    SHOW_NOTATION               = 0x00000800
+
+    def acceptNode(self, node):
+        raise NotImplementedError

diff --git a/addon/xml/dom/__init__.py b/addon/xml/dom/__init__.py
new file mode 100644
index 0000000..97cf9a6
--- /dev/null
+++ b/addon/xml/dom/__init__.py
@@ -0,0 +1,140 @@
+"""W3C Document Object Model implementation for Python.
+
+The Python mapping of the Document Object Model is documented in the
+Python Library Reference in the section on the xml.dom package.
+
+This package contains the following modules:
+
+minidom -- A simple implementation of the Level 1 DOM with namespace
+           support added (based on the Level 2 specification) and other
+           minor Level 2 functionality.
+
+pulldom -- DOM builder supporting on-demand tree-building for selected
+           subtrees of the document.
+
+"""
+
+
+class Node:
+    """Class giving the NodeType constants."""
+    __slots__ = ()
+
+    # DOM implementations may use this as a base class for their own
+    # Node implementations.  If they don't, the constants defined here
+    # should still be used as the canonical definitions as they match
+    # the values given in the W3C recommendation.  Client code can
+    # safely refer to these values in all tests of Node.nodeType
+    # values.
+
+    ELEMENT_NODE                = 1
+    ATTRIBUTE_NODE              = 2
+    TEXT_NODE                   = 3
+    CDATA_SECTION_NODE          = 4
+    ENTITY_REFERENCE_NODE       = 5
+    ENTITY_NODE                 = 6
+    PROCESSING_INSTRUCTION_NODE = 7
+    COMMENT_NODE                = 8
+    DOCUMENT_NODE               = 9
+    DOCUMENT_TYPE_NODE          = 10
+    DOCUMENT_FRAGMENT_NODE      = 11
+    NOTATION_NODE               = 12
+
+
+#ExceptionCode
+INDEX_SIZE_ERR                 = 1
+DOMSTRING_SIZE_ERR             = 2
+HIERARCHY_REQUEST_ERR          = 3
+WRONG_DOCUMENT_ERR             = 4
+INVALID_CHARACTER_ERR          = 5
+NO_DATA_ALLOWED_ERR            = 6
+NO_MODIFICATION_ALLOWED_ERR    = 7
+NOT_FOUND_ERR                  = 8
+NOT_SUPPORTED_ERR              = 9
+INUSE_ATTRIBUTE_ERR            = 10
+INVALID_STATE_ERR              = 11
+SYNTAX_ERR                     = 12
+INVALID_MODIFICATION_ERR       = 13
+NAMESPACE_ERR                  = 14
+INVALID_ACCESS_ERR             = 15
+VALIDATION_ERR                 = 16
+
+
+class DOMException(Exception):
+    """Abstract base class for DOM exceptions.
+    Exceptions with specific codes are specializations of this class."""
+
+    def __init__(self, *args, **kw):
+        if self.__class__ is DOMException:
+            raise RuntimeError(
+                "DOMException should not be instantiated directly")
+        Exception.__init__(self, *args, **kw)
+
+    def _get_code(self):
+        return self.code
+
+
+class IndexSizeErr(DOMException):
+    code = INDEX_SIZE_ERR
+
+class DomstringSizeErr(DOMException):
+    code = DOMSTRING_SIZE_ERR
+
+class HierarchyRequestErr(DOMException):
+    code = HIERARCHY_REQUEST_ERR
+
+class WrongDocumentErr(DOMException):
+    code = WRONG_DOCUMENT_ERR
+
+class InvalidCharacterErr(DOMException):
+    code = INVALID_CHARACTER_ERR
+
+class NoDataAllowedErr(DOMException):
+    code = NO_DATA_ALLOWED_ERR
+
+class NoModificationAllowedErr(DOMException):
+    code = NO_MODIFICATION_ALLOWED_ERR
+
+class NotFoundErr(DOMException):
+    code = NOT_FOUND_ERR
+
+class NotSupportedErr(DOMException):
+    code = NOT_SUPPORTED_ERR
+
+class InuseAttributeErr(DOMException):
+    code = INUSE_ATTRIBUTE_ERR
+
+class InvalidStateErr(DOMException):
+    code = INVALID_STATE_ERR
+
+class SyntaxErr(DOMException):
+    code = SYNTAX_ERR
+
+class InvalidModificationErr(DOMException):
+    code = INVALID_MODIFICATION_ERR
+
+class NamespaceErr(DOMException):
+    code = NAMESPACE_ERR
+
+class InvalidAccessErr(DOMException):
+    code = INVALID_ACCESS_ERR
+
+class ValidationErr(DOMException):
+    code = VALIDATION_ERR
+
+class UserDataHandler:
+    """Class giving the operation constants for UserDataHandler.handle()."""
+
+    # Based on DOM Level 3 (WD 9 April 2002)
+
+    NODE_CLONED   = 1
+    NODE_IMPORTED = 2
+    NODE_DELETED  = 3
+    NODE_RENAMED  = 4
+
+XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace";
+XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/";
+XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
+EMPTY_NAMESPACE = None
+EMPTY_PREFIX = None
+
+from .domreg import getDOMImplementation, registerDOMImplementation

diff --git a/addon/xml/dom/domreg.py b/addon/xml/dom/domreg.py
new file mode 100644
index 0000000..69c17ee
--- /dev/null
+++ b/addon/xml/dom/domreg.py
@@ -0,0 +1,99 @@
+"""Registration facilities for DOM. This module should not be used
+directly. Instead, the functions getDOMImplementation and
+registerDOMImplementation should be imported from xml.dom."""
+
+# This is a list of well-known implementations.  Well-known names
+# should be published by posting to xml-sig@xxxxxxxxxx, and are
+# subsequently recorded in this file.
+
+import sys
+
+well_known_implementations = {
+    'minidom':'xml.dom.minidom',
+    '4DOM': 'xml.dom.DOMImplementation',
+    }
+
+# DOM implementations not officially registered should register
+# themselves with their
+
+registered = {}
+
+def registerDOMImplementation(name, factory):
+    """registerDOMImplementation(name, factory)
+
+    Register the factory function with the name. The factory function
+    should return an object which implements the DOMImplementation
+    interface. The factory function can either return the same object,
+    or a new one (e.g. if that implementation supports some
+    customization)."""
+
+    registered[name] = factory
+
+def _good_enough(dom, features):
+    "_good_enough(dom, features) -> Return 1 if the dom offers the features"
+    for f,v in features:
+        if not dom.hasFeature(f,v):
+            return 0
+    return 1
+
+def getDOMImplementation(name=None, features=()):
+    """getDOMImplementation(name = None, features = ()) -> DOM implementation.
+
+    Return a suitable DOM implementation. The name is either
+    well-known, the module name of a DOM implementation, or None. If
+    it is not None, imports the corresponding module and returns
+    DOMImplementation object if the import succeeds.
+
+    If name is not given, consider the available implementations to
+    find one with the required feature set. If no implementation can
+    be found, raise an ImportError. The features list must be a sequence
+    of (feature, version) pairs which are passed to hasFeature."""
+
+    import os
+    creator = None
+    mod = well_known_implementations.get(name)
+    if mod:
+        mod = __import__(mod, {}, {}, ['getDOMImplementation'])
+        return mod.getDOMImplementation()
+    elif name:
+        return registered[name]()
+    elif not sys.flags.ignore_environment and "PYTHON_DOM" in os.environ:
+        return getDOMImplementation(name = os.environ["PYTHON_DOM"])
+
+    # User did not specify a name, try implementations in arbitrary
+    # order, returning the one that has the required features
+    if isinstance(features, str):
+        features = _parse_feature_string(features)
+    for creator in registered.values():
+        dom = creator()
+        if _good_enough(dom, features):
+            return dom
+
+    for creator in well_known_implementations.keys():
+        try:
+            dom = getDOMImplementation(name = creator)
+        except Exception: # typically ImportError, or AttributeError
+            continue
+        if _good_enough(dom, features):
+            return dom
+
+    raise ImportError("no suitable DOM implementation found")
+
+def _parse_feature_string(s):
+    features = []
+    parts = s.split()
+    i = 0
+    length = len(parts)
+    while i < length:
+        feature = parts[i]
+        if feature[0] in "0123456789":
+            raise ValueError("bad feature name: %r" % (feature,))
+        i = i + 1
+        version = None
+        if i < length:
+            v = parts[i]
+            if v[0] in "0123456789":
+                i = i + 1
+                version = v
+        features.append((feature, version))
+    return tuple(features)

diff --git a/addon/xml/dom/expatbuilder.py b/addon/xml/dom/expatbuilder.py
new file mode 100644
index 0000000..2bd835b
--- /dev/null
+++ b/addon/xml/dom/expatbuilder.py
@@ -0,0 +1,965 @@
+"""Facility to use the Expat parser to load a minidom instance
+from a string or file.
+
+This avoids all the overhead of SAX and pulldom to gain performance.
+"""
+
+# Warning!
+#
+# This module is tightly bound to the implementation details of the
+# minidom DOM and can't be used with other DOM implementations.  This
+# is due, in part, to a lack of appropriate methods in the DOM (there is
+# no way to create Entity and Notation nodes via the DOM Level 2
+# interface), and for performance.  The latter is the cause of some fairly
+# cryptic code.
+#
+# Performance hacks:
+#
+#   -  .character_data_handler() has an extra case in which continuing
+#      data is appended to an existing Text node; this can be a
+#      speedup since pyexpat can break up character data into multiple
+#      callbacks even though we set the buffer_text attribute on the
+#      parser.  This also gives us the advantage that we don't need a
+#      separate normalization pass.
+#
+#   -  Determining that a node exists is done using an identity comparison
+#      with None rather than a truth test; this avoids searching for and
+#      calling any methods on the node object if it exists.  (A rather
+#      nice speedup is achieved this way as well!)
+
+from xml.dom import xmlbuilder, minidom, Node
+from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE
+from xml.parsers import expat
+from xml.dom.minidom import _append_child, _set_attribute_node
+from xml.dom.NodeFilter import NodeFilter
+
+TEXT_NODE = Node.TEXT_NODE
+CDATA_SECTION_NODE = Node.CDATA_SECTION_NODE
+DOCUMENT_NODE = Node.DOCUMENT_NODE
+
+FILTER_ACCEPT = xmlbuilder.DOMBuilderFilter.FILTER_ACCEPT
+FILTER_REJECT = xmlbuilder.DOMBuilderFilter.FILTER_REJECT
+FILTER_SKIP = xmlbuilder.DOMBuilderFilter.FILTER_SKIP
+FILTER_INTERRUPT = xmlbuilder.DOMBuilderFilter.FILTER_INTERRUPT
+
+theDOMImplementation = minidom.getDOMImplementation()
+
+# Expat typename -> TypeInfo
+_typeinfo_map = {
+    "CDATA":    minidom.TypeInfo(None, "cdata"),
+    "ENUM":     minidom.TypeInfo(None, "enumeration"),
+    "ENTITY":   minidom.TypeInfo(None, "entity"),
+    "ENTITIES": minidom.TypeInfo(None, "entities"),
+    "ID":       minidom.TypeInfo(None, "id"),
+    "IDREF":    minidom.TypeInfo(None, "idref"),
+    "IDREFS":   minidom.TypeInfo(None, "idrefs"),
+    "NMTOKEN":  minidom.TypeInfo(None, "nmtoken"),
+    "NMTOKENS": minidom.TypeInfo(None, "nmtokens"),
+    }
+
+class ElementInfo(object):
+    __slots__ = '_attr_info', '_model', 'tagName'
+
+    def __init__(self, tagName, model=None):
+        self.tagName = tagName
+        self._attr_info = []
+        self._model = model
+
+    def __getstate__(self):
+        return self._attr_info, self._model, self.tagName
+
+    def __setstate__(self, state):
+        self._attr_info, self._model, self.tagName = state
+
+    def getAttributeType(self, aname):
+        for info in self._attr_info:
+            if info[1] == aname:
+                t = info[-2]
+                if t[0] == "(":
+                    return _typeinfo_map["ENUM"]
+                else:
+                    return _typeinfo_map[info[-2]]
+        return minidom._no_type
+
+    def getAttributeTypeNS(self, namespaceURI, localName):
+        return minidom._no_type
+
+    def isElementContent(self):
+        if self._model:
+            type = self._model[0]
+            return type not in (expat.model.XML_CTYPE_ANY,
+                                expat.model.XML_CTYPE_MIXED)
+        else:
+            return False
+
+    def isEmpty(self):
+        if self._model:
+            return self._model[0] == expat.model.XML_CTYPE_EMPTY
+        else:
+            return False
+
+    def isId(self, aname):
+        for info in self._attr_info:
+            if info[1] == aname:
+                return info[-2] == "ID"
+        return False
+
+    def isIdNS(self, euri, ename, auri, aname):
+        # not sure this is meaningful
+        return self.isId((auri, aname))
+
+def _intern(builder, s):
+    return builder._intern_setdefault(s, s)
+
+def _parse_ns_name(builder, name):
+    assert ' ' in name
+    parts = name.split(' ')
+    intern = builder._intern_setdefault
+    if len(parts) == 3:
+        uri, localname, prefix = parts
+        prefix = intern(prefix, prefix)
+        qname = "%s:%s" % (prefix, localname)
+        qname = intern(qname, qname)
+        localname = intern(localname, localname)
+    elif len(parts) == 2:
+        uri, localname = parts
+        prefix = EMPTY_PREFIX
+        qname = localname = intern(localname, localname)
+    else:
+        raise ValueError("Unsupported syntax: spaces in URIs not supported: 
%r" % name)
+    return intern(uri, uri), localname, prefix, qname
+
+
+class ExpatBuilder:
+    """Document builder that uses Expat to build a ParsedXML.DOM document
+    instance."""
+
+    def __init__(self, options=None):
+        if options is None:
+            options = xmlbuilder.Options()
+        self._options = options
+        if self._options.filter is not None:
+            self._filter = FilterVisibilityController(self._options.filter)
+        else:
+            self._filter = None
+            # This *really* doesn't do anything in this case, so
+            # override it with something fast & minimal.
+            self._finish_start_element = id
+        self._parser = None
+        self.reset()
+
+    def createParser(self):
+        """Create a new parser object."""
+        return expat.ParserCreate()
+
+    def getParser(self):
+        """Return the parser object, creating a new one if needed."""
+        if not self._parser:
+            self._parser = self.createParser()
+            self._intern_setdefault = self._parser.intern.setdefault
+            self._parser.buffer_text = True
+            self._parser.ordered_attributes = True
+            self._parser.specified_attributes = True
+            self.install(self._parser)
+        return self._parser
+
+    def reset(self):
+        """Free all data structures used during DOM construction."""
+        self.document = theDOMImplementation.createDocument(
+            EMPTY_NAMESPACE, None, None)
+        self.curNode = self.document
+        self._elem_info = self.document._elem_info
+        self._cdata = False
+
+    def install(self, parser):
+        """Install the callbacks needed to build the DOM into the parser."""
+        # This creates circular references!
+        parser.StartDoctypeDeclHandler = self.start_doctype_decl_handler
+        parser.StartElementHandler = self.first_element_handler
+        parser.EndElementHandler = self.end_element_handler
+        parser.ProcessingInstructionHandler = self.pi_handler
+        if self._options.entities:
+            parser.EntityDeclHandler = self.entity_decl_handler
+        parser.NotationDeclHandler = self.notation_decl_handler
+        if self._options.comments:
+            parser.CommentHandler = self.comment_handler
+        if self._options.cdata_sections:
+            parser.StartCdataSectionHandler = self.start_cdata_section_handler
+            parser.EndCdataSectionHandler = self.end_cdata_section_handler
+            parser.CharacterDataHandler = self.character_data_handler_cdata
+        else:
+            parser.CharacterDataHandler = self.character_data_handler
+        parser.ExternalEntityRefHandler = self.external_entity_ref_handler
+        parser.XmlDeclHandler = self.xml_decl_handler
+        parser.ElementDeclHandler = self.element_decl_handler
+        parser.AttlistDeclHandler = self.attlist_decl_handler
+
+    def parseFile(self, file):
+        """Parse a document from a file object, returning the document
+        node."""
+        parser = self.getParser()
+        first_buffer = True
+        try:
+            while 1:
+                buffer = file.read(16*1024)
+                if not buffer:
+                    break
+                parser.Parse(buffer, 0)
+                if first_buffer and self.document.documentElement:
+                    self._setup_subset(buffer)
+                first_buffer = False
+            parser.Parse("", True)
+        except ParseEscape:
+            pass
+        doc = self.document
+        self.reset()
+        self._parser = None
+        return doc
+
+    def parseString(self, string):
+        """Parse a document from a string, returning the document node."""
+        parser = self.getParser()
+        try:
+            parser.Parse(string, True)
+            self._setup_subset(string)
+        except ParseEscape:
+            pass
+        doc = self.document
+        self.reset()
+        self._parser = None
+        return doc
+
+    def _setup_subset(self, buffer):
+        """Load the internal subset if there might be one."""
+        if self.document.doctype:
+            extractor = InternalSubsetExtractor()
+            extractor.parseString(buffer)
+            subset = extractor.getSubset()
+            self.document.doctype.internalSubset = subset
+
+    def start_doctype_decl_handler(self, doctypeName, systemId, publicId,
+                                   has_internal_subset):
+        doctype = self.document.implementation.createDocumentType(
+            doctypeName, publicId, systemId)
+        doctype.ownerDocument = self.document
+        _append_child(self.document, doctype)
+        self.document.doctype = doctype
+        if self._filter and self._filter.acceptNode(doctype) == FILTER_REJECT:
+            self.document.doctype = None
+            del self.document.childNodes[-1]
+            doctype = None
+            self._parser.EntityDeclHandler = None
+            self._parser.NotationDeclHandler = None
+        if has_internal_subset:
+            if doctype is not None:
+                doctype.entities._seq = []
+                doctype.notations._seq = []
+            self._parser.CommentHandler = None
+            self._parser.ProcessingInstructionHandler = None
+            self._parser.EndDoctypeDeclHandler = self.end_doctype_decl_handler
+
+    def end_doctype_decl_handler(self):
+        if self._options.comments:
+            self._parser.CommentHandler = self.comment_handler
+        self._parser.ProcessingInstructionHandler = self.pi_handler
+        if not (self._elem_info or self._filter):
+            self._finish_end_element = id
+
+    def pi_handler(self, target, data):
+        node = self.document.createProcessingInstruction(target, data)
+        _append_child(self.curNode, node)
+        if self._filter and self._filter.acceptNode(node) == FILTER_REJECT:
+            self.curNode.removeChild(node)
+
+    def character_data_handler_cdata(self, data):
+        childNodes = self.curNode.childNodes
+        if self._cdata:
+            if (  self._cdata_continue
+                  and childNodes[-1].nodeType == CDATA_SECTION_NODE):
+                childNodes[-1].appendData(data)
+                return
+            node = self.document.createCDATASection(data)
+            self._cdata_continue = True
+        elif childNodes and childNodes[-1].nodeType == TEXT_NODE:
+            node = childNodes[-1]
+            value = node.data + data
+            node.data = value
+            return
+        else:
+            node = minidom.Text()
+            node.data = data
+            node.ownerDocument = self.document
+        _append_child(self.curNode, node)
+
+    def character_data_handler(self, data):
+        childNodes = self.curNode.childNodes
+        if childNodes and childNodes[-1].nodeType == TEXT_NODE:
+            node = childNodes[-1]
+            node.data = node.data + data
+            return
+        node = minidom.Text()
+        node.data = node.data + data
+        node.ownerDocument = self.document
+        _append_child(self.curNode, node)
+
+    def entity_decl_handler(self, entityName, is_parameter_entity, value,
+                            base, systemId, publicId, notationName):
+        if is_parameter_entity:
+            # we don't care about parameter entities for the DOM
+            return
+        if not self._options.entities:
+            return
+        node = self.document._create_entity(entityName, publicId,
+                                            systemId, notationName)
+        if value is not None:
+            # internal entity
+            # node *should* be readonly, but we'll cheat
+            child = self.document.createTextNode(value)
+            node.childNodes.append(child)
+        self.document.doctype.entities._seq.append(node)
+        if self._filter and self._filter.acceptNode(node) == FILTER_REJECT:
+            del self.document.doctype.entities._seq[-1]
+
+    def notation_decl_handler(self, notationName, base, systemId, publicId):
+        node = self.document._create_notation(notationName, publicId, systemId)
+        self.document.doctype.notations._seq.append(node)
+        if self._filter and self._filter.acceptNode(node) == FILTER_ACCEPT:
+            del self.document.doctype.notations._seq[-1]
+
+    def comment_handler(self, data):
+        node = self.document.createComment(data)
+        _append_child(self.curNode, node)
+        if self._filter and self._filter.acceptNode(node) == FILTER_REJECT:
+            self.curNode.removeChild(node)
+
+    def start_cdata_section_handler(self):
+        self._cdata = True
+        self._cdata_continue = False
+
+    def end_cdata_section_handler(self):
+        self._cdata = False
+        self._cdata_continue = False
+
+    def external_entity_ref_handler(self, context, base, systemId, publicId):
+        return 1
+
+    def first_element_handler(self, name, attributes):
+        if self._filter is None and not self._elem_info:
+            self._finish_end_element = id
+        self.getParser().StartElementHandler = self.start_element_handler
+        self.start_element_handler(name, attributes)
+
+    def start_element_handler(self, name, attributes):
+        node = self.document.createElement(name)
+        _append_child(self.curNode, node)
+        self.curNode = node
+
+        if attributes:
+            for i in range(0, len(attributes), 2):
+                a = minidom.Attr(attributes[i], EMPTY_NAMESPACE,
+                                 None, EMPTY_PREFIX)
+                value = attributes[i+1]
+                a.value = value
+                a.ownerDocument = self.document
+                _set_attribute_node(node, a)
+
+        if node is not self.document.documentElement:
+            self._finish_start_element(node)
+
+    def _finish_start_element(self, node):
+        if self._filter:
+            # To be general, we'd have to call isSameNode(), but this
+            # is sufficient for minidom:
+            if node is self.document.documentElement:
+                return
+            filt = self._filter.startContainer(node)
+            if filt == FILTER_REJECT:
+                # ignore this node & all descendents
+                Rejecter(self)
+            elif filt == FILTER_SKIP:
+                # ignore this node, but make it's children become
+                # children of the parent node
+                Skipper(self)
+            else:
+                return
+            self.curNode = node.parentNode
+            node.parentNode.removeChild(node)
+            node.unlink()
+
+    # If this ever changes, Namespaces.end_element_handler() needs to
+    # be changed to match.
+    #
+    def end_element_handler(self, name):
+        curNode = self.curNode
+        self.curNode = curNode.parentNode
+        self._finish_end_element(curNode)
+
+    def _finish_end_element(self, curNode):
+        info = self._elem_info.get(curNode.tagName)
+        if info:
+            self._handle_white_text_nodes(curNode, info)
+        if self._filter:
+            if curNode is self.document.documentElement:
+                return
+            if self._filter.acceptNode(curNode) == FILTER_REJECT:
+                self.curNode.removeChild(curNode)
+                curNode.unlink()
+
+    def _handle_white_text_nodes(self, node, info):
+        if (self._options.whitespace_in_element_content
+            or not info.isElementContent()):
+            return
+
+        # We have element type information and should remove ignorable
+        # whitespace; identify for text nodes which contain only
+        # whitespace.
+        L = []
+        for child in node.childNodes:
+            if child.nodeType == TEXT_NODE and not child.data.strip():
+                L.append(child)
+
+        # Remove ignorable whitespace from the tree.
+        for child in L:
+            node.removeChild(child)
+
+    def element_decl_handler(self, name, model):
+        info = self._elem_info.get(name)
+        if info is None:
+            self._elem_info[name] = ElementInfo(name, model)
+        else:
+            assert info._model is None
+            info._model = model
+
+    def attlist_decl_handler(self, elem, name, type, default, required):
+        info = self._elem_info.get(elem)
+        if info is None:
+            info = ElementInfo(elem)
+            self._elem_info[elem] = info
+        info._attr_info.append(
+            [None, name, None, None, default, 0, type, required])
+
+    def xml_decl_handler(self, version, encoding, standalone):
+        self.document.version = version
+        self.document.encoding = encoding
+        # This is still a little ugly, thanks to the pyexpat API. ;-(
+        if standalone >= 0:
+            if standalone:
+                self.document.standalone = True
+            else:
+                self.document.standalone = False
+
+
+# Don't include FILTER_INTERRUPT, since that's checked separately
+# where allowed.
+_ALLOWED_FILTER_RETURNS = (FILTER_ACCEPT, FILTER_REJECT, FILTER_SKIP)
+
+class FilterVisibilityController(object):
+    """Wrapper around a DOMBuilderFilter which implements the checks
+    to make the whatToShow filter attribute work."""
+
+    __slots__ = 'filter',
+
+    def __init__(self, filter):
+        self.filter = filter
+
+    def startContainer(self, node):
+        mask = self._nodetype_mask[node.nodeType]
+        if self.filter.whatToShow & mask:
+            val = self.filter.startContainer(node)
+            if val == FILTER_INTERRUPT:
+                raise ParseEscape
+            if val not in _ALLOWED_FILTER_RETURNS:
+                raise ValueError(
+                      "startContainer() returned illegal value: " + repr(val))
+            return val
+        else:
+            return FILTER_ACCEPT
+
+    def acceptNode(self, node):
+        mask = self._nodetype_mask[node.nodeType]
+        if self.filter.whatToShow & mask:
+            val = self.filter.acceptNode(node)
+            if val == FILTER_INTERRUPT:
+                raise ParseEscape
+            if val == FILTER_SKIP:
+                # move all child nodes to the parent, and remove this node
+                parent = node.parentNode
+                for child in node.childNodes[:]:
+                    parent.appendChild(child)
+                # node is handled by the caller
+                return FILTER_REJECT
+            if val not in _ALLOWED_FILTER_RETURNS:
+                raise ValueError(
+                      "acceptNode() returned illegal value: " + repr(val))
+            return val
+        else:
+            return FILTER_ACCEPT
+
+    _nodetype_mask = {
+        Node.ELEMENT_NODE:                NodeFilter.SHOW_ELEMENT,
+        Node.ATTRIBUTE_NODE:              NodeFilter.SHOW_ATTRIBUTE,
+        Node.TEXT_NODE:                   NodeFilter.SHOW_TEXT,
+        Node.CDATA_SECTION_NODE:          NodeFilter.SHOW_CDATA_SECTION,
+        Node.ENTITY_REFERENCE_NODE:       NodeFilter.SHOW_ENTITY_REFERENCE,
+        Node.ENTITY_NODE:                 NodeFilter.SHOW_ENTITY,
+        Node.PROCESSING_INSTRUCTION_NODE: 
NodeFilter.SHOW_PROCESSING_INSTRUCTION,
+        Node.COMMENT_NODE:                NodeFilter.SHOW_COMMENT,
+        Node.DOCUMENT_NODE:               NodeFilter.SHOW_DOCUMENT,
+        Node.DOCUMENT_TYPE_NODE:          NodeFilter.SHOW_DOCUMENT_TYPE,
+        Node.DOCUMENT_FRAGMENT_NODE:      NodeFilter.SHOW_DOCUMENT_FRAGMENT,
+        Node.NOTATION_NODE:               NodeFilter.SHOW_NOTATION,
+        }
+
+
+class FilterCrutch(object):
+    __slots__ = '_builder', '_level', '_old_start', '_old_end'
+
+    def __init__(self, builder):
+        self._level = 0
+        self._builder = builder
+        parser = builder._parser
+        self._old_start = parser.StartElementHandler
+        self._old_end = parser.EndElementHandler
+        parser.StartElementHandler = self.start_element_handler
+        parser.EndElementHandler = self.end_element_handler
+
+class Rejecter(FilterCrutch):
+    __slots__ = ()
+
+    def __init__(self, builder):
+        FilterCrutch.__init__(self, builder)
+        parser = builder._parser
+        for name in ("ProcessingInstructionHandler",
+                     "CommentHandler",
+                     "CharacterDataHandler",
+                     "StartCdataSectionHandler",
+                     "EndCdataSectionHandler",
+                     "ExternalEntityRefHandler",
+                     ):
+            setattr(parser, name, None)
+
+    def start_element_handler(self, *args):
+        self._level = self._level + 1
+
+    def end_element_handler(self, *args):
+        if self._level == 0:
+            # restore the old handlers
+            parser = self._builder._parser
+            self._builder.install(parser)
+            parser.StartElementHandler = self._old_start
+            parser.EndElementHandler = self._old_end
+        else:
+            self._level = self._level - 1
+
+class Skipper(FilterCrutch):
+    __slots__ = ()
+
+    def start_element_handler(self, *args):
+        node = self._builder.curNode
+        self._old_start(*args)
+        if self._builder.curNode is not node:
+            self._level = self._level + 1
+
+    def end_element_handler(self, *args):
+        if self._level == 0:
+            # We're popping back out of the node we're skipping, so we
+            # shouldn't need to do anything but reset the handlers.
+            self._builder._parser.StartElementHandler = self._old_start
+            self._builder._parser.EndElementHandler = self._old_end
+            self._builder = None
+        else:
+            self._level = self._level - 1
+            self._old_end(*args)
+
+
+# framework document used by the fragment builder.
+# Takes a string for the doctype, subset string, and namespace attrs string.
+
+_FRAGMENT_BUILDER_INTERNAL_SYSTEM_ID = \
+    "http://xml.python.org/entities/fragment-builder/internal";
+
+_FRAGMENT_BUILDER_TEMPLATE = (
+    '''\
+<!DOCTYPE wrapper
+  %%s [
+  <!ENTITY fragment-builder-internal
+    SYSTEM "%s">
+%%s
+]>
+<wrapper %%s
+>&fragment-builder-internal;</wrapper>'''
+    % _FRAGMENT_BUILDER_INTERNAL_SYSTEM_ID)
+
+
+class FragmentBuilder(ExpatBuilder):
+    """Builder which constructs document fragments given XML source
+    text and a context node.
+
+    The context node is expected to provide information about the
+    namespace declarations which are in scope at the start of the
+    fragment.
+    """
+
+    def __init__(self, context, options=None):
+        if context.nodeType == DOCUMENT_NODE:
+            self.originalDocument = context
+            self.context = context
+        else:
+            self.originalDocument = context.ownerDocument
+            self.context = context
+        ExpatBuilder.__init__(self, options)
+
+    def reset(self):
+        ExpatBuilder.reset(self)
+        self.fragment = None
+
+    def parseFile(self, file):
+        """Parse a document fragment from a file object, returning the
+        fragment node."""
+        return self.parseString(file.read())
+
+    def parseString(self, string):
+        """Parse a document fragment from a string, returning the
+        fragment node."""
+        self._source = string
+        parser = self.getParser()
+        doctype = self.originalDocument.doctype
+        ident = ""
+        if doctype:
+            subset = doctype.internalSubset or self._getDeclarations()
+            if doctype.publicId:
+                ident = ('PUBLIC "%s" "%s"'
+                         % (doctype.publicId, doctype.systemId))
+            elif doctype.systemId:
+                ident = 'SYSTEM "%s"' % doctype.systemId
+        else:
+            subset = ""
+        nsattrs = self._getNSattrs() # get ns decls from node's ancestors
+        document = _FRAGMENT_BUILDER_TEMPLATE % (ident, subset, nsattrs)
+        try:
+            parser.Parse(document, 1)
+        except:
+            self.reset()
+            raise
+        fragment = self.fragment
+        self.reset()
+##         self._parser = None
+        return fragment
+
+    def _getDeclarations(self):
+        """Re-create the internal subset from the DocumentType node.
+
+        This is only needed if we don't already have the
+        internalSubset as a string.
+        """
+        doctype = self.context.ownerDocument.doctype
+        s = ""
+        if doctype:
+            for i in range(doctype.notations.length):
+                notation = doctype.notations.item(i)
+                if s:
+                    s = s + "\n  "
+                s = "%s<!NOTATION %s" % (s, notation.nodeName)
+                if notation.publicId:
+                    s = '%s PUBLIC "%s"\n             "%s">' \
+                        % (s, notation.publicId, notation.systemId)
+                else:
+                    s = '%s SYSTEM "%s">' % (s, notation.systemId)
+            for i in range(doctype.entities.length):
+                entity = doctype.entities.item(i)
+                if s:
+                    s = s + "\n  "
+                s = "%s<!ENTITY %s" % (s, entity.nodeName)
+                if entity.publicId:
+                    s = '%s PUBLIC "%s"\n             "%s"' \
+                        % (s, entity.publicId, entity.systemId)
+                elif entity.systemId:
+                    s = '%s SYSTEM "%s"' % (s, entity.systemId)
+                else:
+                    s = '%s "%s"' % (s, entity.firstChild.data)
+                if entity.notationName:
+                    s = "%s NOTATION %s" % (s, entity.notationName)
+                s = s + ">"
+        return s
+
+    def _getNSattrs(self):
+        return ""
+
+    def external_entity_ref_handler(self, context, base, systemId, publicId):
+        if systemId == _FRAGMENT_BUILDER_INTERNAL_SYSTEM_ID:
+            # this entref is the one that we made to put the subtree
+            # in; all of our given input is parsed in here.
+            old_document = self.document
+            old_cur_node = self.curNode
+            parser = self._parser.ExternalEntityParserCreate(context)
+            # put the real document back, parse into the fragment to return
+            self.document = self.originalDocument
+            self.fragment = self.document.createDocumentFragment()
+            self.curNode = self.fragment
+            try:
+                parser.Parse(self._source, 1)
+            finally:
+                self.curNode = old_cur_node
+                self.document = old_document
+                self._source = None
+            return -1
+        else:
+            return ExpatBuilder.external_entity_ref_handler(
+                self, context, base, systemId, publicId)
+
+
+class Namespaces:
+    """Mix-in class for builders; adds support for namespaces."""
+
+    def _initNamespaces(self):
+        # list of (prefix, uri) ns declarations.  Namespace attrs are
+        # constructed from this and added to the element's attrs.
+        self._ns_ordered_prefixes = []
+
+    def createParser(self):
+        """Create a new namespace-handling parser."""
+        parser = expat.ParserCreate(namespace_separator=" ")
+        parser.namespace_prefixes = True
+        return parser
+
+    def install(self, parser):
+        """Insert the namespace-handlers onto the parser."""
+        ExpatBuilder.install(self, parser)
+        if self._options.namespace_declarations:
+            parser.StartNamespaceDeclHandler = (
+                self.start_namespace_decl_handler)
+
+    def start_namespace_decl_handler(self, prefix, uri):
+        """Push this namespace declaration on our storage."""
+        self._ns_ordered_prefixes.append((prefix, uri))
+
+    def start_element_handler(self, name, attributes):
+        if ' ' in name:
+            uri, localname, prefix, qname = _parse_ns_name(self, name)
+        else:
+            uri = EMPTY_NAMESPACE
+            qname = name
+            localname = None
+            prefix = EMPTY_PREFIX
+        node = minidom.Element(qname, uri, prefix, localname)
+        node.ownerDocument = self.document
+        _append_child(self.curNode, node)
+        self.curNode = node
+
+        if self._ns_ordered_prefixes:
+            for prefix, uri in self._ns_ordered_prefixes:
+                if prefix:
+                    a = minidom.Attr(_intern(self, 'xmlns:' + prefix),
+                                     XMLNS_NAMESPACE, prefix, "xmlns")
+                else:
+                    a = minidom.Attr("xmlns", XMLNS_NAMESPACE,
+                                     "xmlns", EMPTY_PREFIX)
+                a.value = uri
+                a.ownerDocument = self.document
+                _set_attribute_node(node, a)
+            del self._ns_ordered_prefixes[:]
+
+        if attributes:
+            node._ensure_attributes()
+            _attrs = node._attrs
+            _attrsNS = node._attrsNS
+            for i in range(0, len(attributes), 2):
+                aname = attributes[i]
+                value = attributes[i+1]
+                if ' ' in aname:
+                    uri, localname, prefix, qname = _parse_ns_name(self, aname)
+                    a = minidom.Attr(qname, uri, localname, prefix)
+                    _attrs[qname] = a
+                    _attrsNS[(uri, localname)] = a
+                else:
+                    a = minidom.Attr(aname, EMPTY_NAMESPACE,
+                                     aname, EMPTY_PREFIX)
+                    _attrs[aname] = a
+                    _attrsNS[(EMPTY_NAMESPACE, aname)] = a
+                a.ownerDocument = self.document
+                a.value = value
+                a.ownerElement = node
+
+    if __debug__:
+        # This only adds some asserts to the original
+        # end_element_handler(), so we only define this when -O is not
+        # used.  If changing one, be sure to check the other to see if
+        # it needs to be changed as well.
+        #
+        def end_element_handler(self, name):
+            curNode = self.curNode
+            if ' ' in name:
+                uri, localname, prefix, qname = _parse_ns_name(self, name)
+                assert (curNode.namespaceURI == uri
+                        and curNode.localName == localname
+                        and curNode.prefix == prefix), \
+                        "element stack messed up! (namespace)"
+            else:
+                assert curNode.nodeName == name, \
+                       "element stack messed up - bad nodeName"
+                assert curNode.namespaceURI == EMPTY_NAMESPACE, \
+                       "element stack messed up - bad namespaceURI"
+            self.curNode = curNode.parentNode
+            self._finish_end_element(curNode)
+
+
+class ExpatBuilderNS(Namespaces, ExpatBuilder):
+    """Document builder that supports namespaces."""
+
+    def reset(self):
+        ExpatBuilder.reset(self)
+        self._initNamespaces()
+
+
+class FragmentBuilderNS(Namespaces, FragmentBuilder):
+    """Fragment builder that supports namespaces."""
+
+    def reset(self):
+        FragmentBuilder.reset(self)
+        self._initNamespaces()
+
+    def _getNSattrs(self):
+        """Return string of namespace attributes from this element and
+        ancestors."""
+        # XXX This needs to be re-written to walk the ancestors of the
+        # context to build up the namespace information from
+        # declarations, elements, and attributes found in context.
+        # Otherwise we have to store a bunch more data on the DOM
+        # (though that *might* be more reliable -- not clear).
+        attrs = ""
+        context = self.context
+        L = []
+        while context:
+            if hasattr(context, '_ns_prefix_uri'):
+                for prefix, uri in context._ns_prefix_uri.items():
+                    # add every new NS decl from context to L and attrs string
+                    if prefix in L:
+                        continue
+                    L.append(prefix)
+                    if prefix:
+                        declname = "xmlns:" + prefix
+                    else:
+                        declname = "xmlns"
+                    if attrs:
+                        attrs = "%s\n    %s='%s'" % (attrs, declname, uri)
+                    else:
+                        attrs = " %s='%s'" % (declname, uri)
+            context = context.parentNode
+        return attrs
+
+
+class ParseEscape(Exception):
+    """Exception raised to short-circuit parsing in InternalSubsetExtractor."""
+    pass
+
+class InternalSubsetExtractor(ExpatBuilder):
+    """XML processor which can rip out the internal document type subset."""
+
+    subset = None
+
+    def getSubset(self):
+        """Return the internal subset as a string."""
+        return self.subset
+
+    def parseFile(self, file):
+        try:
+            ExpatBuilder.parseFile(self, file)
+        except ParseEscape:
+            pass
+
+    def parseString(self, string):
+        try:
+            ExpatBuilder.parseString(self, string)
+        except ParseEscape:
+            pass
+
+    def install(self, parser):
+        parser.StartDoctypeDeclHandler = self.start_doctype_decl_handler
+        parser.StartElementHandler = self.start_element_handler
+
+    def start_doctype_decl_handler(self, name, publicId, systemId,
+                                   has_internal_subset):
+        if has_internal_subset:
+            parser = self.getParser()
+            self.subset = []
+            parser.DefaultHandler = self.subset.append
+            parser.EndDoctypeDeclHandler = self.end_doctype_decl_handler
+        else:
+            raise ParseEscape()
+
+    def end_doctype_decl_handler(self):
+        s = ''.join(self.subset).replace('\r\n', '\n').replace('\r', '\n')
+        self.subset = s
+        raise ParseEscape()
+
+    def start_element_handler(self, name, attrs):
+        raise ParseEscape()
+
+
+def parse(file, namespaces=True):
+    """Parse a document, returning the resulting Document node.
+
+    'file' may be either a file name or an open file object.
+    """
+    if namespaces:
+        builder = ExpatBuilderNS()
+    else:
+        builder = ExpatBuilder()
+
+    if isinstance(file, str):
+        with open(file, 'rb') as fp:
+            result = builder.parseFile(fp)
+    else:
+        result = builder.parseFile(file)
+    return result
+
+
+def parseString(string, namespaces=True):
+    """Parse a document from a string, returning the resulting
+    Document node.
+    """
+    if namespaces:
+        builder = ExpatBuilderNS()
+    else:
+        builder = ExpatBuilder()
+    return builder.parseString(string)
+
+
+def parseFragment(file, context, namespaces=True):
+    """Parse a fragment of a document, given the context from which it
+    was originally extracted.  context should be the parent of the
+    node(s) which are in the fragment.
+
+    'file' may be either a file name or an open file object.
+    """
+    if namespaces:
+        builder = FragmentBuilderNS(context)
+    else:
+        builder = FragmentBuilder(context)
+
+    if isinstance(file, str):
+        with open(file, 'rb') as fp:
+            result = builder.parseFile(fp)
+    else:
+        result = builder.parseFile(file)
+    return result
+
+
+def parseFragmentString(string, context, namespaces=True):
+    """Parse a fragment of a document from a string, given the context
+    from which it was originally extracted.  context should be the
+    parent of the node(s) which are in the fragment.
+    """
+    if namespaces:
+        builder = FragmentBuilderNS(context)
+    else:
+        builder = FragmentBuilder(context)
+    return builder.parseString(string)
+
+
+def makeBuilder(options):
+    """Create a builder based on an Options object."""
+    if options.namespaces:
+        return ExpatBuilderNS(options)
+    else:
+        return ExpatBuilder(options)

diff --git a/addon/xml/dom/minicompat.py b/addon/xml/dom/minicompat.py
new file mode 100644
index 0000000..5d6fae9
--- /dev/null
+++ b/addon/xml/dom/minicompat.py
@@ -0,0 +1,109 @@
+"""Python version compatibility support for minidom.
+
+This module contains internal implementation details and
+should not be imported; use xml.dom.minidom instead.
+"""
+
+# This module should only be imported using "import *".
+#
+# The following names are defined:
+#
+#   NodeList      -- lightest possible NodeList implementation
+#
+#   EmptyNodeList -- lightest possible NodeList that is guaranteed to
+#                    remain empty (immutable)
+#
+#   StringTypes   -- tuple of defined string types
+#
+#   defproperty   -- function used in conjunction with GetattrMagic;
+#                    using these together is needed to make them work
+#                    as efficiently as possible in both Python 2.2+
+#                    and older versions.  For example:
+#
+#                        class MyClass(GetattrMagic):
+#                            def _get_myattr(self):
+#                                return something
+#
+#                        defproperty(MyClass, "myattr",
+#                                    "return some value")
+#
+#                    For Python 2.2 and newer, this will construct a
+#                    property object on the class, which avoids
+#                    needing to override __getattr__().  It will only
+#                    work for read-only attributes.
+#
+#                    For older versions of Python, inheriting from
+#                    GetattrMagic will use the traditional
+#                    __getattr__() hackery to achieve the same effect,
+#                    but less efficiently.
+#
+#                    defproperty() should be used for each version of
+#                    the relevant _get_<property>() function.
+
+__all__ = ["NodeList", "EmptyNodeList", "StringTypes", "defproperty"]
+
+import xml.dom
+
+StringTypes = (str,)
+
+
+class NodeList(list):
+    __slots__ = ()
+
+    def item(self, index):
+        if 0 <= index < len(self):
+            return self[index]
+
+    def _get_length(self):
+        return len(self)
+
+    def _set_length(self, value):
+        raise xml.dom.NoModificationAllowedErr(
+            "attempt to modify read-only attribute 'length'")
+
+    length = property(_get_length, _set_length,
+                      doc="The number of nodes in the NodeList.")
+
+    # For backward compatibility
+    def __setstate__(self, state):
+        if state is None:
+            state = []
+        self[:] = state
+
+
+class EmptyNodeList(tuple):
+    __slots__ = ()
+
+    def __add__(self, other):
+        NL = NodeList()
+        NL.extend(other)
+        return NL
+
+    def __radd__(self, other):
+        NL = NodeList()
+        NL.extend(other)
+        return NL
+
+    def item(self, index):
+        return None
+
+    def _get_length(self):
+        return 0
+
+    def _set_length(self, value):
+        raise xml.dom.NoModificationAllowedErr(
+            "attempt to modify read-only attribute 'length'")
+
+    length = property(_get_length, _set_length,
+                      doc="The number of nodes in the NodeList.")
+
+
+def defproperty(klass, name, doc):
+    get = getattr(klass, ("_get_" + name))
+    def set(self, value, name=name):
+        raise xml.dom.NoModificationAllowedErr(
+            "attempt to modify read-only attribute " + repr(name))
+    assert not hasattr(klass, "_set_" + name), \
+           "expected not to find _set_" + name
+    prop = property(get, set, doc=doc)
+    setattr(klass, name, prop)

This diff is so big that we needed to truncate the remainder.

Repository URL: https://bitbucket.org/nvdaaddonteam/readfeeds/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.

Other related posts: