Procházet zdrojové kódy

Change i18n process (#4131)

Before, the ignore info were stored in a different file which was a bit cumbersome
for new comers. Now, this info is stored directly in the translation file as a
comment.

Before, there was no way of telling translators that a previously translated string
was in need of a new translation. Now, the dirty information is there to convey that
info.
Alexis Degrugillier před 4 roky
rodič
revize
127b7f0a3a
100 změnil soubory, kde provedl 3191 přidání a 2191 odebrání
  1. 37 27
      app/i18n/cz/admin.php
  2. 69 59
      app/i18n/cz/conf.php
  3. 29 19
      app/i18n/cz/feedback.php
  4. 75 65
      app/i18n/cz/gen.php
  5. 15 5
      app/i18n/cz/index.php
  6. 17 7
      app/i18n/cz/install.php
  7. 64 54
      app/i18n/cz/sub.php
  8. 30 20
      app/i18n/cz/user.php
  9. 15 5
      app/i18n/de/admin.php
  10. 19 9
      app/i18n/de/conf.php
  11. 10 0
      app/i18n/de/feedback.php
  12. 56 46
      app/i18n/de/gen.php
  13. 12 2
      app/i18n/de/index.php
  14. 12 2
      app/i18n/de/install.php
  15. 15 5
      app/i18n/de/sub.php
  16. 10 0
      app/i18n/de/user.php
  17. 139 129
      app/i18n/en-us/admin.php
  18. 182 172
      app/i18n/en-us/conf.php
  19. 92 82
      app/i18n/en-us/feedback.php
  20. 191 181
      app/i18n/en-us/gen.php
  21. 55 45
      app/i18n/en-us/index.php
  22. 79 69
      app/i18n/en-us/install.php
  23. 107 97
      app/i18n/en-us/sub.php
  24. 30 20
      app/i18n/en-us/user.php
  25. 10 0
      app/i18n/en/admin.php
  26. 10 0
      app/i18n/en/conf.php
  27. 10 0
      app/i18n/en/feedback.php
  28. 10 0
      app/i18n/en/gen.php
  29. 10 0
      app/i18n/en/index.php
  30. 10 0
      app/i18n/en/install.php
  31. 10 0
      app/i18n/en/sub.php
  32. 10 0
      app/i18n/en/user.php
  33. 12 2
      app/i18n/es/admin.php
  34. 18 8
      app/i18n/es/conf.php
  35. 10 0
      app/i18n/es/feedback.php
  36. 50 40
      app/i18n/es/gen.php
  37. 11 1
      app/i18n/es/index.php
  38. 10 0
      app/i18n/es/install.php
  39. 12 2
      app/i18n/es/sub.php
  40. 10 0
      app/i18n/es/user.php
  41. 15 5
      app/i18n/fr/admin.php
  42. 25 15
      app/i18n/fr/conf.php
  43. 10 0
      app/i18n/fr/feedback.php
  44. 52 42
      app/i18n/fr/gen.php
  45. 14 4
      app/i18n/fr/index.php
  46. 12 2
      app/i18n/fr/install.php
  47. 15 5
      app/i18n/fr/sub.php
  48. 10 0
      app/i18n/fr/user.php
  49. 72 62
      app/i18n/he/admin.php
  50. 79 69
      app/i18n/he/conf.php
  51. 54 44
      app/i18n/he/feedback.php
  52. 108 98
      app/i18n/he/gen.php
  53. 15 5
      app/i18n/he/index.php
  54. 32 22
      app/i18n/he/install.php
  55. 63 53
      app/i18n/he/sub.php
  56. 30 20
      app/i18n/he/user.php
  57. 21 11
      app/i18n/it/admin.php
  58. 69 59
      app/i18n/it/conf.php
  59. 29 19
      app/i18n/it/feedback.php
  60. 77 67
      app/i18n/it/gen.php
  61. 18 8
      app/i18n/it/index.php
  62. 20 10
      app/i18n/it/install.php
  63. 63 53
      app/i18n/it/sub.php
  64. 30 20
      app/i18n/it/user.php
  65. 10 0
      app/i18n/ja/admin.php
  66. 18 8
      app/i18n/ja/conf.php
  67. 10 0
      app/i18n/ja/feedback.php
  68. 46 36
      app/i18n/ja/gen.php
  69. 11 1
      app/i18n/ja/index.php
  70. 10 0
      app/i18n/ja/install.php
  71. 11 1
      app/i18n/ja/sub.php
  72. 10 0
      app/i18n/ja/user.php
  73. 10 0
      app/i18n/ko/admin.php
  74. 17 7
      app/i18n/ko/conf.php
  75. 10 0
      app/i18n/ko/feedback.php
  76. 59 49
      app/i18n/ko/gen.php
  77. 11 1
      app/i18n/ko/index.php
  78. 10 0
      app/i18n/ko/install.php
  79. 11 1
      app/i18n/ko/sub.php
  80. 10 0
      app/i18n/ko/user.php
  81. 12 2
      app/i18n/nl/admin.php
  82. 21 11
      app/i18n/nl/conf.php
  83. 10 0
      app/i18n/nl/feedback.php
  84. 56 46
      app/i18n/nl/gen.php
  85. 12 2
      app/i18n/nl/index.php
  86. 12 2
      app/i18n/nl/install.php
  87. 12 2
      app/i18n/nl/sub.php
  88. 10 0
      app/i18n/nl/user.php
  89. 16 6
      app/i18n/oc/admin.php
  90. 21 11
      app/i18n/oc/conf.php
  91. 10 0
      app/i18n/oc/feedback.php
  92. 50 40
      app/i18n/oc/gen.php
  93. 14 4
      app/i18n/oc/index.php
  94. 10 0
      app/i18n/oc/install.php
  95. 14 4
      app/i18n/oc/sub.php
  96. 10 0
      app/i18n/oc/user.php
  97. 55 45
      app/i18n/pl/admin.php
  98. 17 7
      app/i18n/pl/conf.php
  99. 10 0
      app/i18n/pl/feedback.php
  100. 49 39
      app/i18n/pl/gen.php

+ 37 - 27
app/i18n/cz/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => 'Umožnit anonymně číst články výchozího uživatele (%s)',
@@ -66,8 +76,8 @@ return array(
 			'ok' => 'Máte rozšíření JSON.',
 		),
 		'mbstring' => array(
-			'nok' => 'Cannot find the recommended mbstring library for Unicode.',	// TODO - Translation
-			'ok' => 'You have the recommended mbstring library for Unicode.',	// TODO - Translation
+			'nok' => 'Cannot find the recommended mbstring library for Unicode.',	// TODO
+			'ok' => 'You have the recommended mbstring library for Unicode.',	// TODO
 		),
 		'pcre' => array(
 			'nok' => 'Nemáte požadovanou knihovnu pro regulární výrazy (php-pcre).',
@@ -101,23 +111,23 @@ return array(
 		),
 	),
 	'extensions' => array(
-		'author' => 'Author',	// TODO - Translation
-		'community' => 'Available community extensions',	// TODO - Translation
-		'description' => 'Description',	// TODO - Translation
+		'author' => 'Author',	// TODO
+		'community' => 'Available community extensions',	// TODO
+		'description' => 'Description',	// TODO
 		'disabled' => 'Vypnuto',
 		'empty_list' => 'Není naistalováno žádné rozšíření',
 		'enabled' => 'Zapnuto',
-		'latest' => 'Installed',	// TODO - Translation
-		'name' => 'Name',	// TODO - Translation
+		'latest' => 'Installed',	// TODO
+		'name' => 'Name',	// TODO
 		'no_configure_view' => 'Toto rozšíření nemá žádné možnosti nastavení.',
 		'system' => array(
 			'_' => 'Systémová rozšíření',
 			'no_rights' => 'Systémová rozšíření (na ně nemáte oprávnění)',
 		),
 		'title' => 'Rozšíření',
-		'update' => 'Update available',	// TODO - Translation
+		'update' => 'Update available',	// TODO
 		'user' => 'Uživatelská rozšíření',
-		'version' => 'Version',	// TODO - Translation
+		'version' => 'Version',	// TODO
 	),
 	'stats' => array(
 		'_' => 'Statistika',
@@ -147,16 +157,16 @@ return array(
 		'top_feed' => 'Top ten kanálů',
 	),
 	'system' => array(
-		'_' => 'System configuration',	// TODO - Translation
-		'auto-update-url' => 'Auto-update server URL',	// TODO - Translation
+		'_' => 'System configuration',	// TODO
+		'auto-update-url' => 'Auto-update server URL',	// TODO
 		'cookie-duration' => array(
-			'help' => 'in seconds',	// TODO - Translation
-			'number' => 'Duration to keep logged in',	// TODO - Translation
+			'help' => 'in seconds',	// TODO
+			'number' => 'Duration to keep logged in',	// TODO
 		),
-		'force_email_validation' => 'Force email address validation',	// TODO - Translation
-		'instance-name' => 'Instance name',	// TODO - Translation
-		'max-categories' => 'Max number of categories per user',	// TODO - Translation
-		'max-feeds' => 'Max number of feeds per user',	// TODO - Translation
+		'force_email_validation' => 'Force email address validation',	// TODO
+		'instance-name' => 'Instance name',	// TODO
+		'max-categories' => 'Max number of categories per user',	// TODO
+		'max-feeds' => 'Max number of feeds per user',	// TODO
 		'registration' => array(
 			'help' => '0 znamená žádná omezení účtu',
 			'number' => 'Maximální počet účtů',
@@ -172,18 +182,18 @@ return array(
 		'title' => 'Aktualizovat systém',
 	),
 	'user' => array(
-		'admin' => 'Administrator',	// TODO - Translation
-		'article_count' => 'Articles',	// TODO - Translation
-		'back_to_manage' => '← Return to user list',	// TODO - Translation
+		'admin' => 'Administrator',	// TODO
+		'article_count' => 'Articles',	// TODO
+		'back_to_manage' => '← Return to user list',	// TODO
 		'create' => 'Vytvořit nového uživatele',
-		'database_size' => 'Database size',	// TODO - Translation
-		'email' => 'Email address',	// TODO - Translation
-		'enabled' => 'Enabled',	// TODO - Translation
-		'feed_count' => 'Feeds',	// TODO - Translation
-		'is_admin' => 'Is admin',	// TODO - Translation
+		'database_size' => 'Database size',	// TODO
+		'email' => 'Email address',	// TODO
+		'enabled' => 'Enabled',	// TODO
+		'feed_count' => 'Feeds',	// TODO
+		'is_admin' => 'Is admin',	// TODO
 		'language' => 'Jazyk',
-		'last_user_activity' => 'Last user activity',	// TODO - Translation
-		'list' => 'User list',	// TODO - Translation
+		'last_user_activity' => 'Last user activity',	// TODO
+		'list' => 'User list',	// TODO
 		'number' => 'Zatím je vytvořen %d účet',
 		'numbers' => 'Zatím je vytvořeno %d účtů',
 		'password_form' => 'Heslo<br /><small>(pro přihlášení webovým formulářem)</small>',

+ 69 - 59
app/i18n/cz/conf.php

@@ -1,21 +1,31 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'Archivace',
-		'exception' => 'Purge exception',	// TODO - Translation
+		'exception' => 'Purge exception',	// TODO
 		'help' => 'Více možností je dostupných v nastavení jednotlivých kanálů',
-		'keep_favourites' => 'Never delete favourites',	// TODO - Translation
-		'keep_labels' => 'Never delete labels',	// TODO - Translation
-		'keep_max' => 'Maximum number of articles to keep',	// TODO - Translation
+		'keep_favourites' => 'Never delete favourites',	// TODO
+		'keep_labels' => 'Never delete labels',	// TODO
+		'keep_max' => 'Maximum number of articles to keep',	// TODO
 		'keep_min_by_feed' => 'Zachovat tento minimální počet článků v každém kanálu',
-		'keep_period' => 'Maximum age of articles to keep',	// TODO - Translation
-		'keep_unreads' => 'Never delete unread articles',	// TODO - Translation
-		'maintenance' => 'Maintenance',	// TODO - Translation
+		'keep_period' => 'Maximum age of articles to keep',	// TODO
+		'keep_unreads' => 'Never delete unread articles',	// TODO
+		'maintenance' => 'Maintenance',	// TODO
 		'optimize' => 'Optimalizovat databázi',
 		'optimize_help' => 'Občasná údržba zmenší velikost databáze',
-		'policy' => 'Purge policy',	// TODO - Translation
-		'policy_warning' => 'If no purge policy is selected, every article will be kept.',	// TODO - Translation
+		'policy' => 'Purge policy',	// TODO
+		'policy_warning' => 'If no purge policy is selected, every article will be kept.',	// TODO
 		'purge_now' => 'Vyčistit nyní',
 		'title' => 'Archivace',
 		'ttl' => 'Neaktualizovat častěji než',
@@ -24,12 +34,12 @@ return array(
 		'_' => 'Zobrazení',
 		'icon' => array(
 			'bottom_line' => 'Spodní řádek',
-			'display_authors' => 'Authors',	// TODO - Translation
+			'display_authors' => 'Authors',	// TODO
 			'entry' => 'Ikony článků',
 			'publication_date' => 'Datum vydání',
 			'related_tags' => 'Související tagy',
 			'sharing' => 'Sdílení',
-			'summary' => 'Summary',	// TODO - Translation
+			'summary' => 'Summary',	// TODO
 			'top_line' => 'Horní řádek',
 		),
 		'language' => 'Jazyk',
@@ -37,15 +47,15 @@ return array(
 			'seconds' => 'sekund (0 znamená žádný timeout)',
 			'timeout' => 'Timeout HTML5 notifikací',
 		),
-		'show_nav_buttons' => 'Show the navigation buttons',	// TODO - Translation
+		'show_nav_buttons' => 'Show the navigation buttons',	// TODO
 		'theme' => 'Vzhled',
-		'theme_not_available' => 'The “%s” theme is not available anymore. Please choose another theme.',	// TODO - Translation
+		'theme_not_available' => 'The “%s” theme is not available anymore. Please choose another theme.',	// TODO
 		'thumbnail' => array(
-			'label' => 'Thumbnail',	// TODO - Translation
-			'landscape' => 'Landscape',	// TODO - Translation
-			'none' => 'None',	// TODO - Translation
-			'portrait' => 'Portrait',	// TODO - Translation
-			'square' => 'Square',	// TODO - Translation
+			'label' => 'Thumbnail',	// TODO
+			'landscape' => 'Landscape',	// TODO
+			'none' => 'None',	// TODO
+			'portrait' => 'Portrait',	// TODO
+			'square' => 'Square',	// TODO
 		),
 		'title' => 'Zobrazení',
 		'width' => array(
@@ -58,7 +68,7 @@ return array(
 	),
 	'profile' => array(
 		'_' => 'Správa profilu',
-		'api' => 'API management',	// TODO - Translation
+		'api' => 'API management',	// TODO
 		'delete' => array(
 			'_' => 'Smazání účtu',
 			'warn' => 'Váš účet bude smazán spolu se všemi souvisejícími daty',
@@ -74,19 +84,19 @@ return array(
 		'deprecated' => 'Tento dotaz již není platný. Odkazovaná kategorie nebo kanál byly smazány.',
 		'filter' => array(
 			'_' => 'Filtr aplikován:',
-			'categories' => 'Display by category',	// TODO - Translation
-			'feeds' => 'Display by feed',	// TODO - Translation
-			'order' => 'Sort by date',	// TODO - Translation
-			'search' => 'Expression',	// TODO - Translation
-			'state' => 'State',	// TODO - Translation
-			'tags' => 'Display by tag',	// TODO - Translation
-			'type' => 'Type',	// TODO - Translation
+			'categories' => 'Display by category',	// TODO
+			'feeds' => 'Display by feed',	// TODO
+			'order' => 'Sort by date',	// TODO
+			'search' => 'Expression',	// TODO
+			'state' => 'State',	// TODO
+			'tags' => 'Display by tag',	// TODO
+			'type' => 'Type',	// TODO
 		),
 		'get_all' => 'Zobrazit všechny články',
 		'get_category' => 'Zobrazit "%s" kategorii',
 		'get_favorite' => 'Zobrazit oblíbené články',
 		'get_feed' => 'Zobrazit "%s" článkek',
-		'name' => 'Name',	// TODO - Translation
+		'name' => 'Name',	// TODO
 		'no_filter' => 'Zrušit filtr',
 		'number' => 'Dotaz n°%d',
 		'order_asc' => 'Zobrazit nejdříve nejstarší články',
@@ -113,13 +123,13 @@ return array(
 	'reading' => array(
 		'_' => 'Čtení',
 		'after_onread' => 'Po “označit vše jako přečtené”,',
-		'always_show_favorites' => 'Show all articles in favourites by default',	// TODO - Translation
+		'always_show_favorites' => 'Show all articles in favourites by default',	// TODO
 		'articles_per_page' => 'Počet článků na stranu',
 		'auto_load_more' => 'Načítat další články dole na stránce',
 		'auto_remove_article' => 'Po přečtení články schovat',
 		'confirm_enabled' => 'Vyžadovat potvrzení pro akci “označit vše jako přečtené”',
 		'display_articles_unfolded' => 'Ve výchozím stavu zobrazovat články otevřené',
-		'display_categories_unfolded' => 'Categories to unfold',	// TODO - Translation
+		'display_categories_unfolded' => 'Categories to unfold',	// TODO
 		'hide_read_feeds' => 'Schovat kategorie a kanály s nulovým počtem nepřečtených článků (nefunguje s nastavením “Zobrazit všechny články”)',
 		'img_with_lazyload' => 'Použít "lazy load" mód pro načítaní obrázků',
 		'jump_next' => 'skočit na další nepřečtený (kanál nebo kategorii)',
@@ -128,24 +138,24 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'když je otevřen původní web s článkem',
 			'article_viewed' => 'během čtení článku',
-			'keep_max_n_unread' => 'Max number of articles to keep unread',	// TODO - Translation
+			'keep_max_n_unread' => 'Max number of articles to keep unread',	// TODO
 			'scroll' => 'během skrolování',
 			'upon_reception' => 'po načtení článku',
 			'when' => 'Označit článek jako přečtený…',
-			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',	// TODO - Translation
+			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',	// TODO
 		),
 		'show' => array(
 			'_' => 'Počet zobrazených článků',
-			'active_category' => 'Active category',	// TODO - Translation
+			'active_category' => 'Active category',	// TODO
 			'adaptive' => 'Vyberte zobrazení',
 			'all_articles' => 'Zobrazit všechny články',
-			'all_categories' => 'All categories',	// TODO - Translation
-			'no_category' => 'No category',	// TODO - Translation
-			'remember_categories' => 'Remember open categories',	// TODO - Translation
+			'all_categories' => 'All categories',	// TODO
+			'no_category' => 'No category',	// TODO
+			'remember_categories' => 'Remember open categories',	// TODO
 			'unread' => 'Zobrazit jen nepřečtené',
 		),
-		'show_fav_unread_help' => 'Applies also on labels',	// TODO - Translation
-		'sides_close_article' => 'Clicking outside of article text area closes the article',	// TODO - Translation
+		'show_fav_unread_help' => 'Applies also on labels',	// TODO
+		'sides_close_article' => 'Clicking outside of article text area closes the article',	// TODO
 		'sort' => array(
 			'_' => 'Řazení',
 			'newer_first' => 'Nejdříve nejnovější',
@@ -162,21 +172,21 @@ return array(
 	),
 	'sharing' => array(
 		'_' => 'Sdílení',
-		'add' => 'Add a sharing method',	// TODO - Translation
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
-		'email' => 'Email',	// TODO - Translation
-		'facebook' => 'Facebook',
+		'add' => 'Add a sharing method',	// TODO
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
+		'email' => 'Email',	// TODO
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => 'Více informací',
 		'print' => 'Tisk',
-		'raindrop' => 'Raindrop.io',
-		'remove' => 'Remove sharing method',	// TODO - Translation
-		'shaarli' => 'Shaarli',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'remove' => 'Remove sharing method',	// TODO
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => 'Jméno pro zobrazení',
 		'share_url' => 'Jakou URL použít pro sdílení',
 		'title' => 'Sdílení',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => 'Zkratky',
@@ -187,7 +197,7 @@ return array(
 		'collapse_article' => 'Srolovat',
 		'first_article' => 'Skočit na první článek',
 		'focus_search' => 'Hledání',
-		'global_view' => 'Switch to global view',	// TODO - Translation
+		'global_view' => 'Switch to global view',	// TODO
 		'help' => 'Zobrazit documentaci',
 		'javascript' => 'Pro použití zkratek musí být povolen JavaScript',
 		'last_article' => 'Skočit na poslední článek',
@@ -196,24 +206,24 @@ return array(
 		'mark_read' => 'Označit jako přečtené',
 		'navigation' => 'Navigace',
 		'navigation_help' => 'Pomocí přepínače <kbd>⇧ Shift</kbd> fungují navigační zkratky v rámci kanálů.<br/>Pomocí přepínače <kbd>Alt ⎇</kbd> fungují v rámci kategorií.',
-		'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.',	// TODO - Translation
+		'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.',	// TODO
 		'next_article' => 'Skočit na další článek',
-		'next_unread_article' => 'Open the next unread article',	// TODO - Translation
-		'non_standard' => 'Some keys (<kbd>%s</kbd>) may not work as shortcuts.',	// TODO - Translation
-		'normal_view' => 'Switch to normal view',	// TODO - Translation
+		'next_unread_article' => 'Open the next unread article',	// TODO
+		'non_standard' => 'Some keys (<kbd>%s</kbd>) may not work as shortcuts.',	// TODO
+		'normal_view' => 'Switch to normal view',	// TODO
 		'other_action' => 'Ostatní akce',
 		'previous_article' => 'Skočit na předchozí článek',
-		'reading_view' => 'Switch to reading view',	// TODO - Translation
-		'rss_view' => 'Open as RSS feed',	// TODO - Translation
+		'reading_view' => 'Switch to reading view',	// TODO
+		'rss_view' => 'Open as RSS feed',	// TODO
 		'see_on_website' => 'Navštívit původní webovou stránku',
-		'shift_for_all_read' => '+ <kbd>Alt ⎇</kbd> to mark previous articles as read<br />+ <kbd>⇧ Shift</kbd> to mark all articles as read',	// TODO - Translation
-		'skip_next_article' => 'Focus next without opening',	// TODO - Translation
-		'skip_previous_article' => 'Focus previous without opening',	// TODO - Translation
+		'shift_for_all_read' => '+ <kbd>Alt ⎇</kbd> to mark previous articles as read<br />+ <kbd>⇧ Shift</kbd> to mark all articles as read',	// TODO
+		'skip_next_article' => 'Focus next without opening',	// TODO
+		'skip_previous_article' => 'Focus previous without opening',	// TODO
 		'title' => 'Zkratky',
-		'toggle_media' => 'Play/pause media',	// TODO - Translation
+		'toggle_media' => 'Play/pause media',	// TODO
 		'user_filter' => 'Aplikovat uživatelské filtry',
 		'user_filter_help' => 'Je-li nastaven pouze jeden filtr, bude použit. Další filtry jsou dostupné pomocí jejich čísla.',
-		'views' => 'Views',	// TODO - Translation
+		'views' => 'Views',	// TODO
 	),
 	'user' => array(
 		'articles_and_size' => '%s článků (%s)',

+ 29 - 19
app/i18n/cz/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'Nemáte oprávnění přistupovat na tuto stránku',
@@ -10,8 +20,8 @@ return array(
 	),
 	'api' => array(
 		'password' => array(
-			'failed' => 'Your password cannot be modified',	// TODO - Translation
-			'updated' => 'Your password has been modified',	// TODO - Translation
+			'failed' => 'Your password cannot be modified',	// TODO
+			'updated' => 'Your password has been modified',	// TODO
 		),
 	),
 	'auth' => array(
@@ -31,7 +41,7 @@ return array(
 	),
 	'extensions' => array(
 		'already_enabled' => '%s je již zapnut',
-		'cannot_remove' => '%s cannot be removed',	// TODO - Translation
+		'cannot_remove' => '%s cannot be removed',	// TODO
 		'disable' => array(
 			'ko' => '%s nelze vypnout. Pro více detailů <a href="%s">zkontrolujte logy FreshRSS</a>.',
 			'ok' => '%s je nyní vypnut',
@@ -43,7 +53,7 @@ return array(
 		'no_access' => 'Nemáte přístup k %s',
 		'not_enabled' => '%s není ještě zapnut',
 		'not_found' => '%s neexistuje',
-		'removed' => '%s removed',	// TODO - Translation
+		'removed' => '%s removed',	// TODO
 	),
 	'import_export' => array(
 		'export_no_zip_extension' => 'Na serveru není naistalována podpora ZIP. Zkuste prosím exportovat soubory jeden po druhém.',
@@ -60,8 +70,8 @@ return array(
 	'sub' => array(
 		'actualize' => 'Aktualizovat',
 		'articles' => array(
-			'marked_read' => 'The selected articles have been marked as read.',	// TODO - Translation
-			'marked_unread' => 'The articles have been marked as unread.',	// TODO - Translation
+			'marked_read' => 'The selected articles have been marked as read.',	// TODO
+			'marked_unread' => 'The articles have been marked as unread.',	// TODO
 		),
 		'category' => array(
 			'created' => 'Kategorie %s byla vytvořena.',
@@ -81,7 +91,7 @@ return array(
 			'actualizeds' => 'RSS kanály byly aktualizovány',
 			'added' => 'RSS kanál <em>%s</em> byl přidán',
 			'already_subscribed' => 'Již jste přihlášen k odběru <em>%s</em>',
-			'cache_cleared' => '<em>%s</em> cache has been cleared',	// TODO - Translation
+			'cache_cleared' => '<em>%s</em> cache has been cleared',	// TODO
 			'deleted' => 'Kanál byl smazán',
 			'error' => 'Kanál nelze aktualizovat',
 			'internal_problem' => 'RSS kanál nelze přidat. Pro detaily <a href="%s">zkontrolujte logy FreshRSS</a>.',
@@ -90,24 +100,24 @@ return array(
 			'n_entries_deleted' => '%d článků bylo smazáno',
 			'no_refresh' => 'Nelze obnovit žádné kanály…',
 			'not_added' => '<em>%s</em> nemůže být přidán',
-			'not_found' => 'Feed cannot be found',	// TODO - Translation
+			'not_found' => 'Feed cannot be found',	// TODO
 			'over_max' => 'Dosáhl jste maximálního počtu kanálů (%d)',
-			'reloaded' => '<em>%s</em> has been reloaded',	// TODO - Translation
+			'reloaded' => '<em>%s</em> has been reloaded',	// TODO
 			'selector_preview' => array(
-				'http_error' => 'Failed to load website content.',	// TODO - Translation
-				'no_entries' => 'There are no articles in this feed. You need at least one article to create a preview.',	// TODO - Translation
-				'no_feed' => 'Internal error (feed cannot be found).',	// TODO - Translation
-				'no_result' => 'The selector didn\'t match anything. As a fallback the original feed text will be displayed instead.',	// TODO - Translation
-				'selector_empty' => 'The selector is empty. You need to define one to create a preview.',	// TODO - Translation
+				'http_error' => 'Failed to load website content.',	// TODO
+				'no_entries' => 'There are no articles in this feed. You need at least one article to create a preview.',	// TODO
+				'no_feed' => 'Internal error (feed cannot be found).',	// TODO
+				'no_result' => 'The selector didn\'t match anything. As a fallback the original feed text will be displayed instead.',	// TODO
+				'selector_empty' => 'The selector is empty. You need to define one to create a preview.',	// TODO
 			),
 			'updated' => 'Kanál byl aktualizován',
 		),
 		'purge_completed' => 'Vyprázdněno (smazáno %d článků)',
 	),
 	'tag' => array(
-		'created' => 'Tag "%s" has been created.',	// TODO - Translation
-		'name_exists' => 'Tag name already exists.',	// TODO - Translation
-		'renamed' => 'Tag "%s" has been renamed to "%s".',	// TODO - Translation
+		'created' => 'Tag "%s" has been created.',	// TODO
+		'name_exists' => 'Tag name already exists.',	// TODO
+		'renamed' => 'Tag "%s" has been renamed to "%s".',	// TODO
 	),
 	'update' => array(
 		'can_apply' => 'FreshRSS bude nyní upgradováno na <strong>verzi %s</strong>.',
@@ -127,8 +137,8 @@ return array(
 			'error' => 'Uživatele %s nelze smazat',
 		),
 		'updated' => array(
-			'_' => 'User %s has been updated',	// TODO - Translation
-			'error' => 'User %s has not been updated',	// TODO - Translation
+			'_' => 'User %s has been updated',	// TODO
+			'error' => 'User %s has not been updated',	// TODO
 		),
 	),
 );

+ 75 - 65
app/i18n/cz/gen.php

@@ -1,37 +1,47 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'Aktualizovat',
-		'add' => 'Add',	// TODO - Translation
-		'back' => '← Go back',	// TODO - Translation
+		'add' => 'Add',	// TODO
+		'back' => '← Go back',	// TODO
 		'back_to_rss_feeds' => '← Zpět na seznam RSS kanálů',
 		'cancel' => 'Zrušit',
 		'create' => 'Vytvořit',
-		'demote' => 'Demote',	// TODO - Translation
+		'demote' => 'Demote',	// TODO
 		'disable' => 'Zakázat',
 		'empty' => 'Vyprázdnit',
 		'enable' => 'Povolit',
-		'export' => 'Export',	// TODO - Translation
+		'export' => 'Export',	// TODO
 		'filter' => 'Filtrovat',
-		'import' => 'Import',	// TODO - Translation
-		'load_default_shortcuts' => 'Load default shortcuts',	// TODO - Translation
+		'import' => 'Import',	// TODO
+		'load_default_shortcuts' => 'Load default shortcuts',	// TODO
 		'manage' => 'Spravovat',
 		'mark_read' => 'Označit jako přečtené',
-		'promote' => 'Promote',	// TODO - Translation
-		'purge' => 'Purge',	// TODO - Translation
+		'promote' => 'Promote',	// TODO
+		'purge' => 'Purge',	// TODO
 		'remove' => 'Odstranit',
-		'rename' => 'Rename',	// TODO - Translation
+		'rename' => 'Rename',	// TODO
 		'see_website' => 'Navštívit WWW stránku',
 		'submit' => 'Odeslat',
 		'truncate' => 'Smazat všechny články',
-		'update' => 'Update',	// TODO - Translation
+		'update' => 'Update',	// TODO
 	),
 	'auth' => array(
-		'accept_tos' => 'I accept the <a href="%s">Terms of Service</a>.',	// TODO - Translation
+		'accept_tos' => 'I accept the <a href="%s">Terms of Service</a>.',	// TODO
 		'email' => 'Email',
 		'keep_logged_in' => 'Zapamatovat přihlášení <small>(%s dny)</small>',
-		'login' => 'Login',	// TODO - Translation
+		'login' => 'Login',	// TODO
 		'logout' => 'Odhlášení',
 		'password' => array(
 			'_' => 'Heslo',
@@ -69,8 +79,8 @@ return array(
 		'december' => 'Pro',
 		'feb' => 'úno',
 		'february' => 'Úno',
-		'format_date' => 'j\\. %s Y',
-		'format_date_hour' => 'j\\. %s Y \\v H\\:i',
+		'format_date' => 'j\\. %s Y',	// IGNORE
+		'format_date_hour' => 'j\\. %s Y \\v H\\:i',	// IGNORE
 		'fri' => 'Pá',
 		'jan' => 'led',
 		'january' => 'Led',
@@ -78,10 +88,10 @@ return array(
 		'july' => 'Čvn',
 		'jun' => 'čer',
 		'june' => 'Čer',
-		'last_2_year' => 'Last two years',	// TODO - Translation
+		'last_2_year' => 'Last two years',	// TODO
 		'last_3_month' => 'Minulé tři měsíce',
-		'last_3_year' => 'Last three years',	// TODO - Translation
-		'last_5_year' => 'Last five years',	// TODO - Translation
+		'last_3_year' => 'Last three years',	// TODO
+		'last_5_year' => 'Last five years',	// TODO
 		'last_6_month' => 'Minulých šest měsíců',
 		'last_month' => 'Minulý měsíc',
 		'last_week' => 'Minulý týden',
@@ -106,9 +116,9 @@ return array(
 		'wed' => 'St',
 		'yesterday' => 'Včera',
 	),
-	'dir' => 'ltr',
+	'dir' => 'ltr',	// IGNORE
 	'freshrss' => array(
-		'_' => 'FreshRSS',	// TODO - Translation
+		'_' => 'FreshRSS',	// TODO
 		'about' => 'O FreshRSS',
 	),
 	'js' => array(
@@ -124,28 +134,28 @@ return array(
 		'should_be_activated' => 'JavaScript musí být povolen',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'O aplikaci',
-		'account' => 'Account',	// TODO - Translation
+		'account' => 'Account',	// TODO
 		'admin' => 'Administrace',
 		'archiving' => 'Archivace',
 		'authentication' => 'Přihlášení',
@@ -160,7 +170,7 @@ return array(
 		'sharing' => 'Sdílení',
 		'shortcuts' => 'Zkratky',
 		'stats' => 'Statistika',
-		'system' => 'System configuration',	// TODO - Translation
+		'system' => 'System configuration',	// TODO
 		'update' => 'Aktualizace',
 		'user_management' => 'Správa uživatelů',
 		'user_profile' => 'Profil',
@@ -175,33 +185,33 @@ return array(
 		'previous' => 'Předchozí',
 	),
 	'period' => array(
-		'days' => 'days',	// TODO - Translation
-		'hours' => 'hours',	// TODO - Translation
-		'months' => 'months',	// TODO - Translation
-		'weeks' => 'weeks',	// TODO - Translation
-		'years' => 'years',	// TODO - Translation
+		'days' => 'days',	// TODO
+		'hours' => 'hours',	// TODO
+		'months' => 'months',	// TODO
+		'weeks' => 'weeks',	// TODO
+		'years' => 'years',	// TODO
 	),
 	'share' => array(
-		'Known' => 'Known based sites',	// TODO - Translation
-		'blogotext' => 'Blogotext',
-		'clipboard' => 'Clipboard',	// TODO - Translation
-		'diaspora' => 'Diaspora*',
-		'email' => 'Email',	// TODO - Translation
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
+		'Known' => 'Known based sites',	// TODO
+		'blogotext' => 'Blogotext',	// IGNORE
+		'clipboard' => 'Clipboard',	// TODO
+		'diaspora' => 'Diaspora*',	// IGNORE
+		'email' => 'Email',	// TODO
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
 		'print' => 'Tisk',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => 'Upozornění!',
@@ -211,8 +221,8 @@ return array(
 		'damn' => 'Sakra!',
 		'default_category' => 'Nezařazeno',
 		'no' => 'Ne',
-		'not_applicable' => 'Not available',	// TODO - Translation
-		'ok' => 'Okay!',	// TODO - Translation
+		'not_applicable' => 'Not available',	// TODO
+		'ok' => 'Okay!',	// TODO
 		'or' => 'nebo',
 		'yes' => 'Ano',
 	),

+ 15 - 5
app/i18n/cz/index.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => 'O FreshRSS',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
 		'bugs_reports' => 'Hlášení chyb',
 		'credits' => 'Poděkování',
 		'credits_content' => 'Některé designové prvky pocházejí z <a href="http://twitter.github.io/bootstrap/">Bootstrap</a>, FreshRSS ale tuto platformu nevyužívá. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Ikony</a> pocházejí z <a href="https://www.gnome.org/">GNOME projektu</a>. Font <em>Open Sans</em> vytvořil <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS je založen na PHP framework <a href="https://github.com/marienfressinaud/MINZ">Minz</a>.',
@@ -32,14 +42,14 @@ return array(
 		'about' => 'O FreshRSS',
 		'before_one_day' => 'Den nazpět',
 		'before_one_week' => 'Před týdnem',
-		'bookmark_query' => 'Bookmark current query',	// TODO - Translation
+		'bookmark_query' => 'Bookmark current query',	// TODO
 		'favorites' => 'Oblíbené (%s)',
 		'global_view' => 'Přehled',
 		'main_stream' => 'Všechny kanály',
 		'mark_all_read' => 'Označit vše jako přečtené',
 		'mark_cat_read' => 'Označit kategorii jako přečtenou',
 		'mark_feed_read' => 'Označit kanál jako přečtený',
-		'mark_selection_unread' => 'Mark selection as unread',	// TODO - Translation
+		'mark_selection_unread' => 'Mark selection as unread',	// TODO
 		'newer_first' => 'Nové nejdříve',
 		'non-starred' => 'Zobrazit vše vyjma oblíbených',
 		'normal_view' => 'Normální',
@@ -52,7 +62,7 @@ return array(
 		'starred' => 'Zobrazit oblíbené',
 		'stats' => 'Statistika',
 		'subscription' => 'Správa subskripcí',
-		'tags' => 'My labels',	// TODO - Translation
+		'tags' => 'My labels',	// TODO
 		'unread' => 'Zobrazovat nepřečtené',
 	),
 	'share' => 'Sdílet',
@@ -60,6 +70,6 @@ return array(
 		'related' => 'Související tagy',
 	),
 	'tos' => array(
-		'title' => 'Terms of Service',	// TODO - Translation
+		'title' => 'Terms of Service',	// TODO
 	),
 );

+ 17 - 7
app/i18n/cz/install.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => 'Dokončit instalaci',
@@ -65,8 +75,8 @@ return array(
 			'ok' => 'Máte doporučenou knihovnu pro parsování JSON.',
 		),
 		'mbstring' => array(
-			'nok' => 'Cannot find the recommended library mbstring for Unicode.',	// TODO - Translation
-			'ok' => 'You have the recommended library mbstring for Unicode.',	// TODO - Translation
+			'nok' => 'Cannot find the recommended library mbstring for Unicode.',	// TODO
+			'ok' => 'You have the recommended library mbstring for Unicode.',	// TODO
 		),
 		'pcre' => array(
 			'nok' => 'Nemáte požadovanou knihovnu pro regulární výrazy (php-pcre).',
@@ -80,12 +90,12 @@ return array(
 			'nok' => 'Vaše verze PHP je %s, ale FreshRSS vyžaduje alespoň verzi %s.',
 			'ok' => 'Vaše verze PHP je %s a je kompatibilní s FreshRSS.',
 		),
-		'reload' => 'Check again',	// TODO - Translation
+		'reload' => 'Check again',	// TODO
 		'tmp' => array(
 			'nok' => 'Zkontrolujte oprávnění adresáře <em>%s</em>. HTTP server musí mít do tohoto adresáře práva zápisu.',
-			'ok' => 'Permissions on the temp directory are good.',	// TODO - Translation
+			'ok' => 'Permissions on the temp directory are good.',	// TODO
 		),
-		'unknown_process_username' => 'unknown',	// TODO - Translation
+		'unknown_process_username' => 'unknown',	// TODO
 		'users' => array(
 			'nok' => 'Zkontrolujte oprávnění adresáře <em>%s</em>. HTTP server musí mít do tohoto adresáře práva zápisu.',
 			'ok' => 'Oprávnění adresáře users jsou v pořádku.',
@@ -111,10 +121,10 @@ return array(
 		'choose' => 'Vyberte jazyk FreshRSS',
 		'defined' => 'Jazyk byl nastaven.',
 	),
-	'missing_applied_migrations' => 'Something went wrong; you should create an empty file <em>%s</em> manually.',	// TODO - Translation
+	'missing_applied_migrations' => 'Something went wrong; you should create an empty file <em>%s</em> manually.',	// TODO
 	'ok' => 'Instalace byla úspěšná.',
 	'session' => array(
-		'nok' => 'The web server seems to be incorrectly configured for cookies required for PHP sessions!',	// TODO - Translation
+		'nok' => 'The web server seems to be incorrectly configured for cookies required for PHP sessions!',	// TODO
 	),
 	'step' => 'krok %d',
 	'steps' => 'Kroky',

+ 64 - 54
app/i18n/cz/sub.php

@@ -1,14 +1,24 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
-		'documentation' => 'Copy the following URL to use it within an external tool.',	// TODO - Translation
-		'title' => 'API',	// TODO - Translation
+		'documentation' => 'Copy the following URL to use it within an external tool.',	// TODO
+		'title' => 'API',	// TODO
 	),
 	'bookmarklet' => array(
-		'documentation' => 'Drag this button to your bookmarks toolbar or right-click it and choose "Bookmark This Link". Then click the "Subscribe" button in any page you want to subscribe to.',	// TODO - Translation
-		'label' => 'Subscribe',	// TODO - Translation
-		'title' => 'Bookmarklet',	// TODO - Translation
+		'documentation' => 'Drag this button to your bookmarks toolbar or right-click it and choose "Bookmark This Link". Then click the "Subscribe" button in any page you want to subscribe to.',	// TODO
+		'label' => 'Subscribe',	// TODO
+		'title' => 'Bookmarklet',	// TODO
 	),
 	'category' => array(
 		'_' => 'Kategorie',
@@ -16,8 +26,8 @@ return array(
 		'archiving' => 'Archivace',
 		'empty' => 'Vyprázdit kategorii',
 		'information' => 'Informace',
-		'position' => 'Display position',	// TODO - Translation
-		'position_help' => 'To control category sort order',	// TODO - Translation
+		'position' => 'Display position',	// TODO
+		'position_help' => 'To control category sort order',	// TODO
 		'title' => 'Název',
 	),
 	'feed' => array(
@@ -31,108 +41,108 @@ return array(
 			'password' => 'Heslo',
 			'username' => 'Přihlašovací jméno',
 		),
-		'clear_cache' => 'Always clear cache',	// TODO - Translation
+		'clear_cache' => 'Always clear cache',	// TODO
 		'content_action' => array(
-			'_' => 'Content action when fetching the article content',	// TODO - Translation
-			'append' => 'Add after existing content',	// TODO - Translation
-			'prepend' => 'Add before existing content',	// TODO - Translation
-			'replace' => 'Replace existing content',	// TODO - Translation
+			'_' => 'Content action when fetching the article content',	// TODO
+			'append' => 'Add after existing content',	// TODO
+			'prepend' => 'Add before existing content',	// TODO
+			'replace' => 'Replace existing content',	// TODO
 		),
-		'css_cookie' => 'Use Cookies when fetching the article content',	// TODO - Translation
-		'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',	// TODO - Translation
+		'css_cookie' => 'Use Cookies when fetching the article content',	// TODO
+		'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',	// TODO
 		'css_help' => 'Stáhne zkrácenou verzi RSS kanálů (pozor, náročnější na čas!)',
 		'css_path' => 'Původní CSS soubor článku z webových stránek',
 		'description' => 'Popis',
 		'empty' => 'Kanál je prázdný. Ověřte prosím zda je ještě autorem udržován.',
 		'error' => 'Vyskytl se problém s kanálem. Ověřte že je vždy dostupný, prosím, a poté jej aktualizujte.',
 		'filteractions' => array(
-			'_' => 'Filter actions',	// TODO - Translation
-			'help' => 'Write one search filter per line.',	// TODO - Translation
+			'_' => 'Filter actions',	// TODO
+			'help' => 'Write one search filter per line.',	// TODO
 		),
 		'information' => 'Informace',
 		'keep_min' => 'Zachovat tento minimální počet článků',
 		'maintenance' => array(
-			'clear_cache' => 'Clear cache',	// TODO - Translation
-			'clear_cache_help' => 'Clear the cache for this feed.',	// TODO - Translation
-			'reload_articles' => 'Reload articles',	// TODO - Translation
-			'reload_articles_help' => 'Reload articles and fetch complete content if a selector is defined.',	// TODO - Translation
-			'title' => 'Maintenance',	// TODO - Translation
+			'clear_cache' => 'Clear cache',	// TODO
+			'clear_cache_help' => 'Clear the cache for this feed.',	// TODO
+			'reload_articles' => 'Reload articles',	// TODO
+			'reload_articles_help' => 'Reload articles and fetch complete content if a selector is defined.',	// TODO
+			'title' => 'Maintenance',	// TODO
 		),
 		'moved_category_deleted' => 'Po smazání kategorie budou v ní obsažené kanály automaticky přesunuty do <em>%s</em>.',
-		'mute' => 'mute',	// TODO - Translation
+		'mute' => 'mute',	// TODO
 		'no_selected' => 'Nejsou označeny žádné kanály.',
 		'number_entries' => '%d článků',
 		'priority' => array(
-			'_' => 'Visibility',	// TODO - Translation
-			'archived' => 'Do not show (archived)',	// TODO - Translation
+			'_' => 'Visibility',	// TODO
+			'archived' => 'Do not show (archived)',	// TODO
 			'main_stream' => 'Zobrazit ve “Všechny kanály”',
-			'normal' => 'Show in its category',	// TODO - Translation
+			'normal' => 'Show in its category',	// TODO
 		),
-		'proxy' => 'Set a proxy for fetching this feed',	// TODO - Translation
-		'proxy_help' => 'Select a protocol (e.g: SOCKS5) and enter the proxy address (e.g: <kbd>127.0.0.1:1080</kbd>)',	// TODO - Translation
+		'proxy' => 'Set a proxy for fetching this feed',	// TODO
+		'proxy_help' => 'Select a protocol (e.g: SOCKS5) and enter the proxy address (e.g: <kbd>127.0.0.1:1080</kbd>)',	// TODO
 		'selector_preview' => array(
-			'show_raw' => 'Show source code',	// TODO - Translation
-			'show_rendered' => 'Show content',	// TODO - Translation
+			'show_raw' => 'Show source code',	// TODO
+			'show_rendered' => 'Show content',	// TODO
 		),
 		'show' => array(
-			'all' => 'Show all feeds',	// TODO - Translation
-			'error' => 'Show only feeds with errors',	// TODO - Translation
+			'all' => 'Show all feeds',	// TODO
+			'error' => 'Show only feeds with errors',	// TODO
 		),
 		'showing' => array(
-			'error' => 'Showing only feeds with errors',	// TODO - Translation
+			'error' => 'Showing only feeds with errors',	// TODO
 		),
-		'ssl_verify' => 'Verify SSL security',	// TODO - Translation
+		'ssl_verify' => 'Verify SSL security',	// TODO
 		'stats' => 'Statistika',
 		'think_to_add' => 'Můžete přidat kanály.',
-		'timeout' => 'Timeout in seconds',	// TODO - Translation
+		'timeout' => 'Timeout in seconds',	// TODO
 		'title' => 'Název',
 		'title_add' => 'Přidat RSS kanál',
 		'ttl' => 'Neobnovovat častěji než',
 		'url' => 'URL kanálu',
-		'useragent' => 'Set the user agent for fetching this feed',	// TODO - Translation
-		'useragent_help' => 'Example: <kbd>Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0)</kbd>',	// TODO - Translation
+		'useragent' => 'Set the user agent for fetching this feed',	// TODO
+		'useragent_help' => 'Example: <kbd>Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0)</kbd>',	// TODO
 		'validator' => 'Zkontrolovat platnost kanálu',
 		'website' => 'URL webové stránky',
 		'websub' => 'Okamžité oznámení s WebSub',
 	),
 	'import_export' => array(
-		'export' => 'Export',	// TODO - Translation
-		'export_labelled' => 'Export your labelled articles',	// TODO - Translation
+		'export' => 'Export',	// TODO
+		'export_labelled' => 'Export your labelled articles',	// TODO
 		'export_opml' => 'Exportovat seznam kanálů (OPML)',
 		'export_starred' => 'Exportovat oblíbené',
 		'feed_list' => 'Seznam %s článků',
 		'file_to_import' => 'Soubor k importu<br />(OPML, JSON nebo ZIP)',
 		'file_to_import_no_zip' => 'Soubor k importu<br />(OPML nebo JSON)',
-		'import' => 'Import',	// TODO - Translation
+		'import' => 'Import',	// TODO
 		'starred_list' => 'Seznam oblíbených článků',
-		'title' => 'Import / export',	// TODO - Translation
+		'title' => 'Import / export',	// TODO
 	),
 	'menu' => array(
-		'add' => 'Add a feed or category',	// TODO - Translation
-		'import_export' => 'Import / export',	// TODO - Translation
-		'label_management' => 'Label management',	// TODO - Translation
+		'add' => 'Add a feed or category',	// TODO
+		'import_export' => 'Import / export',	// TODO
+		'label_management' => 'Label management',	// TODO
 		'stats' => array(
 			'idle' => 'Neaktivní kanály',
 			'main' => 'Přehled',
 			'repartition' => 'Rozdělení článků',
 		),
 		'subscription_management' => 'Správa subskripcí',
-		'subscription_tools' => 'Subscription tools',	// TODO - Translation
+		'subscription_tools' => 'Subscription tools',	// TODO
 	),
 	'tag' => array(
-		'name' => 'Name',	// TODO - Translation
-		'new_name' => 'New name',	// TODO - Translation
-		'old_name' => 'Old name',	// TODO - Translation
+		'name' => 'Name',	// TODO
+		'new_name' => 'New name',	// TODO
+		'old_name' => 'Old name',	// TODO
 	),
 	'title' => array(
 		'_' => 'Správa subskripcí',
-		'add' => 'Add a feed or category',	// TODO - Translation
-		'add_category' => 'Add a category',	// TODO - Translation
-		'add_feed' => 'Add a feed',	// TODO - Translation
-		'add_label' => 'Add a label',	// TODO - Translation
-		'delete_label' => 'Delete a label',	// TODO - Translation
+		'add' => 'Add a feed or category',	// TODO
+		'add_category' => 'Add a category',	// TODO
+		'add_feed' => 'Add a feed',	// TODO
+		'add_label' => 'Add a label',	// TODO
+		'delete_label' => 'Delete a label',	// TODO
 		'feed_management' => 'Správa RSS kanálů',
-		'rename_label' => 'Rename a label',	// TODO - Translation
-		'subscription_tools' => 'Subscription tools',	// TODO - Translation
+		'rename_label' => 'Rename a label',	// TODO
+		'subscription_tools' => 'Subscription tools',	// TODO
 	),
 );

+ 30 - 20
app/i18n/cz/user.php

@@ -1,44 +1,54 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(
-			'invalid' => 'This email address is invalid.',	// TODO - Translation
-			'required' => 'An email address is required.',	// TODO - Translation
+			'invalid' => 'This email address is invalid.',	// TODO
+			'required' => 'An email address is required.',	// TODO
 		),
 		'validation' => array(
-			'change_email' => 'You can change your email address <a href="%s">on the profile page</a>.',	// TODO - Translation
-			'email_sent_to' => 'We sent you an email at <strong>%s</strong>. Please follow its instructions to validate your address.',	// TODO - Translation
+			'change_email' => 'You can change your email address <a href="%s">on the profile page</a>.',	// TODO
+			'email_sent_to' => 'We sent you an email at <strong>%s</strong>. Please follow its instructions to validate your address.',	// TODO
 			'feedback' => array(
-				'email_failed' => 'We couldn’t send you an email because of a server configuration error.',	// TODO - Translation
-				'email_sent' => 'An email has been sent to your address.',	// TODO - Translation
-				'error' => 'Email address validation failed.',	// TODO - Translation
-				'ok' => 'This email address has been validated.',	// TODO - Translation
-				'unnecessary' => 'This email address was already validated.',	// TODO - Translation
-				'wrong_token' => 'This email address failed to be validated due to a wrong token.',	// TODO - Translation
+				'email_failed' => 'We couldn’t send you an email because of a server configuration error.',	// TODO
+				'email_sent' => 'An email has been sent to your address.',	// TODO
+				'error' => 'Email address validation failed.',	// TODO
+				'ok' => 'This email address has been validated.',	// TODO
+				'unnecessary' => 'This email address was already validated.',	// TODO
+				'wrong_token' => 'This email address failed to be validated due to a wrong token.',	// TODO
 			),
-			'need_to' => 'You need to validate your email address before being able to use %s.',	// TODO - Translation
-			'resend_email' => 'Resend the email',	// TODO - Translation
-			'title' => 'Email address validation',	// TODO - Translation
+			'need_to' => 'You need to validate your email address before being able to use %s.',	// TODO
+			'resend_email' => 'Resend the email',	// TODO
+			'title' => 'Email address validation',	// TODO
 		),
 	),
 	'mailer' => array(
 		'email_need_validation' => array(
-			'body' => 'You’ve just registered on %s, but you still need to validate your email address. For that, just follow the link:',	// TODO - Translation
-			'title' => 'You need to validate your account',	// TODO - Translation
-			'welcome' => 'Welcome %s,',	// TODO - Translation
+			'body' => 'You’ve just registered on %s, but you still need to validate your email address. For that, just follow the link:',	// TODO
+			'title' => 'You need to validate your account',	// TODO
+			'welcome' => 'Welcome %s,',	// TODO
 		),
 	),
 	'password' => array(
-		'invalid' => 'The password is invalid.',	// TODO - Translation
+		'invalid' => 'The password is invalid.',	// TODO
 	),
 	'tos' => array(
 		'feedback' => array(
-			'invalid' => 'You must accept the Terms of Service to be able to register.',	// TODO - Translation
+			'invalid' => 'You must accept the Terms of Service to be able to register.',	// TODO
 		),
 	),
 	'username' => array(
-		'invalid' => 'This username is invalid.',	// TODO - Translation
-		'taken' => 'This username, %s, is taken.',	// TODO - Translation
+		'invalid' => 'This username is invalid.',	// TODO
+		'taken' => 'This username, %s, is taken.',	// TODO
 	),
 );

+ 15 - 5
app/i18n/de/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => 'Anonymes Lesen der Artikel des Standardbenutzers (%s) erlauben',
@@ -108,7 +118,7 @@ return array(
 		'empty_list' => 'Es gibt keine installierte Erweiterung.',
 		'enabled' => 'Aktiviert',
 		'latest' => 'Installiert',
-		'name' => 'Name',
+		'name' => 'Name',	// IGNORE
 		'no_configure_view' => 'Diese Erweiterung kann nicht konfiguriert werden.',
 		'system' => array(
 			'_' => 'System-Erweiterungen',
@@ -117,7 +127,7 @@ return array(
 		'title' => 'Erweiterungen',
 		'update' => 'Update verfügbar',
 		'user' => 'Benutzer-Erweiterungen',
-		'version' => 'Version',
+		'version' => 'Version',	// IGNORE
 	),
 	'stats' => array(
 		'_' => 'Statistiken',
@@ -130,7 +140,7 @@ return array(
 		'entry_per_hour' => 'Pro Stunde (Durchschnitt: %.2f Nachrichten)',
 		'entry_per_month' => 'Pro Monat (Durchschnitt: %.2f Nachrichten)',
 		'entry_repartition' => 'Einträge-Verteilung',
-		'feed' => 'Feed',
+		'feed' => 'Feed',	// IGNORE
 		'feed_per_category' => 'Feeds pro Kategorie',
 		'idle' => 'Inaktive Feeds',
 		'main' => 'Haupt-Statistiken',
@@ -172,14 +182,14 @@ return array(
 		'title' => 'System aktualisieren',
 	),
 	'user' => array(
-		'admin' => 'Administrator',
+		'admin' => 'Administrator',	// IGNORE
 		'article_count' => 'Artikel',
 		'back_to_manage' => '← Zurück zur Benutzerliste',
 		'create' => 'Neuen Benutzer erstellen',
 		'database_size' => 'Datenbankgröße',
 		'email' => 'E-Mail-Adresse',
 		'enabled' => 'Aktiviert',
-		'feed_count' => 'Feeds',
+		'feed_count' => 'Feeds',	// IGNORE
 		'is_admin' => 'Ist Administrator',
 		'language' => 'Sprache',
 		'last_user_activity' => 'Letzte Benutzeraktivität',

+ 19 - 9
app/i18n/de/conf.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'Archivierung',
@@ -86,7 +96,7 @@ return array(
 		'get_category' => 'Kategorie "%s" anzeigen',
 		'get_favorite' => 'Lieblingsartikel anzeigen',
 		'get_feed' => 'Feed "%s" anzeigen',
-		'name' => 'Name',
+		'name' => 'Name',	// IGNORE
 		'no_filter' => 'Kein Filter',
 		'number' => 'Abfrage Nr. %d',
 		'order_asc' => 'Älteste Artikel zuerst anzeigen',
@@ -163,20 +173,20 @@ return array(
 	'sharing' => array(
 		'_' => 'Teilen',
 		'add' => 'Füge eine Teilen-Dienst hinzu',
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'E-Mail',
-		'facebook' => 'Facebook',
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => 'Weitere Informationen',
 		'print' => 'Drucken',
-		'raindrop' => 'Raindrop.io',
+		'raindrop' => 'Raindrop.io',	// IGNORE
 		'remove' => 'Entferne Teilen-Dienst',
-		'shaarli' => 'Shaarli',
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => 'Anzuzeigender Teilen-Name',
 		'share_url' => 'Zu verwendende Teilen-URL',
 		'title' => 'Teilen',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => 'Tastenkombination',
@@ -194,7 +204,7 @@ return array(
 		'load_more' => 'Weitere Artikel laden',
 		'mark_favorite' => 'Als Favorit auswählen/entfernen',
 		'mark_read' => 'Als (un-)gelesen markieren',
-		'navigation' => 'Navigation',
+		'navigation' => 'Navigation',	// IGNORE
 		'navigation_help' => 'Mit der <kbd>⇧ Umschalttaste</kbd> finden die Tastenkombination auf Feeds Anwendung.<br/>Mit der <kbd>Alt ⎇</kbd>-Taste finden die Tastenkombination auf Kategorien Anwendung.',
 		'navigation_no_mod_help' => 'Die folgenden Navigationsverknüpfungen unterstützen keine Modifikatoren.',
 		'next_article' => 'Zum nächsten Artikel springen',

+ 10 - 0
app/i18n/de/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'Sie haben nicht die Berechtigung, diese Seite aufzurufen',

+ 56 - 46
app/i18n/de/gen.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'Feeds aktualisieren',
@@ -48,8 +58,8 @@ return array(
 		),
 	),
 	'date' => array(
-		'Apr' => '\\A\\p\\r\\i\\l',
-		'Aug' => '\\A\\u\\g\\u\\s\\t',
+		'Apr' => '\\A\\p\\r\\i\\l',	// IGNORE
+		'Aug' => '\\A\\u\\g\\u\\s\\t',	// IGNORE
 		'Dec' => '\\D\\e\\z\\e\\m\\b\\e\\r',
 		'Feb' => '\\F\\e\\b\\r\\u\\a\\r',
 		'Jan' => '\\J\\a\\n\\u\\a\\r',
@@ -57,13 +67,13 @@ return array(
 		'Jun' => '\\J\\u\\n\\i',
 		'Mar' => '\\M\\ä\\r\\z',
 		'May' => '\\M\\a\\i',
-		'Nov' => '\\N\\o\\v\\e\\m\\b\\e\\r',
+		'Nov' => '\\N\\o\\v\\e\\m\\b\\e\\r',	// IGNORE
 		'Oct' => '\\O\\k\\t\\o\\b\\e\\r',
-		'Sep' => '\\S\\e\\p\\t\\e\\m\\b\\e\\r',
+		'Sep' => '\\S\\e\\p\\t\\e\\m\\b\\e\\r',	// IGNORE
 		'apr' => 'Apr',
-		'april' => 'April',
+		'april' => 'April',	// IGNORE
 		'aug' => 'Aug',
-		'august' => 'August',
+		'august' => 'August',	// IGNORE
 		'before_yesterday' => 'Ältere Beiträge',
 		'dec' => 'Dez',
 		'december' => 'Dezember',
@@ -93,12 +103,12 @@ return array(
 		'mon' => 'Mo',
 		'month' => 'Monat(en)',
 		'nov' => 'Nov',
-		'november' => 'November',
+		'november' => 'November',	// IGNORE
 		'oct' => 'Okt',
 		'october' => 'Oktober',
 		'sat' => 'Sa',
 		'sep' => 'Sep',
-		'september' => 'September',
+		'september' => 'September',	// IGNORE
 		'sun' => 'So',
 		'thu' => 'Do',
 		'today' => 'Heute',
@@ -106,9 +116,9 @@ return array(
 		'wed' => 'Mi',
 		'yesterday' => 'Gestern',
 	),
-	'dir' => 'ltr',
+	'dir' => 'ltr',	// IGNORE
 	'freshrss' => array(
-		'_' => 'FreshRSS',
+		'_' => 'FreshRSS',	// IGNORE
 		'about' => 'Über FreshRSS',
 	),
 	'js' => array(
@@ -124,29 +134,29 @@ return array(
 		'should_be_activated' => 'JavaScript muss aktiviert sein',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'Über',
-		'account' => 'Account',
-		'admin' => 'Administration',
+		'account' => 'Account',	// IGNORE
+		'admin' => 'Administration',	// IGNORE
 		'archiving' => 'Archivierung',
 		'authentication' => 'Authentifizierung',
 		'check_install' => 'Installationsüberprüfung',
@@ -183,25 +193,25 @@ return array(
 	),
 	'share' => array(
 		'Known' => 'Known-Seite (https://withknown.com)',
-		'blogotext' => 'Blogotext',
+		'blogotext' => 'Blogotext',	// IGNORE
 		'clipboard' => 'Zwischenablage',
-		'diaspora' => 'Diaspora*',
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'E-Mail',
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
 		'print' => 'Drucken',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => 'Achtung!',

+ 12 - 2
app/i18n/de/index.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => 'Über',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
 		'bugs_reports' => 'Fehlerberichte',
 		'credits' => 'Mitwirkende',
 		'credits_content' => 'Einige Designelemente stammen von <a href="http://twitter.github.io/bootstrap/">Bootstrap</a>, obwohl FreshRSS dieses Framework nicht nutzt. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Icons</a> stammen vom <a href="https://www.gnome.org/">GNOME project</a>. <em>Open Sans</em> Font wurde von <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a> erstellt. FreshRSS basiert auf <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, einem PHP-Framework.',
@@ -12,7 +22,7 @@ return array(
 		'license' => 'Lizenz',
 		'project_website' => 'Projekt-Website',
 		'title' => 'Über',
-		'version' => 'Version',
+		'version' => 'Version',	// IGNORE
 	),
 	'feed' => array(
 		'add' => 'Sie können Feeds hinzufügen.',

+ 12 - 2
app/i18n/de/install.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => 'Installation fertigstellen',
@@ -23,7 +33,7 @@ return array(
 			'ko' => 'Überprüfen Sie Ihre Datenbank-Information.',
 			'ok' => 'Datenbank-Konfiguration ist gespeichert worden.',
 		),
-		'host' => 'Host',
+		'host' => 'Host',	// IGNORE
 		'password' => 'Datenbank-Password',
 		'prefix' => 'Tabellen-Präfix',
 		'type' => 'Datenbank-Typ',
@@ -119,5 +129,5 @@ return array(
 	'step' => 'Schritt %d',
 	'steps' => 'Schritte',
 	'this_is_the_end' => 'Das ist das Ende',
-	'title' => 'Installation · FreshRSS',
+	'title' => 'Installation · FreshRSS',	// IGNORE
 );

+ 15 - 5
app/i18n/de/sub.php

@@ -1,21 +1,31 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
 		'documentation' => 'Kopieren Sie die folgende URL, um sie in einem externen Tool zu verwenden.',
-		'title' => 'API',
+		'title' => 'API',	// IGNORE
 	),
 	'bookmarklet' => array(
 		'documentation' => 'Ziehen Sie diese Schaltfläche auf Ihre Lesezeichen-Symbolleiste oder klicken Sie mit der rechten Maustaste darauf und wählen Sie "Als Lesezeichen hinzufügen". Klicken Sie dann auf einer beliebigen Seite, die Sie abonnieren möchten, auf die Schaltfläche "Abonnieren".',
 		'label' => 'Abonnieren',
-		'title' => 'Bookmarklet',
+		'title' => 'Bookmarklet',	// IGNORE
 	),
 	'category' => array(
 		'_' => 'Kategorie',
 		'add' => 'Kategorie hinzufügen',
 		'archiving' => 'Archivierung',
 		'empty' => 'Leere Kategorie',
-		'information' => 'Information',
+		'information' => 'Information',	// IGNORE
 		'position' => 'Reihenfolge',
 		'position_help' => 'Steuert die Kategoriesortierung',
 		'title' => 'Titel',
@@ -49,7 +59,7 @@ return array(
 			'_' => 'Filteraktionen',
 			'help' => 'Ein Suchfilter pro Zeile',
 		),
-		'information' => 'Information',
+		'information' => 'Information',	// IGNORE
 		'keep_min' => 'Minimale Anzahl an Artikeln, die behalten wird',
 		'maintenance' => array(
 			'clear_cache' => 'Zwischenspeicher leeren',
@@ -120,7 +130,7 @@ return array(
 		'subscription_tools' => 'Abonnement-Tools',
 	),
 	'tag' => array(
-		'name' => 'Name',
+		'name' => 'Name',	// IGNORE
 		'new_name' => 'Neuer Name',
 		'old_name' => 'Alter Name',
 	),

+ 10 - 0
app/i18n/de/user.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(

+ 139 - 129
app/i18n/en-us/admin.php

@@ -1,194 +1,204 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
-		'allow_anonymous' => 'Allow anonymous reading of the default user\'s articles (%s)',
-		'allow_anonymous_refresh' => 'Allow anonymous refresh of the articles',
-		'api_enabled' => 'Allow <abbr>API</abbr> access <small>(required for mobile apps)</small>',
-		'form' => 'Web form (traditional, requires JavaScript)',
-		'http' => 'HTTP (for advanced users with HTTPS)',
-		'none' => 'None (dangerous)',
-		'title' => 'Authentication',
-		'token' => 'Authentication token',
-		'token_help' => 'Allows access to RSS output of the default user without authentication:',
-		'type' => 'Authentication method',
-		'unsafe_autologin' => 'Allow unsafe automatic login using the format: ',
+		'allow_anonymous' => 'Allow anonymous reading of the default user\'s articles (%s)',	// IGNORE
+		'allow_anonymous_refresh' => 'Allow anonymous refresh of the articles',	// IGNORE
+		'api_enabled' => 'Allow <abbr>API</abbr> access <small>(required for mobile apps)</small>',	// IGNORE
+		'form' => 'Web form (traditional, requires JavaScript)',	// IGNORE
+		'http' => 'HTTP (for advanced users with HTTPS)',	// IGNORE
+		'none' => 'None (dangerous)',	// IGNORE
+		'title' => 'Authentication',	// IGNORE
+		'token' => 'Authentication token',	// IGNORE
+		'token_help' => 'Allows access to RSS output of the default user without authentication:',	// IGNORE
+		'type' => 'Authentication method',	// IGNORE
+		'unsafe_autologin' => 'Allow unsafe automatic login using the format: ',	// IGNORE
 	),
 	'check_install' => array(
 		'cache' => array(
-			'nok' => 'Check permissions on <em>./data/cache</em> directory. HTTP server must have write permission.',
-			'ok' => 'Permissions on the cache directory are good.',
+			'nok' => 'Check permissions on <em>./data/cache</em> directory. HTTP server must have write permission.',	// IGNORE
+			'ok' => 'Permissions on the cache directory are good.',	// IGNORE
 		),
 		'categories' => array(
-			'nok' => 'Category table is improperly configured.',
-			'ok' => 'Category table is okay.',
+			'nok' => 'Category table is improperly configured.',	// IGNORE
+			'ok' => 'Category table is okay.',	// IGNORE
 		),
 		'connection' => array(
-			'nok' => 'Connection to the database cannot be established.',
-			'ok' => 'Connection to the database is okay.',
+			'nok' => 'Connection to the database cannot be established.',	// IGNORE
+			'ok' => 'Connection to the database is okay.',	// IGNORE
 		),
 		'ctype' => array(
-			'nok' => 'Cannot find a required library for character type checking (php-ctype).',
-			'ok' => 'You have the required library for character type checking (ctype).',
+			'nok' => 'Cannot find a required library for character type checking (php-ctype).',	// IGNORE
+			'ok' => 'You have the required library for character type checking (ctype).',	// IGNORE
 		),
 		'curl' => array(
-			'nok' => 'Cannot find the cURL library (php-curl package).',
-			'ok' => 'You have the cURL library.',
+			'nok' => 'Cannot find the cURL library (php-curl package).',	// IGNORE
+			'ok' => 'You have the cURL library.',	// IGNORE
 		),
 		'data' => array(
-			'nok' => 'Check permissions on <em>./data</em> directory. HTTP server must have write permission.',
-			'ok' => 'Permissions on the data directory are good.',
+			'nok' => 'Check permissions on <em>./data</em> directory. HTTP server must have write permission.',	// IGNORE
+			'ok' => 'Permissions on the data directory are good.',	// IGNORE
 		),
-		'database' => 'Database installation',
+		'database' => 'Database installation',	// IGNORE
 		'dom' => array(
-			'nok' => 'Cannot find a required library to browse the DOM (php-xml package).',
-			'ok' => 'You have the required library to browse the DOM.',
+			'nok' => 'Cannot find a required library to browse the DOM (php-xml package).',	// IGNORE
+			'ok' => 'You have the required library to browse the DOM.',	// IGNORE
 		),
 		'entries' => array(
-			'nok' => 'Entry table is improperly configured.',
-			'ok' => 'Entry table is okay.',
+			'nok' => 'Entry table is improperly configured.',	// IGNORE
+			'ok' => 'Entry table is okay.',	// IGNORE
 		),
 		'favicons' => array(
-			'nok' => 'Check permissions on <em>./data/favicons</em> directory. HTTP server must have write permission.',
-			'ok' => 'Permissions on the favicons directory are good.',
+			'nok' => 'Check permissions on <em>./data/favicons</em> directory. HTTP server must have write permission.',	// IGNORE
+			'ok' => 'Permissions on the favicons directory are good.',	// IGNORE
 		),
 		'feeds' => array(
-			'nok' => 'Feed table is improperly configured.',
-			'ok' => 'Feed table is okay.',
+			'nok' => 'Feed table is improperly configured.',	// IGNORE
+			'ok' => 'Feed table is okay.',	// IGNORE
 		),
 		'fileinfo' => array(
-			'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',
-			'ok' => 'You have the fileinfo library.',
+			'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',	// IGNORE
+			'ok' => 'You have the fileinfo library.',	// IGNORE
 		),
-		'files' => 'File installation',
+		'files' => 'File installation',	// IGNORE
 		'json' => array(
-			'nok' => 'Cannot find JSON (php-json package).',
-			'ok' => 'You have the JSON extension.',
+			'nok' => 'Cannot find JSON (php-json package).',	// IGNORE
+			'ok' => 'You have the JSON extension.',	// IGNORE
 		),
 		'mbstring' => array(
-			'nok' => 'Cannot find the recommended mbstring library for Unicode.',
-			'ok' => 'You have the recommended mbstring library for Unicode.',
+			'nok' => 'Cannot find the recommended mbstring library for Unicode.',	// IGNORE
+			'ok' => 'You have the recommended mbstring library for Unicode.',	// IGNORE
 		),
 		'pcre' => array(
-			'nok' => 'Cannot find a required library for regular expressions (php-pcre).',
-			'ok' => 'You have the required library for regular expressions (PCRE).',
+			'nok' => 'Cannot find a required library for regular expressions (php-pcre).',	// IGNORE
+			'ok' => 'You have the required library for regular expressions (PCRE).',	// IGNORE
 		),
 		'pdo' => array(
-			'nok' => 'Cannot find PDO or one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',
-			'ok' => 'You have PDO and at least one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',
+			'nok' => 'Cannot find PDO or one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',	// IGNORE
+			'ok' => 'You have PDO and at least one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',	// IGNORE
 		),
 		'php' => array(
-			'_' => 'PHP installation',
-			'nok' => 'Your PHP version is %s but FreshRSS requires at least version %s.',
-			'ok' => 'Your PHP version (%s) is compatible with FreshRSS.',
+			'_' => 'PHP installation',	// IGNORE
+			'nok' => 'Your PHP version is %s but FreshRSS requires at least version %s.',	// IGNORE
+			'ok' => 'Your PHP version (%s) is compatible with FreshRSS.',	// IGNORE
 		),
 		'tables' => array(
-			'nok' => 'There are one or more missing tables in the database.',
-			'ok' => 'The appropriate tables exist in the database.',
+			'nok' => 'There are one or more missing tables in the database.',	// IGNORE
+			'ok' => 'The appropriate tables exist in the database.',	// IGNORE
 		),
-		'title' => 'Installation check',
+		'title' => 'Installation check',	// IGNORE
 		'tokens' => array(
-			'nok' => 'Check permissions on <em>./data/tokens</em> directory. HTTP server must have write permission',
-			'ok' => 'Permissions on the tokens directory are good.',
+			'nok' => 'Check permissions on <em>./data/tokens</em> directory. HTTP server must have write permission',	// IGNORE
+			'ok' => 'Permissions on the tokens directory are good.',	// IGNORE
 		),
 		'users' => array(
-			'nok' => 'Check permissions on <em>./data/users</em> directory. HTTP server must have write permission',
-			'ok' => 'Permissions on the users directory are good.',
+			'nok' => 'Check permissions on <em>./data/users</em> directory. HTTP server must have write permission',	// IGNORE
+			'ok' => 'Permissions on the users directory are good.',	// IGNORE
 		),
 		'zip' => array(
-			'nok' => 'Cannot find the ZIP extension (php-zip package).',
-			'ok' => 'You have the ZIP extension.',
+			'nok' => 'Cannot find the ZIP extension (php-zip package).',	// IGNORE
+			'ok' => 'You have the ZIP extension.',	// IGNORE
 		),
 	),
 	'extensions' => array(
-		'author' => 'Author',
-		'community' => 'Available community extensions',
-		'description' => 'Description',
-		'disabled' => 'Disabled',
-		'empty_list' => 'There are no installed extensions',
-		'enabled' => 'Enabled',
-		'latest' => 'Installed',
-		'name' => 'Name',
-		'no_configure_view' => 'This extension cannot be configured.',
+		'author' => 'Author',	// IGNORE
+		'community' => 'Available community extensions',	// IGNORE
+		'description' => 'Description',	// IGNORE
+		'disabled' => 'Disabled',	// IGNORE
+		'empty_list' => 'There are no installed extensions',	// IGNORE
+		'enabled' => 'Enabled',	// IGNORE
+		'latest' => 'Installed',	// IGNORE
+		'name' => 'Name',	// IGNORE
+		'no_configure_view' => 'This extension cannot be configured.',	// IGNORE
 		'system' => array(
-			'_' => 'System extensions',
-			'no_rights' => 'System extension (you do not have the required permissions)',
+			'_' => 'System extensions',	// IGNORE
+			'no_rights' => 'System extension (you do not have the required permissions)',	// IGNORE
 		),
-		'title' => 'Extensions',
-		'update' => 'Update available',
-		'user' => 'User extensions',
-		'version' => 'Version',
+		'title' => 'Extensions',	// IGNORE
+		'update' => 'Update available',	// IGNORE
+		'user' => 'User extensions',	// IGNORE
+		'version' => 'Version',	// IGNORE
 	),
 	'stats' => array(
-		'_' => 'Statistics',
-		'all_feeds' => 'All feeds',
-		'category' => 'Category',
-		'entry_count' => 'Entry count',
-		'entry_per_category' => 'Entries per category',
-		'entry_per_day' => 'Entries per day (last 30 days)',
-		'entry_per_day_of_week' => 'Per day of week (average: %.2f messages)',
-		'entry_per_hour' => 'Per hour (average: %.2f messages)',
-		'entry_per_month' => 'Per month (average: %.2f messages)',
-		'entry_repartition' => 'Entries repartition',
-		'feed' => 'Feed',
-		'feed_per_category' => 'Feeds per category',
-		'idle' => 'Idle feeds',
-		'main' => 'Main statistics',
-		'main_stream' => 'Main stream',
-		'no_idle' => 'There are no idle feeds!',
-		'number_entries' => '%d articles',
-		'percent_of_total' => '%% of total',
-		'repartition' => 'Articles repartition',
+		'_' => 'Statistics',	// IGNORE
+		'all_feeds' => 'All feeds',	// IGNORE
+		'category' => 'Category',	// IGNORE
+		'entry_count' => 'Entry count',	// IGNORE
+		'entry_per_category' => 'Entries per category',	// IGNORE
+		'entry_per_day' => 'Entries per day (last 30 days)',	// IGNORE
+		'entry_per_day_of_week' => 'Per day of week (average: %.2f messages)',	// IGNORE
+		'entry_per_hour' => 'Per hour (average: %.2f messages)',	// IGNORE
+		'entry_per_month' => 'Per month (average: %.2f messages)',	// IGNORE
+		'entry_repartition' => 'Entries repartition',	// IGNORE
+		'feed' => 'Feed',	// IGNORE
+		'feed_per_category' => 'Feeds per category',	// IGNORE
+		'idle' => 'Idle feeds',	// IGNORE
+		'main' => 'Main statistics',	// IGNORE
+		'main_stream' => 'Main stream',	// IGNORE
+		'no_idle' => 'There are no idle feeds!',	// IGNORE
+		'number_entries' => '%d articles',	// IGNORE
+		'percent_of_total' => '%% of total',	// IGNORE
+		'repartition' => 'Articles repartition',	// IGNORE
 		'status_favorites' => 'Favorites',
-		'status_read' => 'Read',
-		'status_total' => 'Total',
-		'status_unread' => 'Unread',
-		'title' => 'Statistics',
-		'top_feed' => 'Top ten feeds',
+		'status_read' => 'Read',	// IGNORE
+		'status_total' => 'Total',	// IGNORE
+		'status_unread' => 'Unread',	// IGNORE
+		'title' => 'Statistics',	// IGNORE
+		'top_feed' => 'Top ten feeds',	// IGNORE
 	),
 	'system' => array(
-		'_' => 'System configuration',
-		'auto-update-url' => 'Auto-update server URL',
+		'_' => 'System configuration',	// IGNORE
+		'auto-update-url' => 'Auto-update server URL',	// IGNORE
 		'cookie-duration' => array(
-			'help' => 'in seconds',
-			'number' => 'Duration to keep logged in',
+			'help' => 'in seconds',	// IGNORE
+			'number' => 'Duration to keep logged in',	// IGNORE
 		),
-		'force_email_validation' => 'Force email address validation',
-		'instance-name' => 'Instance name',
-		'max-categories' => 'Max number of categories per user',
-		'max-feeds' => 'Max number of feeds per user',
+		'force_email_validation' => 'Force email address validation',	// IGNORE
+		'instance-name' => 'Instance name',	// IGNORE
+		'max-categories' => 'Max number of categories per user',	// IGNORE
+		'max-feeds' => 'Max number of feeds per user',	// IGNORE
 		'registration' => array(
-			'help' => '0 means that there is no account limit',
-			'number' => 'Max number of accounts',
+			'help' => '0 means that there is no account limit',	// IGNORE
+			'number' => 'Max number of accounts',	// IGNORE
 		),
 	),
 	'update' => array(
-		'_' => 'Update system',
-		'apply' => 'Apply',
-		'check' => 'Check for new updates',
-		'current_version' => 'Your current version of FreshRSS is %s.',
-		'last' => 'Last verification: %s',
-		'none' => 'No update to apply',
-		'title' => 'Update system',
+		'_' => 'Update system',	// IGNORE
+		'apply' => 'Apply',	// IGNORE
+		'check' => 'Check for new updates',	// IGNORE
+		'current_version' => 'Your current version of FreshRSS is %s.',	// IGNORE
+		'last' => 'Last verification: %s',	// IGNORE
+		'none' => 'No update to apply',	// IGNORE
+		'title' => 'Update system',	// IGNORE
 	),
 	'user' => array(
-		'admin' => 'Administrator',
-		'article_count' => 'Articles',
-		'back_to_manage' => '← Return to user list',
-		'create' => 'Create new user',
-		'database_size' => 'Database size',
-		'email' => 'Email address',
-		'enabled' => 'Enabled',
-		'feed_count' => 'Feeds',
-		'is_admin' => 'Is admin',
-		'language' => 'Language',
-		'last_user_activity' => 'Last user activity',
-		'list' => 'User list',
-		'number' => 'There is %d account created',
-		'numbers' => 'There are %d accounts created',
-		'password_form' => 'Password<br /><small>(for the Web-form login method)</small>',
-		'password_format' => 'At least 7 characters',
-		'title' => 'Manage users',
-		'username' => 'Username',
+		'admin' => 'Administrator',	// IGNORE
+		'article_count' => 'Articles',	// IGNORE
+		'back_to_manage' => '← Return to user list',	// IGNORE
+		'create' => 'Create new user',	// IGNORE
+		'database_size' => 'Database size',	// IGNORE
+		'email' => 'Email address',	// IGNORE
+		'enabled' => 'Enabled',	// IGNORE
+		'feed_count' => 'Feeds',	// IGNORE
+		'is_admin' => 'Is admin',	// IGNORE
+		'language' => 'Language',	// IGNORE
+		'last_user_activity' => 'Last user activity',	// IGNORE
+		'list' => 'User list',	// IGNORE
+		'number' => 'There is %d account created',	// IGNORE
+		'numbers' => 'There are %d accounts created',	// IGNORE
+		'password_form' => 'Password<br /><small>(for the Web-form login method)</small>',	// IGNORE
+		'password_format' => 'At least 7 characters',	// IGNORE
+		'title' => 'Manage users',	// IGNORE
+		'username' => 'Username',	// IGNORE
 	),
 );

+ 182 - 172
app/i18n/en-us/conf.php

@@ -1,101 +1,111 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
-		'_' => 'Archiving',
-		'exception' => 'Purge exception',
-		'help' => 'More options are available in the individual feed\'s settings',
+		'_' => 'Archiving',	// IGNORE
+		'exception' => 'Purge exception',	// IGNORE
+		'help' => 'More options are available in the individual feed\'s settings',	// IGNORE
 		'keep_favourites' => 'Never delete favorites',
-		'keep_labels' => 'Never delete labels',
-		'keep_max' => 'Maximum number of articles to keep',
-		'keep_min_by_feed' => 'Minimum number of articles to keep per feed',
-		'keep_period' => 'Maximum age of articles to keep',
-		'keep_unreads' => 'Never delete unread articles',
-		'maintenance' => 'Maintenance',
-		'optimize' => 'Optimize database',
-		'optimize_help' => 'Run occasionally to reduce the size of the database',
-		'policy' => 'Purge policy',
-		'policy_warning' => 'If no purge policy is selected, every article will be kept.',
-		'purge_now' => 'Purge now',
-		'title' => 'Archiving',
-		'ttl' => 'Do not automatically refresh more often than',
+		'keep_labels' => 'Never delete labels',	// IGNORE
+		'keep_max' => 'Maximum number of articles to keep',	// IGNORE
+		'keep_min_by_feed' => 'Minimum number of articles to keep per feed',	// IGNORE
+		'keep_period' => 'Maximum age of articles to keep',	// IGNORE
+		'keep_unreads' => 'Never delete unread articles',	// IGNORE
+		'maintenance' => 'Maintenance',	// IGNORE
+		'optimize' => 'Optimize database',	// IGNORE
+		'optimize_help' => 'Run occasionally to reduce the size of the database',	// IGNORE
+		'policy' => 'Purge policy',	// IGNORE
+		'policy_warning' => 'If no purge policy is selected, every article will be kept.',	// IGNORE
+		'purge_now' => 'Purge now',	// IGNORE
+		'title' => 'Archiving',	// IGNORE
+		'ttl' => 'Do not automatically refresh more often than',	// IGNORE
 	),
 	'display' => array(
-		'_' => 'Display',
+		'_' => 'Display',	// IGNORE
 		'icon' => array(
-			'bottom_line' => 'Bottom line',
-			'display_authors' => 'Authors',
-			'entry' => 'Article icons',
-			'publication_date' => 'Date of publication',
-			'related_tags' => 'Article tags',
-			'sharing' => 'Sharing',
-			'summary' => 'Summary',
-			'top_line' => 'Top line',
+			'bottom_line' => 'Bottom line',	// IGNORE
+			'display_authors' => 'Authors',	// IGNORE
+			'entry' => 'Article icons',	// IGNORE
+			'publication_date' => 'Date of publication',	// IGNORE
+			'related_tags' => 'Article tags',	// IGNORE
+			'sharing' => 'Sharing',	// IGNORE
+			'summary' => 'Summary',	// IGNORE
+			'top_line' => 'Top line',	// IGNORE
 		),
-		'language' => 'Language',
+		'language' => 'Language',	// IGNORE
 		'notif_html5' => array(
-			'seconds' => 'seconds (0 means no timeout)',
-			'timeout' => 'HTML5 notification timeout',
+			'seconds' => 'seconds (0 means no timeout)',	// IGNORE
+			'timeout' => 'HTML5 notification timeout',	// IGNORE
 		),
-		'show_nav_buttons' => 'Show the navigation buttons',
-		'theme' => 'Theme',
-		'theme_not_available' => 'The “%s” theme is not available anymore. Please choose another theme.',
+		'show_nav_buttons' => 'Show the navigation buttons',	// IGNORE
+		'theme' => 'Theme',	// IGNORE
+		'theme_not_available' => 'The “%s” theme is not available anymore. Please choose another theme.',	// IGNORE
 		'thumbnail' => array(
-			'label' => 'Thumbnail',
-			'landscape' => 'Landscape',
-			'none' => 'None',
-			'portrait' => 'Portrait',
-			'square' => 'Square',
+			'label' => 'Thumbnail',	// IGNORE
+			'landscape' => 'Landscape',	// IGNORE
+			'none' => 'None',	// IGNORE
+			'portrait' => 'Portrait',	// IGNORE
+			'square' => 'Square',	// IGNORE
 		),
-		'title' => 'Display',
+		'title' => 'Display',	// IGNORE
 		'width' => array(
-			'content' => 'Content width',
-			'large' => 'Wide',
-			'medium' => 'Medium',
-			'no_limit' => 'Full Width',
-			'thin' => 'Narrow',
+			'content' => 'Content width',	// IGNORE
+			'large' => 'Wide',	// IGNORE
+			'medium' => 'Medium',	// IGNORE
+			'no_limit' => 'Full Width',	// IGNORE
+			'thin' => 'Narrow',	// IGNORE
 		),
 	),
 	'profile' => array(
-		'_' => 'Profile management',
-		'api' => 'API management',
+		'_' => 'Profile management',	// IGNORE
+		'api' => 'API management',	// IGNORE
 		'delete' => array(
-			'_' => 'Account deletion',
-			'warn' => 'Your account and all related data will be deleted.',
+			'_' => 'Account deletion',	// IGNORE
+			'warn' => 'Your account and all related data will be deleted.',	// IGNORE
 		),
-		'email' => 'Email address',
-		'password_api' => 'API password<br /><small>(e.g., for mobile apps)</small>',
-		'password_form' => 'Password<br /><small>(for the Web-form login method)</small>',
-		'password_format' => 'At least 7 characters',
-		'title' => 'Profile',
+		'email' => 'Email address',	// IGNORE
+		'password_api' => 'API password<br /><small>(e.g., for mobile apps)</small>',	// IGNORE
+		'password_form' => 'Password<br /><small>(for the Web-form login method)</small>',	// IGNORE
+		'password_format' => 'At least 7 characters',	// IGNORE
+		'title' => 'Profile',	// IGNORE
 	),
 	'query' => array(
-		'_' => 'User queries',
-		'deprecated' => 'This query is no longer valid. The referenced category or feed has been deleted.',
+		'_' => 'User queries',	// IGNORE
+		'deprecated' => 'This query is no longer valid. The referenced category or feed has been deleted.',	// IGNORE
 		'filter' => array(
-			'_' => 'Filter applied:',
-			'categories' => 'Display by category',
-			'feeds' => 'Display by feed',
-			'order' => 'Sort by date',
-			'search' => 'Expression',
-			'state' => 'State',
-			'tags' => 'Display by tag',
-			'type' => 'Type',
+			'_' => 'Filter applied:',	// IGNORE
+			'categories' => 'Display by category',	// IGNORE
+			'feeds' => 'Display by feed',	// IGNORE
+			'order' => 'Sort by date',	// IGNORE
+			'search' => 'Expression',	// IGNORE
+			'state' => 'State',	// IGNORE
+			'tags' => 'Display by tag',	// IGNORE
+			'type' => 'Type',	// IGNORE
 		),
-		'get_all' => 'Display all articles',
-		'get_category' => 'Display "%s" category',
+		'get_all' => 'Display all articles',	// IGNORE
+		'get_category' => 'Display "%s" category',	// IGNORE
 		'get_favorite' => 'Display favorite articles',
-		'get_feed' => 'Display "%s" feed',
-		'name' => 'Name',
-		'no_filter' => 'No filter',
-		'number' => 'Query n°%d',
-		'order_asc' => 'Display oldest articles first',
-		'order_desc' => 'Display newest articles first',
-		'search' => 'Search for "%s"',
-		'state_0' => 'Display all articles',
-		'state_1' => 'Display read articles',
-		'state_2' => 'Display unread articles',
-		'state_3' => 'Display all articles',
+		'get_feed' => 'Display "%s" feed',	// IGNORE
+		'name' => 'Name',	// IGNORE
+		'no_filter' => 'No filter',	// IGNORE
+		'number' => 'Query n°%d',	// IGNORE
+		'order_asc' => 'Display oldest articles first',	// IGNORE
+		'order_desc' => 'Display newest articles first',	// IGNORE
+		'search' => 'Search for "%s"',	// IGNORE
+		'state_0' => 'Display all articles',	// IGNORE
+		'state_1' => 'Display read articles',	// IGNORE
+		'state_2' => 'Display unread articles',	// IGNORE
+		'state_3' => 'Display all articles',	// IGNORE
 		'state_4' => 'Display favorite articles',
 		'state_5' => 'Display read favorite articles',
 		'state_6' => 'Display unread favorite articles',
@@ -104,121 +114,121 @@ return array(
 		'state_9' => 'Display read not favorite articles',
 		'state_10' => 'Display unread not favorite articles',
 		'state_11' => 'Display not favorite articles',
-		'state_12' => 'Display all articles',
-		'state_13' => 'Display read articles',
-		'state_14' => 'Display unread articles',
-		'state_15' => 'Display all articles',
-		'title' => 'User queries',
+		'state_12' => 'Display all articles',	// IGNORE
+		'state_13' => 'Display read articles',	// IGNORE
+		'state_14' => 'Display unread articles',	// IGNORE
+		'state_15' => 'Display all articles',	// IGNORE
+		'title' => 'User queries',	// IGNORE
 	),
 	'reading' => array(
-		'_' => 'Reading',
-		'after_onread' => 'After “mark all as read”,',
+		'_' => 'Reading',	// IGNORE
+		'after_onread' => 'After “mark all as read”,',	// IGNORE
 		'always_show_favorites' => 'Show all articles in favorites by default',
-		'articles_per_page' => 'Number of articles per page',
-		'auto_load_more' => 'Load more articles at the bottom of the page',
-		'auto_remove_article' => 'Hide articles after reading',
-		'confirm_enabled' => 'Display a confirmation dialog on “mark all as read” actions',
-		'display_articles_unfolded' => 'Show articles unfolded by default',
-		'display_categories_unfolded' => 'Categories to unfold',
-		'hide_read_feeds' => 'Hide categories & feeds with no unread articles (does not work with “Show all articles” configuration)',
-		'img_with_lazyload' => 'Use "lazy load" mode to load pictures',
-		'jump_next' => 'jump to next unread sibling (feed or category)',
-		'mark_updated_article_unread' => 'Mark updated articles as unread',
-		'number_divided_when_reader' => 'Divide by 2 in the reading view.',
+		'articles_per_page' => 'Number of articles per page',	// IGNORE
+		'auto_load_more' => 'Load more articles at the bottom of the page',	// IGNORE
+		'auto_remove_article' => 'Hide articles after reading',	// IGNORE
+		'confirm_enabled' => 'Display a confirmation dialog on “mark all as read” actions',	// IGNORE
+		'display_articles_unfolded' => 'Show articles unfolded by default',	// IGNORE
+		'display_categories_unfolded' => 'Categories to unfold',	// IGNORE
+		'hide_read_feeds' => 'Hide categories & feeds with no unread articles (does not work with “Show all articles” configuration)',	// IGNORE
+		'img_with_lazyload' => 'Use "lazy load" mode to load pictures',	// IGNORE
+		'jump_next' => 'jump to next unread sibling (feed or category)',	// IGNORE
+		'mark_updated_article_unread' => 'Mark updated articles as unread',	// IGNORE
+		'number_divided_when_reader' => 'Divide by 2 in the reading view.',	// IGNORE
 		'read' => array(
-			'article_open_on_website' => 'when the article is opened on its original website',
-			'article_viewed' => 'when the article is viewed',
-			'keep_max_n_unread' => 'Max number of articles to keep unread',
-			'scroll' => 'while scrolling',
-			'upon_reception' => 'upon receiving the article',
-			'when' => 'Mark an article as read…',
-			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',
+			'article_open_on_website' => 'when the article is opened on its original website',	// IGNORE
+			'article_viewed' => 'when the article is viewed',	// IGNORE
+			'keep_max_n_unread' => 'Max number of articles to keep unread',	// IGNORE
+			'scroll' => 'while scrolling',	// IGNORE
+			'upon_reception' => 'upon receiving the article',	// IGNORE
+			'when' => 'Mark an article as read…',	// IGNORE
+			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',	// IGNORE
 		),
 		'show' => array(
-			'_' => 'Articles to display',
-			'active_category' => 'Active category',
-			'adaptive' => 'Adjust showing',
-			'all_articles' => 'Show all articles',
-			'all_categories' => 'All categories',
-			'no_category' => 'No category',
-			'remember_categories' => 'Remember open categories',
-			'unread' => 'Show only unread',
+			'_' => 'Articles to display',	// IGNORE
+			'active_category' => 'Active category',	// IGNORE
+			'adaptive' => 'Adjust showing',	// IGNORE
+			'all_articles' => 'Show all articles',	// IGNORE
+			'all_categories' => 'All categories',	// IGNORE
+			'no_category' => 'No category',	// IGNORE
+			'remember_categories' => 'Remember open categories',	// IGNORE
+			'unread' => 'Show only unread',	// IGNORE
 		),
-		'show_fav_unread_help' => 'Applies also on labels',
-		'sides_close_article' => 'Clicking outside of article text area closes the article',
+		'show_fav_unread_help' => 'Applies also on labels',	// IGNORE
+		'sides_close_article' => 'Clicking outside of article text area closes the article',	// IGNORE
 		'sort' => array(
-			'_' => 'Sort order',
-			'newer_first' => 'Newest first',
-			'older_first' => 'Oldest first',
+			'_' => 'Sort order',	// IGNORE
+			'newer_first' => 'Newest first',	// IGNORE
+			'older_first' => 'Oldest first',	// IGNORE
 		),
-		'sticky_post' => 'Stick the article to the top when opened',
-		'title' => 'Reading',
+		'sticky_post' => 'Stick the article to the top when opened',	// IGNORE
+		'title' => 'Reading',	// IGNORE
 		'view' => array(
-			'default' => 'Default view',
-			'global' => 'Global view',
-			'normal' => 'Normal view',
-			'reader' => 'Reading view',
+			'default' => 'Default view',	// IGNORE
+			'global' => 'Global view',	// IGNORE
+			'normal' => 'Normal view',	// IGNORE
+			'reader' => 'Reading view',	// IGNORE
 		),
 	),
 	'sharing' => array(
-		'_' => 'Sharing',
-		'add' => 'Add a sharing method',
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
-		'email' => 'Email',
-		'facebook' => 'Facebook',
-		'more_information' => 'More information',
-		'print' => 'Print',
-		'raindrop' => 'Raindrop.io',
-		'remove' => 'Remove sharing method',
-		'shaarli' => 'Shaarli',
-		'share_name' => 'Share name to display',
-		'share_url' => 'Share URL to use',
-		'title' => 'Sharing',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'_' => 'Sharing',	// IGNORE
+		'add' => 'Add a sharing method',	// IGNORE
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
+		'email' => 'Email',	// IGNORE
+		'facebook' => 'Facebook',	// IGNORE
+		'more_information' => 'More information',	// IGNORE
+		'print' => 'Print',	// IGNORE
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'remove' => 'Remove sharing method',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'share_name' => 'Share name to display',	// IGNORE
+		'share_url' => 'Share URL to use',	// IGNORE
+		'title' => 'Sharing',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
-		'_' => 'Shortcuts',
-		'article_action' => 'Article actions',
-		'auto_share' => 'Share',
-		'auto_share_help' => 'If there is only one sharing mode, it is used. Otherwise, modes are accessible by their number.',
-		'close_dropdown' => 'Close menus',
-		'collapse_article' => 'Collapse',
-		'first_article' => 'Open the first article',
-		'focus_search' => 'Access search box',
-		'global_view' => 'Switch to global view',
-		'help' => 'Display documentation',
-		'javascript' => 'JavaScript must be enabled in order to use shortcuts',
-		'last_article' => 'Open the last article',
-		'load_more' => 'Load more articles',
+		'_' => 'Shortcuts',	// IGNORE
+		'article_action' => 'Article actions',	// IGNORE
+		'auto_share' => 'Share',	// IGNORE
+		'auto_share_help' => 'If there is only one sharing mode, it is used. Otherwise, modes are accessible by their number.',	// IGNORE
+		'close_dropdown' => 'Close menus',	// IGNORE
+		'collapse_article' => 'Collapse',	// IGNORE
+		'first_article' => 'Open the first article',	// IGNORE
+		'focus_search' => 'Access search box',	// IGNORE
+		'global_view' => 'Switch to global view',	// IGNORE
+		'help' => 'Display documentation',	// IGNORE
+		'javascript' => 'JavaScript must be enabled in order to use shortcuts',	// IGNORE
+		'last_article' => 'Open the last article',	// IGNORE
+		'load_more' => 'Load more articles',	// IGNORE
 		'mark_favorite' => 'Toggle favorite',
-		'mark_read' => 'Toggle read',
-		'navigation' => 'Navigation',
-		'navigation_help' => 'With the <kbd>⇧ Shift</kbd> modifier, navigation shortcuts apply on feeds.<br/>With the <kbd>Alt ⎇</kbd> modifier, navigation shortcuts apply on categories.',
-		'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.',
-		'next_article' => 'Open the next article',
-		'next_unread_article' => 'Open the next unread article',
-		'non_standard' => 'Some keys (<kbd>%s</kbd>) may not work as shortcuts.',
-		'normal_view' => 'Switch to normal view',
-		'other_action' => 'Other actions',
-		'previous_article' => 'Open the previous article',
-		'reading_view' => 'Switch to reading view',
-		'rss_view' => 'Open as RSS feed',
-		'see_on_website' => 'See on original website',
-		'shift_for_all_read' => '+ <kbd>Alt ⎇</kbd> to mark previous articles as read<br />+ <kbd>⇧ Shift</kbd> to mark all articles as read',
-		'skip_next_article' => 'Focus next without opening',
-		'skip_previous_article' => 'Focus previous without opening',
-		'title' => 'Shortcuts',
-		'toggle_media' => 'Play/pause media',
-		'user_filter' => 'Access user queries',
-		'user_filter_help' => 'If there is only one user query, it is used. Otherwise, queries are accessible by their number.',
-		'views' => 'Views',
+		'mark_read' => 'Toggle read',	// IGNORE
+		'navigation' => 'Navigation',	// IGNORE
+		'navigation_help' => 'With the <kbd>⇧ Shift</kbd> modifier, navigation shortcuts apply on feeds.<br/>With the <kbd>Alt ⎇</kbd> modifier, navigation shortcuts apply on categories.',	// IGNORE
+		'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.',	// IGNORE
+		'next_article' => 'Open the next article',	// IGNORE
+		'next_unread_article' => 'Open the next unread article',	// IGNORE
+		'non_standard' => 'Some keys (<kbd>%s</kbd>) may not work as shortcuts.',	// IGNORE
+		'normal_view' => 'Switch to normal view',	// IGNORE
+		'other_action' => 'Other actions',	// IGNORE
+		'previous_article' => 'Open the previous article',	// IGNORE
+		'reading_view' => 'Switch to reading view',	// IGNORE
+		'rss_view' => 'Open as RSS feed',	// IGNORE
+		'see_on_website' => 'See on original website',	// IGNORE
+		'shift_for_all_read' => '+ <kbd>Alt ⎇</kbd> to mark previous articles as read<br />+ <kbd>⇧ Shift</kbd> to mark all articles as read',	// IGNORE
+		'skip_next_article' => 'Focus next without opening',	// IGNORE
+		'skip_previous_article' => 'Focus previous without opening',	// IGNORE
+		'title' => 'Shortcuts',	// IGNORE
+		'toggle_media' => 'Play/pause media',	// IGNORE
+		'user_filter' => 'Access user queries',	// IGNORE
+		'user_filter_help' => 'If there is only one user query, it is used. Otherwise, queries are accessible by their number.',	// IGNORE
+		'views' => 'Views',	// IGNORE
 	),
 	'user' => array(
-		'articles_and_size' => '%s articles (%s)',
-		'current' => 'Current user',
-		'is_admin' => 'is administrator',
-		'users' => 'Users',
+		'articles_and_size' => '%s articles (%s)',	// IGNORE
+		'current' => 'Current user',	// IGNORE
+		'is_admin' => 'is administrator',	// IGNORE
+		'users' => 'Users',	// IGNORE
 	),
 );

+ 92 - 82
app/i18n/en-us/feedback.php

@@ -1,134 +1,144 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
-		'denied' => 'You don’t have permission to access this page',
-		'not_found' => 'You are looking for a page that doesn’t exist',
+		'denied' => 'You don’t have permission to access this page',	// IGNORE
+		'not_found' => 'You are looking for a page that doesn’t exist',	// IGNORE
 	),
 	'admin' => array(
-		'optimization_complete' => 'Optimization complete',
+		'optimization_complete' => 'Optimization complete',	// IGNORE
 	),
 	'api' => array(
 		'password' => array(
-			'failed' => 'Your password cannot be modified',
-			'updated' => 'Your password has been modified',
+			'failed' => 'Your password cannot be modified',	// IGNORE
+			'updated' => 'Your password has been modified',	// IGNORE
 		),
 	),
 	'auth' => array(
 		'login' => array(
-			'invalid' => 'Login is invalid',
-			'success' => 'You are connected',
+			'invalid' => 'Login is invalid',	// IGNORE
+			'success' => 'You are connected',	// IGNORE
 		),
 		'logout' => array(
-			'success' => 'You are disconnected',
+			'success' => 'You are disconnected',	// IGNORE
 		),
 	),
 	'conf' => array(
-		'error' => 'An error occurred while saving configuration',
-		'query_created' => 'Query "%s" has been created.',
-		'shortcuts_updated' => 'Shortcuts have been updated',
-		'updated' => 'Configuration has been updated',
+		'error' => 'An error occurred while saving configuration',	// IGNORE
+		'query_created' => 'Query "%s" has been created.',	// IGNORE
+		'shortcuts_updated' => 'Shortcuts have been updated',	// IGNORE
+		'updated' => 'Configuration has been updated',	// IGNORE
 	),
 	'extensions' => array(
-		'already_enabled' => '%s is already enabled',
-		'cannot_remove' => '%s cannot be removed',
+		'already_enabled' => '%s is already enabled',	// IGNORE
+		'cannot_remove' => '%s cannot be removed',	// IGNORE
 		'disable' => array(
-			'ko' => '%s cannot be disabled. <a href="%s">Check FreshRSS logs</a> for details.',
-			'ok' => '%s is now disabled',
+			'ko' => '%s cannot be disabled. <a href="%s">Check FreshRSS logs</a> for details.',	// IGNORE
+			'ok' => '%s is now disabled',	// IGNORE
 		),
 		'enable' => array(
-			'ko' => '%s cannot be enabled. <a href="%s">Check FreshRSS logs</a> for details.',
-			'ok' => '%s is now enabled',
+			'ko' => '%s cannot be enabled. <a href="%s">Check FreshRSS logs</a> for details.',	// IGNORE
+			'ok' => '%s is now enabled',	// IGNORE
 		),
-		'no_access' => 'You have no access on %s',
-		'not_enabled' => '%s is not enabled',
-		'not_found' => '%s does not exist',
-		'removed' => '%s removed',
+		'no_access' => 'You have no access on %s',	// IGNORE
+		'not_enabled' => '%s is not enabled',	// IGNORE
+		'not_found' => '%s does not exist',	// IGNORE
+		'removed' => '%s removed',	// IGNORE
 	),
 	'import_export' => array(
-		'export_no_zip_extension' => 'The ZIP extension is not present on your server. Please try to export files one by one.',
-		'feeds_imported' => 'Your feeds have been imported and will now be updated',
-		'feeds_imported_with_errors' => 'Your feeds have been imported, but some errors occurred',
-		'file_cannot_be_uploaded' => 'File cannot be uploaded!',
-		'no_zip_extension' => 'The ZIP extension is not present on your server.',
-		'zip_error' => 'An error occurred during ZIP import.',
+		'export_no_zip_extension' => 'The ZIP extension is not present on your server. Please try to export files one by one.',	// IGNORE
+		'feeds_imported' => 'Your feeds have been imported and will now be updated',	// IGNORE
+		'feeds_imported_with_errors' => 'Your feeds have been imported, but some errors occurred',	// IGNORE
+		'file_cannot_be_uploaded' => 'File cannot be uploaded!',	// IGNORE
+		'no_zip_extension' => 'The ZIP extension is not present on your server.',	// IGNORE
+		'zip_error' => 'An error occurred during ZIP import.',	// IGNORE
 	),
 	'profile' => array(
-		'error' => 'Your profile cannot be modified',
-		'updated' => 'Your profile has been modified',
+		'error' => 'Your profile cannot be modified',	// IGNORE
+		'updated' => 'Your profile has been modified',	// IGNORE
 	),
 	'sub' => array(
-		'actualize' => 'Updating',
+		'actualize' => 'Updating',	// IGNORE
 		'articles' => array(
-			'marked_read' => 'The selected articles have been marked as read.',
-			'marked_unread' => 'The articles have been marked as unread.',
+			'marked_read' => 'The selected articles have been marked as read.',	// IGNORE
+			'marked_unread' => 'The articles have been marked as unread.',	// IGNORE
 		),
 		'category' => array(
-			'created' => 'Category %s has been created.',
-			'deleted' => 'Category has been deleted.',
-			'emptied' => 'Category has been emptied',
-			'error' => 'Category cannot be updated',
-			'name_exists' => 'Category name already exists.',
-			'no_id' => 'You must specify the id of the category.',
-			'no_name' => 'Category name cannot be empty.',
-			'not_delete_default' => 'You cannot delete the default category!',
-			'not_exist' => 'The category does not exist!',
-			'over_max' => 'You have reached your limit of categories (%d)',
-			'updated' => 'Category has been updated.',
+			'created' => 'Category %s has been created.',	// IGNORE
+			'deleted' => 'Category has been deleted.',	// IGNORE
+			'emptied' => 'Category has been emptied',	// IGNORE
+			'error' => 'Category cannot be updated',	// IGNORE
+			'name_exists' => 'Category name already exists.',	// IGNORE
+			'no_id' => 'You must specify the id of the category.',	// IGNORE
+			'no_name' => 'Category name cannot be empty.',	// IGNORE
+			'not_delete_default' => 'You cannot delete the default category!',	// IGNORE
+			'not_exist' => 'The category does not exist!',	// IGNORE
+			'over_max' => 'You have reached your limit of categories (%d)',	// IGNORE
+			'updated' => 'Category has been updated.',	// IGNORE
 		),
 		'feed' => array(
-			'actualized' => '<em>%s</em> has been updated',
-			'actualizeds' => 'RSS feeds have been updated',
-			'added' => 'RSS feed <em>%s</em> has been added',
-			'already_subscribed' => 'You have already subscribed to <em>%s</em>',
-			'cache_cleared' => '<em>%s</em> cache has been cleared',
-			'deleted' => 'Feed has been deleted',
-			'error' => 'Feed cannot be updated',
-			'internal_problem' => 'The newsfeed could not be added. <a href="%s">Check FreshRSS logs</a> for details. You can try force adding by appending <code>#force_feed</code> to the URL.',
-			'invalid_url' => 'URL <em>%s</em> is invalid',
-			'n_actualized' => '%d feeds have been updated',
-			'n_entries_deleted' => '%d articles have been deleted',
-			'no_refresh' => 'There are no feeds to refresh',
-			'not_added' => '<em>%s</em> could not be added',
-			'not_found' => 'Feed cannot be found',
-			'over_max' => 'You have reached your limit of feeds (%d)',
-			'reloaded' => '<em>%s</em> has been reloaded',
+			'actualized' => '<em>%s</em> has been updated',	// IGNORE
+			'actualizeds' => 'RSS feeds have been updated',	// IGNORE
+			'added' => 'RSS feed <em>%s</em> has been added',	// IGNORE
+			'already_subscribed' => 'You have already subscribed to <em>%s</em>',	// IGNORE
+			'cache_cleared' => '<em>%s</em> cache has been cleared',	// IGNORE
+			'deleted' => 'Feed has been deleted',	// IGNORE
+			'error' => 'Feed cannot be updated',	// IGNORE
+			'internal_problem' => 'The newsfeed could not be added. <a href="%s">Check FreshRSS logs</a> for details. You can try force adding by appending <code>#force_feed</code> to the URL.',	// IGNORE
+			'invalid_url' => 'URL <em>%s</em> is invalid',	// IGNORE
+			'n_actualized' => '%d feeds have been updated',	// IGNORE
+			'n_entries_deleted' => '%d articles have been deleted',	// IGNORE
+			'no_refresh' => 'There are no feeds to refresh',	// IGNORE
+			'not_added' => '<em>%s</em> could not be added',	// IGNORE
+			'not_found' => 'Feed cannot be found',	// IGNORE
+			'over_max' => 'You have reached your limit of feeds (%d)',	// IGNORE
+			'reloaded' => '<em>%s</em> has been reloaded',	// IGNORE
 			'selector_preview' => array(
-				'http_error' => 'Failed to load website content.',
-				'no_entries' => 'There are no articles in this feed. You need at least one article to create a preview.',
-				'no_feed' => 'Internal error (feed cannot be found).',
-				'no_result' => 'The selector didn\'t match anything. As a fallback the original feed text will be displayed instead.',
-				'selector_empty' => 'The selector is empty. You need to define one to create a preview.',
+				'http_error' => 'Failed to load website content.',	// IGNORE
+				'no_entries' => 'There are no articles in this feed. You need at least one article to create a preview.',	// IGNORE
+				'no_feed' => 'Internal error (feed cannot be found).',	// IGNORE
+				'no_result' => 'The selector didn\'t match anything. As a fallback the original feed text will be displayed instead.',	// IGNORE
+				'selector_empty' => 'The selector is empty. You need to define one to create a preview.',	// IGNORE
 			),
-			'updated' => 'Feed has been updated',
+			'updated' => 'Feed has been updated',	// IGNORE
 		),
-		'purge_completed' => 'Purge completed (%d articles deleted)',
+		'purge_completed' => 'Purge completed (%d articles deleted)',	// IGNORE
 	),
 	'tag' => array(
-		'created' => 'Tag "%s" has been created.',
-		'name_exists' => 'Tag name already exists.',
-		'renamed' => 'Tag "%s" has been renamed to "%s".',
+		'created' => 'Tag "%s" has been created.',	// IGNORE
+		'name_exists' => 'Tag name already exists.',	// IGNORE
+		'renamed' => 'Tag "%s" has been renamed to "%s".',	// IGNORE
 	),
 	'update' => array(
-		'can_apply' => 'FreshRSS will now be updated to the <strong>version %s</strong>.',
-		'error' => 'The update process has encountered an error: %s',
-		'file_is_nok' => 'New <strong>version %s</strong> available, but check permissions on <em>%s</em> directory. HTTP server must have have write permission',
-		'finished' => 'Update complete!',
-		'none' => 'No update to apply',
-		'server_not_found' => 'Update server cannot be found. [%s]',
+		'can_apply' => 'FreshRSS will now be updated to the <strong>version %s</strong>.',	// IGNORE
+		'error' => 'The update process has encountered an error: %s',	// IGNORE
+		'file_is_nok' => 'New <strong>version %s</strong> available, but check permissions on <em>%s</em> directory. HTTP server must have have write permission',	// IGNORE
+		'finished' => 'Update complete!',	// IGNORE
+		'none' => 'No update to apply',	// IGNORE
+		'server_not_found' => 'Update server cannot be found. [%s]',	// IGNORE
 	),
 	'user' => array(
 		'created' => array(
-			'_' => 'User %s has been created',
-			'error' => 'User %s cannot be created',
+			'_' => 'User %s has been created',	// IGNORE
+			'error' => 'User %s cannot be created',	// IGNORE
 		),
 		'deleted' => array(
-			'_' => 'User %s has been deleted',
-			'error' => 'User %s cannot be deleted',
+			'_' => 'User %s has been deleted',	// IGNORE
+			'error' => 'User %s cannot be deleted',	// IGNORE
 		),
 		'updated' => array(
-			'_' => 'User %s has been updated',
-			'error' => 'User %s has not been updated',
+			'_' => 'User %s has been updated',	// IGNORE
+			'error' => 'User %s has not been updated',	// IGNORE
 		),
 	),
 );

+ 191 - 181
app/i18n/en-us/gen.php

@@ -1,219 +1,229 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
-		'actualize' => 'Update feeds',
-		'add' => 'Add',
-		'back' => '← Go back',
-		'back_to_rss_feeds' => '← Go back to your RSS feeds',
-		'cancel' => 'Cancel',
-		'create' => 'Create',
-		'demote' => 'Demote',
-		'disable' => 'Disable',
-		'empty' => 'Empty',
-		'enable' => 'Enable',
-		'export' => 'Export',
-		'filter' => 'Filter',
-		'import' => 'Import',
-		'load_default_shortcuts' => 'Load default shortcuts',
-		'manage' => 'Manage',
-		'mark_read' => 'Mark as read',
-		'promote' => 'Promote',
-		'purge' => 'Purge',
-		'remove' => 'Remove',
-		'rename' => 'Rename',
-		'see_website' => 'See website',
-		'submit' => 'Submit',
-		'truncate' => 'Delete all articles',
-		'update' => 'Update',
+		'actualize' => 'Update feeds',	// IGNORE
+		'add' => 'Add',	// IGNORE
+		'back' => '← Go back',	// IGNORE
+		'back_to_rss_feeds' => '← Go back to your RSS feeds',	// IGNORE
+		'cancel' => 'Cancel',	// IGNORE
+		'create' => 'Create',	// IGNORE
+		'demote' => 'Demote',	// IGNORE
+		'disable' => 'Disable',	// IGNORE
+		'empty' => 'Empty',	// IGNORE
+		'enable' => 'Enable',	// IGNORE
+		'export' => 'Export',	// IGNORE
+		'filter' => 'Filter',	// IGNORE
+		'import' => 'Import',	// IGNORE
+		'load_default_shortcuts' => 'Load default shortcuts',	// IGNORE
+		'manage' => 'Manage',	// IGNORE
+		'mark_read' => 'Mark as read',	// IGNORE
+		'promote' => 'Promote',	// IGNORE
+		'purge' => 'Purge',	// IGNORE
+		'remove' => 'Remove',	// IGNORE
+		'rename' => 'Rename',	// IGNORE
+		'see_website' => 'See website',	// IGNORE
+		'submit' => 'Submit',	// IGNORE
+		'truncate' => 'Delete all articles',	// IGNORE
+		'update' => 'Update',	// IGNORE
 	),
 	'auth' => array(
-		'accept_tos' => 'I accept the <a href="%s">Terms of Service</a>.',
-		'email' => 'Email address',
-		'keep_logged_in' => 'Keep me logged in <small>(%s days)</small>',
-		'login' => 'Login',
-		'logout' => 'Logout',
+		'accept_tos' => 'I accept the <a href="%s">Terms of Service</a>.',	// IGNORE
+		'email' => 'Email address',	// IGNORE
+		'keep_logged_in' => 'Keep me logged in <small>(%s days)</small>',	// IGNORE
+		'login' => 'Login',	// IGNORE
+		'logout' => 'Logout',	// IGNORE
 		'password' => array(
-			'_' => 'Password',
-			'format' => '<small>At least 7 characters</small>',
+			'_' => 'Password',	// IGNORE
+			'format' => '<small>At least 7 characters</small>',	// IGNORE
 		),
 		'registration' => array(
-			'_' => 'New account',
-			'ask' => 'Create an account?',
-			'title' => 'Account creation',
+			'_' => 'New account',	// IGNORE
+			'ask' => 'Create an account?',	// IGNORE
+			'title' => 'Account creation',	// IGNORE
 		),
 		'username' => array(
-			'_' => 'Username',
-			'format' => '<small>Maximum 16 alphanumeric characters</small>',
+			'_' => 'Username',	// IGNORE
+			'format' => '<small>Maximum 16 alphanumeric characters</small>',	// IGNORE
 		),
 	),
 	'date' => array(
-		'Apr' => '\\A\\p\\r\\i\\l',
-		'Aug' => '\\A\\u\\g\\u\\s\\t',
-		'Dec' => '\\D\\e\\c\\e\\m\\b\\e\\r',
-		'Feb' => '\\F\\e\\b\\r\\u\\a\\r\\y',
-		'Jan' => '\\J\\a\\n\\u\\a\\r\\y',
-		'Jul' => '\\J\\u\\l\\y',
-		'Jun' => '\\J\\u\\n\\e',
-		'Mar' => '\\M\\a\\r\\c\\h',
-		'May' => '\\M\\a\\y',
-		'Nov' => '\\N\\o\\v\\e\\m\\b\\e\\r',
-		'Oct' => '\\O\\c\\t\\o\\b\\e\\r',
-		'Sep' => '\\S\\e\\p\\t\\e\\m\\b\\e\\r',
-		'apr' => 'Apr.',
-		'april' => 'April',
-		'aug' => 'Aug.',
-		'august' => 'August',
-		'before_yesterday' => 'Before yesterday',
-		'dec' => 'Dec.',
-		'december' => 'December',
-		'feb' => 'Feb.',
-		'february' => 'February',
+		'Apr' => '\\A\\p\\r\\i\\l',	// IGNORE
+		'Aug' => '\\A\\u\\g\\u\\s\\t',	// IGNORE
+		'Dec' => '\\D\\e\\c\\e\\m\\b\\e\\r',	// IGNORE
+		'Feb' => '\\F\\e\\b\\r\\u\\a\\r\\y',	// IGNORE
+		'Jan' => '\\J\\a\\n\\u\\a\\r\\y',	// IGNORE
+		'Jul' => '\\J\\u\\l\\y',	// IGNORE
+		'Jun' => '\\J\\u\\n\\e',	// IGNORE
+		'Mar' => '\\M\\a\\r\\c\\h',	// IGNORE
+		'May' => '\\M\\a\\y',	// IGNORE
+		'Nov' => '\\N\\o\\v\\e\\m\\b\\e\\r',	// IGNORE
+		'Oct' => '\\O\\c\\t\\o\\b\\e\\r',	// IGNORE
+		'Sep' => '\\S\\e\\p\\t\\e\\m\\b\\e\\r',	// IGNORE
+		'apr' => 'Apr.',	// IGNORE
+		'april' => 'April',	// IGNORE
+		'aug' => 'Aug.',	// IGNORE
+		'august' => 'August',	// IGNORE
+		'before_yesterday' => 'Before yesterday',	// IGNORE
+		'dec' => 'Dec.',	// IGNORE
+		'december' => 'December',	// IGNORE
+		'feb' => 'Feb.',	// IGNORE
+		'february' => 'February',	// IGNORE
 		'format_date' => '%s j\\<\\s\\u\\p\\>S\\<\\/\\s\\u\\p\\> Y',
 		'format_date_hour' => '%s j\\<\\s\\u\\p\\>S\\<\\/\\s\\u\\p\\> Y \\a\\t g\\:i a',
-		'fri' => 'Fri',
-		'jan' => 'Jan.',
-		'january' => 'January',
-		'jul' => 'July',
-		'july' => 'July',
-		'jun' => 'June',
-		'june' => 'June',
-		'last_2_year' => 'Last two years',
-		'last_3_month' => 'Last three months',
-		'last_3_year' => 'Last three years',
-		'last_5_year' => 'Last five years',
-		'last_6_month' => 'Last six months',
-		'last_month' => 'Last month',
-		'last_week' => 'Last week',
-		'last_year' => 'Last year',
-		'mar' => 'Mar.',
-		'march' => 'March',
-		'may' => 'May',
-		'may_' => 'May',
-		'mon' => 'Mon',
-		'month' => 'months',
-		'nov' => 'Nov.',
-		'november' => 'November',
-		'oct' => 'Oct.',
-		'october' => 'October',
-		'sat' => 'Sat',
-		'sep' => 'Sept.',
-		'september' => 'September',
-		'sun' => 'Sun',
-		'thu' => 'Thu',
-		'today' => 'Today',
-		'tue' => 'Tue',
-		'wed' => 'Wed',
-		'yesterday' => 'Yesterday',
+		'fri' => 'Fri',	// IGNORE
+		'jan' => 'Jan.',	// IGNORE
+		'january' => 'January',	// IGNORE
+		'jul' => 'July',	// IGNORE
+		'july' => 'July',	// IGNORE
+		'jun' => 'June',	// IGNORE
+		'june' => 'June',	// IGNORE
+		'last_2_year' => 'Last two years',	// IGNORE
+		'last_3_month' => 'Last three months',	// IGNORE
+		'last_3_year' => 'Last three years',	// IGNORE
+		'last_5_year' => 'Last five years',	// IGNORE
+		'last_6_month' => 'Last six months',	// IGNORE
+		'last_month' => 'Last month',	// IGNORE
+		'last_week' => 'Last week',	// IGNORE
+		'last_year' => 'Last year',	// IGNORE
+		'mar' => 'Mar.',	// IGNORE
+		'march' => 'March',	// IGNORE
+		'may' => 'May',	// IGNORE
+		'may_' => 'May',	// IGNORE
+		'mon' => 'Mon',	// IGNORE
+		'month' => 'months',	// IGNORE
+		'nov' => 'Nov.',	// IGNORE
+		'november' => 'November',	// IGNORE
+		'oct' => 'Oct.',	// IGNORE
+		'october' => 'October',	// IGNORE
+		'sat' => 'Sat',	// IGNORE
+		'sep' => 'Sept.',	// IGNORE
+		'september' => 'September',	// IGNORE
+		'sun' => 'Sun',	// IGNORE
+		'thu' => 'Thu',	// IGNORE
+		'today' => 'Today',	// IGNORE
+		'tue' => 'Tue',	// IGNORE
+		'wed' => 'Wed',	// IGNORE
+		'yesterday' => 'Yesterday',	// IGNORE
 	),
-	'dir' => 'ltr',
+	'dir' => 'ltr',	// IGNORE
 	'freshrss' => array(
-		'_' => 'FreshRSS',
-		'about' => 'About FreshRSS',
+		'_' => 'FreshRSS',	// IGNORE
+		'about' => 'About FreshRSS',	// IGNORE
 	),
 	'js' => array(
-		'category_empty' => 'Empty category',
+		'category_empty' => 'Empty category',	// IGNORE
 		'confirm_action' => 'Are you sure you want to perform this action? It cannot be canceled!',
 		'confirm_action_feed_cat' => 'Are you sure you want to perform this action? You will lose related favorites and user queries. It cannot be canceled!',
 		'feedback' => array(
-			'body_new_articles' => 'There are %%d new articles to read on FreshRSS.',
-			'request_failed' => 'A request has failed, it may have been caused by internet connection problems.',
-			'title_new_articles' => 'FreshRSS: new articles!',
+			'body_new_articles' => 'There are %%d new articles to read on FreshRSS.',	// IGNORE
+			'request_failed' => 'A request has failed, it may have been caused by internet connection problems.',	// IGNORE
+			'title_new_articles' => 'FreshRSS: new articles!',	// IGNORE
 		),
-		'new_article' => 'There are new articles available, click to refresh the page.',
-		'should_be_activated' => 'JavaScript must be enabled',
+		'new_article' => 'There are new articles available, click to refresh the page.',	// IGNORE
+		'should_be_activated' => 'JavaScript must be enabled',	// IGNORE
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
-		'about' => 'About',
-		'account' => 'Account',
-		'admin' => 'Administration',
-		'archiving' => 'Archiving',
-		'authentication' => 'Authentication',
-		'check_install' => 'Installation check',
-		'configuration' => 'Configuration',
-		'display' => 'Display',
-		'extensions' => 'Extensions',
-		'logs' => 'Logs',
-		'queries' => 'User queries',
-		'reading' => 'Reading',
-		'search' => 'Search words or #tags',
-		'sharing' => 'Sharing',
-		'shortcuts' => 'Shortcuts',
-		'stats' => 'Statistics',
-		'system' => 'System configuration',
-		'update' => 'Update',
-		'user_management' => 'Manage users',
-		'user_profile' => 'Profile',
+		'about' => 'About',	// IGNORE
+		'account' => 'Account',	// IGNORE
+		'admin' => 'Administration',	// IGNORE
+		'archiving' => 'Archiving',	// IGNORE
+		'authentication' => 'Authentication',	// IGNORE
+		'check_install' => 'Installation check',	// IGNORE
+		'configuration' => 'Configuration',	// IGNORE
+		'display' => 'Display',	// IGNORE
+		'extensions' => 'Extensions',	// IGNORE
+		'logs' => 'Logs',	// IGNORE
+		'queries' => 'User queries',	// IGNORE
+		'reading' => 'Reading',	// IGNORE
+		'search' => 'Search words or #tags',	// IGNORE
+		'sharing' => 'Sharing',	// IGNORE
+		'shortcuts' => 'Shortcuts',	// IGNORE
+		'stats' => 'Statistics',	// IGNORE
+		'system' => 'System configuration',	// IGNORE
+		'update' => 'Update',	// IGNORE
+		'user_management' => 'Manage users',	// IGNORE
+		'user_profile' => 'Profile',	// IGNORE
 	),
 	'pagination' => array(
-		'first' => 'First',
-		'last' => 'Last',
-		'load_more' => 'Load more articles',
-		'mark_all_read' => 'Mark all as read',
-		'next' => 'Next',
-		'nothing_to_load' => 'There are no more articles',
-		'previous' => 'Previous',
+		'first' => 'First',	// IGNORE
+		'last' => 'Last',	// IGNORE
+		'load_more' => 'Load more articles',	// IGNORE
+		'mark_all_read' => 'Mark all as read',	// IGNORE
+		'next' => 'Next',	// IGNORE
+		'nothing_to_load' => 'There are no more articles',	// IGNORE
+		'previous' => 'Previous',	// IGNORE
 	),
 	'period' => array(
-		'days' => 'days',
-		'hours' => 'hours',
-		'months' => 'months',
-		'weeks' => 'weeks',
-		'years' => 'years',
+		'days' => 'days',	// IGNORE
+		'hours' => 'hours',	// IGNORE
+		'months' => 'months',	// IGNORE
+		'weeks' => 'weeks',	// IGNORE
+		'years' => 'years',	// IGNORE
 	),
 	'share' => array(
-		'Known' => 'Known based sites',
-		'blogotext' => 'Blogotext',
-		'clipboard' => 'Clipboard',
-		'diaspora' => 'Diaspora*',
-		'email' => 'Email',
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
-		'print' => 'Print',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'Known' => 'Known based sites',	// IGNORE
+		'blogotext' => 'Blogotext',	// IGNORE
+		'clipboard' => 'Clipboard',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
+		'email' => 'Email',	// IGNORE
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
+		'print' => 'Print',	// IGNORE
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
-		'attention' => 'Warning!',
-		'blank_to_disable' => 'Leave blank to disable',
-		'by_author' => 'By:',
-		'by_default' => 'By default',
-		'damn' => 'Blast!',
-		'default_category' => 'Uncategorized',
-		'no' => 'No',
-		'not_applicable' => 'Not available',
-		'ok' => 'Okay!',
-		'or' => 'or',
-		'yes' => 'Yes',
+		'attention' => 'Warning!',	// IGNORE
+		'blank_to_disable' => 'Leave blank to disable',	// IGNORE
+		'by_author' => 'By:',	// IGNORE
+		'by_default' => 'By default',	// IGNORE
+		'damn' => 'Blast!',	// IGNORE
+		'default_category' => 'Uncategorized',	// IGNORE
+		'no' => 'No',	// IGNORE
+		'not_applicable' => 'Not available',	// IGNORE
+		'ok' => 'Okay!',	// IGNORE
+		'or' => 'or',	// IGNORE
+		'yes' => 'Yes',	// IGNORE
 	),
 );

+ 55 - 45
app/i18n/en-us/index.php

@@ -1,65 +1,75 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
-		'_' => 'About',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
-		'bugs_reports' => 'Bug reports',
-		'credits' => 'Credits',
-		'credits_content' => 'Some design elements come from <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> although FreshRSS doesn’t use this framework. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Icons</a> come from <a href="https://www.gnome.org/">GNOME project</a>. <em>Open Sans</em> font police has been created by <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS is based on <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, a PHP framework.',
-		'freshrss_description' => 'FreshRSS is a RSS feeds aggregator to self-host like <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> or <a href="https://github.com/LeedRSS/Leed">Leed</a>. It is light and easy to take in hand while being powerful and configurable tool.',
-		'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">on Github</a>',
-		'license' => 'License',
-		'project_website' => 'Project website',
-		'title' => 'About',
-		'version' => 'Version',
+		'_' => 'About',	// IGNORE
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
+		'bugs_reports' => 'Bug reports',	// IGNORE
+		'credits' => 'Credits',	// IGNORE
+		'credits_content' => 'Some design elements come from <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> although FreshRSS doesn’t use this framework. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Icons</a> come from <a href="https://www.gnome.org/">GNOME project</a>. <em>Open Sans</em> font police has been created by <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS is based on <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, a PHP framework.',	// IGNORE
+		'freshrss_description' => 'FreshRSS is a RSS feeds aggregator to self-host like <a href="http://tontof.net/kriss/feed/">Kriss Feed</a> or <a href="https://github.com/LeedRSS/Leed">Leed</a>. It is light and easy to take in hand while being powerful and configurable tool.',	// IGNORE
+		'github' => '<a href="https://github.com/FreshRSS/FreshRSS/issues">on Github</a>',	// IGNORE
+		'license' => 'License',	// IGNORE
+		'project_website' => 'Project website',	// IGNORE
+		'title' => 'About',	// IGNORE
+		'version' => 'Version',	// IGNORE
 	),
 	'feed' => array(
-		'add' => 'Please add some feeds.',
-		'empty' => 'There are no articles to show.',
-		'rss_of' => 'RSS feed of %s',
-		'title' => 'Main stream',
+		'add' => 'Please add some feeds.',	// IGNORE
+		'empty' => 'There are no articles to show.',	// IGNORE
+		'rss_of' => 'RSS feed of %s',	// IGNORE
+		'title' => 'Main stream',	// IGNORE
 		'title_fav' => 'Favorites',
-		'title_global' => 'Global view',
+		'title_global' => 'Global view',	// IGNORE
 	),
 	'log' => array(
-		'_' => 'Logs',
-		'clear' => 'Clear the logs',
-		'empty' => 'Log file is empty',
-		'title' => 'Logs',
+		'_' => 'Logs',	// IGNORE
+		'clear' => 'Clear the logs',	// IGNORE
+		'empty' => 'Log file is empty',	// IGNORE
+		'title' => 'Logs',	// IGNORE
 	),
 	'menu' => array(
-		'about' => 'About FreshRSS',
-		'before_one_day' => 'Older than one day',
-		'before_one_week' => 'Older than one week',
-		'bookmark_query' => 'Bookmark current query',
+		'about' => 'About FreshRSS',	// IGNORE
+		'before_one_day' => 'Older than one day',	// IGNORE
+		'before_one_week' => 'Older than one week',	// IGNORE
+		'bookmark_query' => 'Bookmark current query',	// IGNORE
 		'favorites' => 'Favorites (%s)',
-		'global_view' => 'Global view',
-		'main_stream' => 'Main stream',
-		'mark_all_read' => 'Mark all as read',
-		'mark_cat_read' => 'Mark category as read',
-		'mark_feed_read' => 'Mark feed as read',
-		'mark_selection_unread' => 'Mark selection as unread',
-		'newer_first' => 'Newer first',
+		'global_view' => 'Global view',	// IGNORE
+		'main_stream' => 'Main stream',	// IGNORE
+		'mark_all_read' => 'Mark all as read',	// IGNORE
+		'mark_cat_read' => 'Mark category as read',	// IGNORE
+		'mark_feed_read' => 'Mark feed as read',	// IGNORE
+		'mark_selection_unread' => 'Mark selection as unread',	// IGNORE
+		'newer_first' => 'Newer first',	// IGNORE
 		'non-starred' => 'Show non-favorites',
-		'normal_view' => 'Normal view',
-		'older_first' => 'Oldest first',
-		'queries' => 'User queries',
-		'read' => 'Show read',
-		'reader_view' => 'Reading view',
-		'rss_view' => 'RSS feed',
-		'search_short' => 'Search',
+		'normal_view' => 'Normal view',	// IGNORE
+		'older_first' => 'Oldest first',	// IGNORE
+		'queries' => 'User queries',	// IGNORE
+		'read' => 'Show read',	// IGNORE
+		'reader_view' => 'Reading view',	// IGNORE
+		'rss_view' => 'RSS feed',	// IGNORE
+		'search_short' => 'Search',	// IGNORE
 		'starred' => 'Show favorites',
-		'stats' => 'Statistics',
-		'subscription' => 'Subscription management',
-		'tags' => 'My labels',
-		'unread' => 'Show unread',
+		'stats' => 'Statistics',	// IGNORE
+		'subscription' => 'Subscription management',	// IGNORE
+		'tags' => 'My labels',	// IGNORE
+		'unread' => 'Show unread',	// IGNORE
 	),
-	'share' => 'Share',
+	'share' => 'Share',	// IGNORE
 	'tag' => array(
-		'related' => 'Article tags',
+		'related' => 'Article tags',	// IGNORE
 	),
 	'tos' => array(
-		'title' => 'Terms of Service',
+		'title' => 'Terms of Service',	// IGNORE
 	),
 );

+ 79 - 69
app/i18n/en-us/install.php

@@ -1,123 +1,133 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
-		'finish' => 'Complete installation',
-		'fix_errors_before' => 'Please all fix errors before continuing to the next step.',
-		'keep_install' => 'Keep previous configuration',
-		'next_step' => 'Go to the next step',
-		'reinstall' => 'Reinstall FreshRSS',
+		'finish' => 'Complete installation',	// IGNORE
+		'fix_errors_before' => 'Please all fix errors before continuing to the next step.',	// IGNORE
+		'keep_install' => 'Keep previous configuration',	// IGNORE
+		'next_step' => 'Go to the next step',	// IGNORE
+		'reinstall' => 'Reinstall FreshRSS',	// IGNORE
 	),
 	'auth' => array(
-		'form' => 'Web form (traditional, requires JavaScript)',
-		'http' => 'HTTP (for advanced users with HTTPS)',
-		'none' => 'None (dangerous)',
-		'password_form' => 'Password<br /><small>(for the Web-form login method)</small>',
-		'password_format' => 'At least 7 characters',
-		'type' => 'Authentication method',
+		'form' => 'Web form (traditional, requires JavaScript)',	// IGNORE
+		'http' => 'HTTP (for advanced users with HTTPS)',	// IGNORE
+		'none' => 'None (dangerous)',	// IGNORE
+		'password_form' => 'Password<br /><small>(for the Web-form login method)</small>',	// IGNORE
+		'password_format' => 'At least 7 characters',	// IGNORE
+		'type' => 'Authentication method',	// IGNORE
 	),
 	'bdd' => array(
-		'_' => 'Database',
+		'_' => 'Database',	// IGNORE
 		'conf' => array(
-			'_' => 'Database configuration',
-			'ko' => 'Verify your database configuration.',
-			'ok' => 'Database configuration has been saved.',
-		),
-		'host' => 'Host',
-		'password' => 'Database password',
-		'prefix' => 'Table prefix',
-		'type' => 'Type of database',
-		'username' => 'Database username',
+			'_' => 'Database configuration',	// IGNORE
+			'ko' => 'Verify your database configuration.',	// IGNORE
+			'ok' => 'Database configuration has been saved.',	// IGNORE
+		),
+		'host' => 'Host',	// IGNORE
+		'password' => 'Database password',	// IGNORE
+		'prefix' => 'Table prefix',	// IGNORE
+		'type' => 'Type of database',	// IGNORE
+		'username' => 'Database username',	// IGNORE
 	),
 	'check' => array(
-		'_' => 'Checks',
-		'already_installed' => 'We have detected that FreshRSS is already installed!',
+		'_' => 'Checks',	// IGNORE
+		'already_installed' => 'We have detected that FreshRSS is already installed!',	// IGNORE
 		'cache' => array(
 			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',
-			'ok' => 'Permissions on the cache directory are good.',
+			'ok' => 'Permissions on the cache directory are good.',	// IGNORE
 		),
 		'ctype' => array(
-			'nok' => 'Cannot find the required library for character type checking (php-ctype).',
-			'ok' => 'You have the required library for character type checking (ctype).',
+			'nok' => 'Cannot find the required library for character type checking (php-ctype).',	// IGNORE
+			'ok' => 'You have the required library for character type checking (ctype).',	// IGNORE
 		),
 		'curl' => array(
-			'nok' => 'Cannot find the cURL library (php-curl package).',
-			'ok' => 'You have the cURL library.',
+			'nok' => 'Cannot find the cURL library (php-curl package).',	// IGNORE
+			'ok' => 'You have the cURL library.',	// IGNORE
 		),
 		'data' => array(
 			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',
-			'ok' => 'Permissions on the data directory are good.',
+			'ok' => 'Permissions on the data directory are good.',	// IGNORE
 		),
 		'dom' => array(
-			'nok' => 'Cannot find the required library to browse the DOM.',
-			'ok' => 'You have the required library to browse the DOM.',
+			'nok' => 'Cannot find the required library to browse the DOM.',	// IGNORE
+			'ok' => 'You have the required library to browse the DOM.',	// IGNORE
 		),
 		'favicons' => array(
 			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',
-			'ok' => 'Permissions on the favicons directory are good.',
+			'ok' => 'Permissions on the favicons directory are good.',	// IGNORE
 		),
 		'fileinfo' => array(
-			'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',
-			'ok' => 'You have the fileinfo library.',
+			'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',	// IGNORE
+			'ok' => 'You have the fileinfo library.',	// IGNORE
 		),
 		'json' => array(
-			'nok' => 'Cannot find the recommended library to parse JSON.',
-			'ok' => 'You have the recommended library to parse JSON.',
+			'nok' => 'Cannot find the recommended library to parse JSON.',	// IGNORE
+			'ok' => 'You have the recommended library to parse JSON.',	// IGNORE
 		),
 		'mbstring' => array(
-			'nok' => 'Cannot find the recommended library mbstring for Unicode.',
-			'ok' => 'You have the recommended library mbstring for Unicode.',
+			'nok' => 'Cannot find the recommended library mbstring for Unicode.',	// IGNORE
+			'ok' => 'You have the recommended library mbstring for Unicode.',	// IGNORE
 		),
 		'pcre' => array(
-			'nok' => 'Cannot find the required library for regular expressions (php-pcre).',
-			'ok' => 'You have the required library for regular expressions (PCRE).',
+			'nok' => 'Cannot find the required library for regular expressions (php-pcre).',	// IGNORE
+			'ok' => 'You have the required library for regular expressions (PCRE).',	// IGNORE
 		),
 		'pdo' => array(
-			'nok' => 'Cannot find PDO or one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',
-			'ok' => 'You have PDO and at least one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',
+			'nok' => 'Cannot find PDO or one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',	// IGNORE
+			'ok' => 'You have PDO and at least one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',	// IGNORE
 		),
 		'php' => array(
-			'nok' => 'Your PHP version is %s, but FreshRSS requires at least version %s.',
-			'ok' => 'Your PHP version, %s, is compatible with FreshRSS.',
+			'nok' => 'Your PHP version is %s, but FreshRSS requires at least version %s.',	// IGNORE
+			'ok' => 'Your PHP version, %s, is compatible with FreshRSS.',	// IGNORE
 		),
-		'reload' => 'Check again',
+		'reload' => 'Check again',	// IGNORE
 		'tmp' => array(
-			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',
-			'ok' => 'Permissions on the temp directory are good.',
+			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',	// IGNORE
+			'ok' => 'Permissions on the temp directory are good.',	// IGNORE
 		),
-		'unknown_process_username' => 'unknown',
+		'unknown_process_username' => 'unknown',	// IGNORE
 		'users' => array(
-			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',
-			'ok' => 'Permissions on the users directory are good.',
+			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',	// IGNORE
+			'ok' => 'Permissions on the users directory are good.',	// IGNORE
 		),
 		'xml' => array(
-			'nok' => 'Cannot find the required library to parse XML.',
-			'ok' => 'You have the required library to parse XML.',
+			'nok' => 'Cannot find the required library to parse XML.',	// IGNORE
+			'ok' => 'You have the required library to parse XML.',	// IGNORE
 		),
 	),
 	'conf' => array(
-		'_' => 'General configuration',
-		'ok' => 'General configuration has been saved.',
+		'_' => 'General configuration',	// IGNORE
+		'ok' => 'General configuration has been saved.',	// IGNORE
 	),
-	'congratulations' => 'Congratulations!',
-	'default_user' => 'Username of the default user <small>(maximum 16 alphanumeric characters)</small>',
-	'fix_errors_before' => 'Please fix errors before continuing to the next step.',
-	'javascript_is_better' => 'FreshRSS is more pleasant with JavaScript enabled',
+	'congratulations' => 'Congratulations!',	// IGNORE
+	'default_user' => 'Username of the default user <small>(maximum 16 alphanumeric characters)</small>',	// IGNORE
+	'fix_errors_before' => 'Please fix errors before continuing to the next step.',	// IGNORE
+	'javascript_is_better' => 'FreshRSS is more pleasant with JavaScript enabled',	// IGNORE
 	'js' => array(
-		'confirm_reinstall' => 'You will lose your previous configuration by reinstalling FreshRSS. Are you sure you want to continue?',
+		'confirm_reinstall' => 'You will lose your previous configuration by reinstalling FreshRSS. Are you sure you want to continue?',	// IGNORE
 	),
 	'language' => array(
-		'_' => 'Language',
-		'choose' => 'Choose a language for FreshRSS',
-		'defined' => 'Language has been defined.',
+		'_' => 'Language',	// IGNORE
+		'choose' => 'Choose a language for FreshRSS',	// IGNORE
+		'defined' => 'Language has been defined.',	// IGNORE
 	),
-	'missing_applied_migrations' => 'Something went wrong; you should create an empty file <em>%s</em> manually.',
-	'ok' => 'The installation process was successful.',
+	'missing_applied_migrations' => 'Something went wrong; you should create an empty file <em>%s</em> manually.',	// IGNORE
+	'ok' => 'The installation process was successful.',	// IGNORE
 	'session' => array(
-		'nok' => 'The web server seems to be incorrectly configured for cookies required for PHP sessions!',
+		'nok' => 'The web server seems to be incorrectly configured for cookies required for PHP sessions!',	// IGNORE
 	),
-	'step' => 'step %d',
-	'steps' => 'Steps',
-	'this_is_the_end' => 'This is the end',
-	'title' => 'Installation · FreshRSS',
+	'step' => 'step %d',	// IGNORE
+	'steps' => 'Steps',	// IGNORE
+	'this_is_the_end' => 'This is the end',	// IGNORE
+	'title' => 'Installation · FreshRSS',	// IGNORE
 );

+ 107 - 97
app/i18n/en-us/sub.php

@@ -1,138 +1,148 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
-		'documentation' => 'Copy the following URL to use it within an external tool.',
-		'title' => 'API',
+		'documentation' => 'Copy the following URL to use it within an external tool.',	// IGNORE
+		'title' => 'API',	// IGNORE
 	),
 	'bookmarklet' => array(
-		'documentation' => 'Drag this button to your bookmarks toolbar or right-click it and choose "Bookmark This Link". Then click the "Subscribe" button in any page you want to subscribe to.',
-		'label' => 'Subscribe',
-		'title' => 'Bookmarklet',
+		'documentation' => 'Drag this button to your bookmarks toolbar or right-click it and choose "Bookmark This Link". Then click the "Subscribe" button in any page you want to subscribe to.',	// IGNORE
+		'label' => 'Subscribe',	// IGNORE
+		'title' => 'Bookmarklet',	// IGNORE
 	),
 	'category' => array(
-		'_' => 'Category',
-		'add' => 'Add a category',
-		'archiving' => 'Archiving',
-		'empty' => 'Empty category',
-		'information' => 'Information',
-		'position' => 'Display position',
-		'position_help' => 'To control category sort order',
-		'title' => 'Title',
+		'_' => 'Category',	// IGNORE
+		'add' => 'Add a category',	// IGNORE
+		'archiving' => 'Archiving',	// IGNORE
+		'empty' => 'Empty category',	// IGNORE
+		'information' => 'Information',	// IGNORE
+		'position' => 'Display position',	// IGNORE
+		'position_help' => 'To control category sort order',	// IGNORE
+		'title' => 'Title',	// IGNORE
 	),
 	'feed' => array(
-		'add' => 'Add a RSS feed',
-		'advanced' => 'Advanced',
-		'archiving' => 'Archiving',
+		'add' => 'Add a RSS feed',	// IGNORE
+		'advanced' => 'Advanced',	// IGNORE
+		'archiving' => 'Archiving',	// IGNORE
 		'auth' => array(
-			'configuration' => 'Login',
-			'help' => 'Allows access to HTTP protected RSS feeds',
-			'http' => 'HTTP Authentication',
-			'password' => 'HTTP password',
-			'username' => 'HTTP username',
+			'configuration' => 'Login',	// IGNORE
+			'help' => 'Allows access to HTTP protected RSS feeds',	// IGNORE
+			'http' => 'HTTP Authentication',	// IGNORE
+			'password' => 'HTTP password',	// IGNORE
+			'username' => 'HTTP username',	// IGNORE
 		),
-		'clear_cache' => 'Always clear cache',
+		'clear_cache' => 'Always clear cache',	// IGNORE
 		'content_action' => array(
-			'_' => 'Content action when fetching the article content',
-			'append' => 'Add after existing content',
-			'prepend' => 'Add before existing content',
-			'replace' => 'Replace existing content',
+			'_' => 'Content action when fetching the article content',	// IGNORE
+			'append' => 'Add after existing content',	// IGNORE
+			'prepend' => 'Add before existing content',	// IGNORE
+			'replace' => 'Replace existing content',	// IGNORE
 		),
-		'css_cookie' => 'Use Cookies when fetching the article content',
-		'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
-		'css_help' => 'Retrieves truncated RSS feeds (caution, requires more time!)',
-		'css_path' => 'Article CSS selector on original website',
-		'description' => 'Description',
-		'empty' => 'This feed is empty. Please verify that it is still maintained.',
-		'error' => 'This feed has encountered a problem. Please verify that it is always reachable then update it.',
+		'css_cookie' => 'Use Cookies when fetching the article content',	// IGNORE
+		'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',	// IGNORE
+		'css_help' => 'Retrieves truncated RSS feeds (caution, requires more time!)',	// IGNORE
+		'css_path' => 'Article CSS selector on original website',	// IGNORE
+		'description' => 'Description',	// IGNORE
+		'empty' => 'This feed is empty. Please verify that it is still maintained.',	// IGNORE
+		'error' => 'This feed has encountered a problem. Please verify that it is always reachable then update it.',	// IGNORE
 		'filteractions' => array(
-			'_' => 'Filter actions',
-			'help' => 'Write one search filter per line.',
+			'_' => 'Filter actions',	// IGNORE
+			'help' => 'Write one search filter per line.',	// IGNORE
 		),
-		'information' => 'Information',
-		'keep_min' => 'Minimum number of articles to keep',
+		'information' => 'Information',	// IGNORE
+		'keep_min' => 'Minimum number of articles to keep',	// IGNORE
 		'maintenance' => array(
-			'clear_cache' => 'Clear cache',
-			'clear_cache_help' => 'Clear the cache for this feed.',
-			'reload_articles' => 'Reload articles',
-			'reload_articles_help' => 'Reload articles and fetch complete content if a selector is defined.',
-			'title' => 'Maintenance',
+			'clear_cache' => 'Clear cache',	// IGNORE
+			'clear_cache_help' => 'Clear the cache for this feed.',	// IGNORE
+			'reload_articles' => 'Reload articles',	// IGNORE
+			'reload_articles_help' => 'Reload articles and fetch complete content if a selector is defined.',	// IGNORE
+			'title' => 'Maintenance',	// IGNORE
 		),
-		'moved_category_deleted' => 'When you delete a category, its feeds are automatically classified under <em>%s</em>.',
-		'mute' => 'mute',
-		'no_selected' => 'No feed selected.',
-		'number_entries' => '%d articles',
+		'moved_category_deleted' => 'When you delete a category, its feeds are automatically classified under <em>%s</em>.',	// IGNORE
+		'mute' => 'mute',	// IGNORE
+		'no_selected' => 'No feed selected.',	// IGNORE
+		'number_entries' => '%d articles',	// IGNORE
 		'priority' => array(
-			'_' => 'Visibility',
-			'archived' => 'Do not show (archived)',
-			'main_stream' => 'Show in main stream',
-			'normal' => 'Show in its category',
+			'_' => 'Visibility',	// IGNORE
+			'archived' => 'Do not show (archived)',	// IGNORE
+			'main_stream' => 'Show in main stream',	// IGNORE
+			'normal' => 'Show in its category',	// IGNORE
 		),
-		'proxy' => 'Set a proxy for fetching this feed',
-		'proxy_help' => 'Select a protocol (e.g: SOCKS5) and enter the proxy address (e.g: <kbd>127.0.0.1:1080</kbd>)',
+		'proxy' => 'Set a proxy for fetching this feed',	// IGNORE
+		'proxy_help' => 'Select a protocol (e.g: SOCKS5) and enter the proxy address (e.g: <kbd>127.0.0.1:1080</kbd>)',	// IGNORE
 		'selector_preview' => array(
-			'show_raw' => 'Show source code',
-			'show_rendered' => 'Show content',
+			'show_raw' => 'Show source code',	// IGNORE
+			'show_rendered' => 'Show content',	// IGNORE
 		),
 		'show' => array(
-			'all' => 'Show all feeds',
-			'error' => 'Show only feeds with errors',
+			'all' => 'Show all feeds',	// IGNORE
+			'error' => 'Show only feeds with errors',	// IGNORE
 		),
 		'showing' => array(
-			'error' => 'Showing only feeds with errors',
+			'error' => 'Showing only feeds with errors',	// IGNORE
 		),
-		'ssl_verify' => 'Verify SSL security',
-		'stats' => 'Statistics',
-		'think_to_add' => 'You may add some feeds.',
-		'timeout' => 'Timeout in seconds',
-		'title' => 'Title',
-		'title_add' => 'Add an RSS feed',
-		'ttl' => 'Do not automatically refresh more often than',
-		'url' => 'Feed URL',
-		'useragent' => 'Set the user agent for fetching this feed',
-		'useragent_help' => 'Example: <kbd>Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0)</kbd>',
-		'validator' => 'Check the validity of the feed',
-		'website' => 'Website URL',
-		'websub' => 'Instant notification with WebSub',
+		'ssl_verify' => 'Verify SSL security',	// IGNORE
+		'stats' => 'Statistics',	// IGNORE
+		'think_to_add' => 'You may add some feeds.',	// IGNORE
+		'timeout' => 'Timeout in seconds',	// IGNORE
+		'title' => 'Title',	// IGNORE
+		'title_add' => 'Add an RSS feed',	// IGNORE
+		'ttl' => 'Do not automatically refresh more often than',	// IGNORE
+		'url' => 'Feed URL',	// IGNORE
+		'useragent' => 'Set the user agent for fetching this feed',	// IGNORE
+		'useragent_help' => 'Example: <kbd>Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0)</kbd>',	// IGNORE
+		'validator' => 'Check the validity of the feed',	// IGNORE
+		'website' => 'Website URL',	// IGNORE
+		'websub' => 'Instant notification with WebSub',	// IGNORE
 	),
 	'import_export' => array(
-		'export' => 'Export',
+		'export' => 'Export',	// IGNORE
 		'export_labelled' => 'Export your labeled articles',
-		'export_opml' => 'Export list of feeds (OPML)',
+		'export_opml' => 'Export list of feeds (OPML)',	// IGNORE
 		'export_starred' => 'Export your favorites',
-		'feed_list' => 'List of %s articles',
-		'file_to_import' => 'File to import<br />(OPML, JSON or ZIP)',
-		'file_to_import_no_zip' => 'File to import<br />(OPML or JSON)',
-		'import' => 'Import',
+		'feed_list' => 'List of %s articles',	// IGNORE
+		'file_to_import' => 'File to import<br />(OPML, JSON or ZIP)',	// IGNORE
+		'file_to_import_no_zip' => 'File to import<br />(OPML or JSON)',	// IGNORE
+		'import' => 'Import',	// IGNORE
 		'starred_list' => 'List of favorite articles',
-		'title' => 'Import / export',
+		'title' => 'Import / export',	// IGNORE
 	),
 	'menu' => array(
-		'add' => 'Add a feed or category',
-		'import_export' => 'Import / export',
-		'label_management' => 'Label management',
+		'add' => 'Add a feed or category',	// IGNORE
+		'import_export' => 'Import / export',	// IGNORE
+		'label_management' => 'Label management',	// IGNORE
 		'stats' => array(
-			'idle' => 'Idle feeds',
-			'main' => 'Main statistics',
-			'repartition' => 'Articles repartition',
+			'idle' => 'Idle feeds',	// IGNORE
+			'main' => 'Main statistics',	// IGNORE
+			'repartition' => 'Articles repartition',	// IGNORE
 		),
-		'subscription_management' => 'Subscription management',
-		'subscription_tools' => 'Subscription tools',
+		'subscription_management' => 'Subscription management',	// IGNORE
+		'subscription_tools' => 'Subscription tools',	// IGNORE
 	),
 	'tag' => array(
-		'name' => 'Name',
-		'new_name' => 'New name',
-		'old_name' => 'Old name',
+		'name' => 'Name',	// IGNORE
+		'new_name' => 'New name',	// IGNORE
+		'old_name' => 'Old name',	// IGNORE
 	),
 	'title' => array(
-		'_' => 'Subscription management',
-		'add' => 'Add a feed or category',
-		'add_category' => 'Add a category',
-		'add_feed' => 'Add a feed',
-		'add_label' => 'Add a label',
-		'delete_label' => 'Delete a label',
-		'feed_management' => 'RSS feeds management',
-		'rename_label' => 'Rename a label',
-		'subscription_tools' => 'Subscription tools',
+		'_' => 'Subscription management',	// IGNORE
+		'add' => 'Add a feed or category',	// IGNORE
+		'add_category' => 'Add a category',	// IGNORE
+		'add_feed' => 'Add a feed',	// IGNORE
+		'add_label' => 'Add a label',	// IGNORE
+		'delete_label' => 'Delete a label',	// IGNORE
+		'feed_management' => 'RSS feeds management',	// IGNORE
+		'rename_label' => 'Rename a label',	// IGNORE
+		'subscription_tools' => 'Subscription tools',	// IGNORE
 	),
 );

+ 30 - 20
app/i18n/en-us/user.php

@@ -1,44 +1,54 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(
-			'invalid' => 'This email address is invalid.',
-			'required' => 'An email address is required.',
+			'invalid' => 'This email address is invalid.',	// IGNORE
+			'required' => 'An email address is required.',	// IGNORE
 		),
 		'validation' => array(
-			'change_email' => 'You can change your email address <a href="%s">on the profile page</a>.',
-			'email_sent_to' => 'We sent you an email at <strong>%s</strong>. Please follow its instructions to validate your address.',
+			'change_email' => 'You can change your email address <a href="%s">on the profile page</a>.',	// IGNORE
+			'email_sent_to' => 'We sent you an email at <strong>%s</strong>. Please follow its instructions to validate your address.',	// IGNORE
 			'feedback' => array(
-				'email_failed' => 'We couldn’t send you an email because of a server configuration error.',
-				'email_sent' => 'An email has been sent to your address.',
-				'error' => 'Email address validation failed.',
-				'ok' => 'This email address has been validated.',
-				'unnecessary' => 'This email address was already validated.',
-				'wrong_token' => 'This email address failed to be validated due to a wrong token.',
+				'email_failed' => 'We couldn’t send you an email because of a server configuration error.',	// IGNORE
+				'email_sent' => 'An email has been sent to your address.',	// IGNORE
+				'error' => 'Email address validation failed.',	// IGNORE
+				'ok' => 'This email address has been validated.',	// IGNORE
+				'unnecessary' => 'This email address was already validated.',	// IGNORE
+				'wrong_token' => 'This email address failed to be validated due to a wrong token.',	// IGNORE
 			),
-			'need_to' => 'You need to validate your email address before being able to use %s.',
-			'resend_email' => 'Resend the email',
-			'title' => 'Email address validation',
+			'need_to' => 'You need to validate your email address before being able to use %s.',	// IGNORE
+			'resend_email' => 'Resend the email',	// IGNORE
+			'title' => 'Email address validation',	// IGNORE
 		),
 	),
 	'mailer' => array(
 		'email_need_validation' => array(
-			'body' => 'You’ve just registered on %s, but you still need to validate your email address. For that, just follow the link:',
-			'title' => 'You need to validate your account',
-			'welcome' => 'Welcome %s,',
+			'body' => 'You’ve just registered on %s, but you still need to validate your email address. For that, just follow the link:',	// IGNORE
+			'title' => 'You need to validate your account',	// IGNORE
+			'welcome' => 'Welcome %s,',	// IGNORE
 		),
 	),
 	'password' => array(
-		'invalid' => 'The password is invalid.',
+		'invalid' => 'The password is invalid.',	// IGNORE
 	),
 	'tos' => array(
 		'feedback' => array(
-			'invalid' => 'You must accept the Terms of Service to be able to register.',
+			'invalid' => 'You must accept the Terms of Service to be able to register.',	// IGNORE
 		),
 	),
 	'username' => array(
-		'invalid' => 'This username is invalid.',
-		'taken' => 'This username, %s, is taken.',
+		'invalid' => 'This username is invalid.',	// IGNORE
+		'taken' => 'This username, %s, is taken.',	// IGNORE
 	),
 );

+ 10 - 0
app/i18n/en/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => 'Allow anonymous reading of the default user\'s articles (%s)',

+ 10 - 0
app/i18n/en/conf.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'Archiving',

+ 10 - 0
app/i18n/en/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'You don’t have permission to access this page',

+ 10 - 0
app/i18n/en/gen.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'Update feeds',

+ 10 - 0
app/i18n/en/index.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => 'About',

+ 10 - 0
app/i18n/en/install.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => 'Complete installation',

+ 10 - 0
app/i18n/en/sub.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
 		'documentation' => 'Copy the following URL to use it within an external tool.',

+ 10 - 0
app/i18n/en/user.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(

+ 12 - 2
app/i18n/es/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => 'Permitir la lectura anónima de los artículos del usuario por defecto (%s)',
@@ -141,7 +151,7 @@ return array(
 		'repartition' => 'Reprto de artículos',
 		'status_favorites' => 'Favoritos',
 		'status_read' => 'Leídos',
-		'status_total' => 'Total',
+		'status_total' => 'Total',	// IGNORE
 		'status_unread' => 'Pendientes',
 		'title' => 'Estadísticas',
 		'top_feed' => 'Las 10 fuentes más activas',
@@ -179,7 +189,7 @@ return array(
 		'database_size' => 'Tamaño de la base de datos',
 		'email' => 'Dirección de correo electrónico',
 		'enabled' => 'Permitido',
-		'feed_count' => 'Feeds',
+		'feed_count' => 'Feeds',	// IGNORE
 		'is_admin' => 'Es admin',
 		'language' => 'Idioma',
 		'last_user_activity' => 'Última actividad del usuario',

+ 18 - 8
app/i18n/es/conf.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'Archivo',
@@ -163,20 +173,20 @@ return array(
 	'sharing' => array(
 		'_' => 'Compartir',
 		'add' => 'Agregar un método de uso compartido',
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
-		'email' => 'Email',
-		'facebook' => 'Facebook',
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
+		'email' => 'Email',	// TODO
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => 'Más información',
 		'print' => 'Imprimir',
-		'raindrop' => 'Raindrop.io',
+		'raindrop' => 'Raindrop.io',	// IGNORE
 		'remove' => 'Quitar método de uso compartido',
-		'shaarli' => 'Shaarli',
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => 'Compartir nombre a mostrar',
 		'share_url' => 'Compatir URL a usar',
 		'title' => 'Compartir',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => 'Atajos de teclado',

+ 10 - 0
app/i18n/es/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'No dispones de permiso para acceder a esta página',

+ 50 - 40
app/i18n/es/gen.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'Actualizar fuentes',
@@ -69,8 +79,8 @@ return array(
 		'december' => 'diciembre',
 		'feb' => 'feb',
 		'february' => 'febrero',
-		'format_date' => 'j %s Y',
-		'format_date_hour' => 'j %s Y \\a\\t H\\:i',
+		'format_date' => 'j %s Y',	// IGNORE
+		'format_date_hour' => 'j %s Y \\a\\t H\\:i',	// IGNORE
 		'fri' => 'Vie',
 		'jan' => 'ene',
 		'january' => 'ene',
@@ -106,9 +116,9 @@ return array(
 		'wed' => 'Mie',
 		'yesterday' => 'Ayer',
 	),
-	'dir' => 'ltr',
+	'dir' => 'ltr',	// IGNORE
 	'freshrss' => array(
-		'_' => 'FreshRSS',
+		'_' => 'FreshRSS',	// IGNORE
 		'about' => 'Acerca de FreshRSS',
 	),
 	'js' => array(
@@ -124,24 +134,24 @@ return array(
 		'should_be_activated' => 'JavaScript debe estar activado',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'Acerca de',
@@ -183,25 +193,25 @@ return array(
 	),
 	'share' => array(
 		'Known' => 'Sitios basados en conocidos',
-		'blogotext' => 'Blogotext',
+		'blogotext' => 'Blogotext',	// IGNORE
 		'clipboard' => 'Portapapeles',
-		'diaspora' => 'Diaspora*',
-		'email' => 'Email',
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
+		'diaspora' => 'Diaspora*',	// IGNORE
+		'email' => 'Email',	// IGNORE
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
 		'print' => 'Imprimir',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => '¡Aviso!',
@@ -210,7 +220,7 @@ return array(
 		'by_default' => 'Por defecto',
 		'damn' => '¡Córcholis!',
 		'default_category' => 'Sin categorizar',
-		'no' => 'No',
+		'no' => 'No',	// IGNORE
 		'not_applicable' => 'No disponible',
 		'ok' => '¡Vale!',
 		'or' => 'o',

+ 11 - 1
app/i18n/es/index.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => 'Acerca de',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
 		'bugs_reports' => 'Informe de fallos',
 		'credits' => 'Créditos',
 		'credits_content' => 'Aunque FreshRSS no usa ese entorno, algunos elementos del diseño están obtenidos de <a href="http://twitter.github.io/bootstrap/">Bootstrap</a>. Los <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Iconos</a> han sido obtenidos del <a href="https://www.gnome.org/">proyecto GNOME</a>. La fuente <em>Open Sans</em> es una creación de <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS usa el entorno PHP <a href="https://github.com/marienfressinaud/MINZ">Minz</a>.',

+ 10 - 0
app/i18n/es/install.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => 'Completar instalación',

+ 12 - 2
app/i18n/es/sub.php

@@ -1,14 +1,24 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
 		'documentation' => 'Copie la siguiente URL para usarla dentro de una herramienta externa.',
-		'title' => 'API',
+		'title' => 'API',	// IGNORE
 	),
 	'bookmarklet' => array(
 		'documentation' => 'Arrastre este botón a la barra de herramientas de marcadores o haga clic derecho en él y elija "Marcar este enlace". Luego haga clic en el botón "Suscribirse" en cualquier página a la que desee suscribirse.',
 		'label' => 'Subscribirse',
-		'title' => 'Bookmarklet',
+		'title' => 'Bookmarklet',	// IGNORE
 	),
 	'category' => array(
 		'_' => 'Categoría',

+ 10 - 0
app/i18n/es/user.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(

+ 15 - 5
app/i18n/fr/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => 'Autoriser la lecture anonyme des articles de l’utilisateur par défaut (%s)',
@@ -103,7 +113,7 @@ return array(
 	'extensions' => array(
 		'author' => 'Auteur',
 		'community' => 'Extensions utilisateur disponibles',
-		'description' => 'Description',
+		'description' => 'Description',	// IGNORE
 		'disabled' => 'Désactivée',
 		'empty_list' => 'Aucune extension installée',
 		'enabled' => 'Activée',
@@ -114,10 +124,10 @@ return array(
 			'_' => 'Extensions système',
 			'no_rights' => 'Extensions système (contrôlées par l’administrateur)',
 		),
-		'title' => 'Extensions',
+		'title' => 'Extensions',	// IGNORE
 		'update' => 'Mise à jour disponible',
 		'user' => 'Extensions utilisateur',
-		'version' => 'Version',
+		'version' => 'Version',	// IGNORE
 	),
 	'stats' => array(
 		'_' => 'Statistiques',
@@ -136,7 +146,7 @@ return array(
 		'main' => 'Statistiques principales',
 		'main_stream' => 'Flux principal',
 		'no_idle' => 'Il n’y a aucun flux inactif !',
-		'number_entries' => '%d articles',
+		'number_entries' => '%d articles',	// IGNORE
 		'percent_of_total' => '%% du total',
 		'repartition' => 'Répartition des articles',
 		'status_favorites' => 'favoris',
@@ -173,7 +183,7 @@ return array(
 	),
 	'user' => array(
 		'admin' => 'Administrateur',
-		'article_count' => 'Articles',
+		'article_count' => 'Articles',	// IGNORE
 		'back_to_manage' => '← Revenir à la liste des utilisateurs',
 		'create' => 'Créer un nouvel utilisateur',
 		'database_size' => 'Volumétrie',

+ 25 - 15
app/i18n/fr/conf.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'Archivage',
@@ -11,7 +21,7 @@ return array(
 		'keep_min_by_feed' => 'Nombre minimum d’articles à conserver par flux',
 		'keep_period' => 'Âge maximum des articles à conserver',
 		'keep_unreads' => 'Ne jamais supprimer les articles non lus',
-		'maintenance' => 'Maintenance',
+		'maintenance' => 'Maintenance',	// IGNORE
 		'optimize' => 'Optimiser la base de données',
 		'optimize_help' => 'À faire de temps en temps pour réduire la taille de la BDD',
 		'policy' => 'Politique de nettoyage',
@@ -44,13 +54,13 @@ return array(
 			'label' => 'Miniature',
 			'landscape' => 'Paysage',
 			'none' => 'Sans',
-			'portrait' => 'Portrait',
+			'portrait' => 'Portrait',	// IGNORE
 			'square' => 'Carrée',
 		),
 		'title' => 'Affichage',
 		'width' => array(
 			'content' => 'Largeur du contenu',
-			'large' => 'Large',
+			'large' => 'Large',	// IGNORE
 			'medium' => 'Moyenne',
 			'no_limit' => 'Pas de limite',
 			'thin' => 'Fine',
@@ -77,10 +87,10 @@ return array(
 			'categories' => 'Afficher par catégorie',
 			'feeds' => 'Afficher par flux',
 			'order' => 'Tri par date',
-			'search' => 'Expression',
+			'search' => 'Expression',	// IGNORE
 			'state' => 'État',
 			'tags' => 'Afficher par étiquette',
-			'type' => 'Type',
+			'type' => 'Type',	// IGNORE
 		),
 		'get_all' => 'Afficher tous les articles',
 		'get_category' => 'Afficher la catégorie "%s"',
@@ -163,20 +173,20 @@ return array(
 	'sharing' => array(
 		'_' => 'Partage',
 		'add' => 'Ajouter une méthode de partage',
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'Courriel',
-		'facebook' => 'Facebook',
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => 'Plus d’informations',
-		'print' => 'Print',
-		'raindrop' => 'Raindrop.io',
+		'print' => 'Print',	// IGNORE
+		'raindrop' => 'Raindrop.io',	// IGNORE
 		'remove' => 'Supprimer la méthode de partage',
-		'shaarli' => 'Shaarli',
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => 'Nom du partage à afficher',
 		'share_url' => 'URL du partage à utiliser',
 		'title' => 'Partage',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => 'Raccourcis',
@@ -194,7 +204,7 @@ return array(
 		'load_more' => 'Charger plus d’articles',
 		'mark_favorite' => 'Basculer l’indicateur de favori',
 		'mark_read' => 'Basculer l’indicateur de lecture',
-		'navigation' => 'Navigation',
+		'navigation' => 'Navigation',	// IGNORE
 		'navigation_help' => 'Avec le modificateur <kbd>⇧ Maj</kbd>, les raccourcis de navigation s’appliquent aux flux.<br/>Avec le modificateur <kbd>Alt ⎇</kbd>, les raccourcis de navigation s’appliquent aux catégories.',
 		'navigation_no_mod_help' => 'Les raccourcis suivant ne supportent pas les modificateurs.',
 		'next_article' => 'Passer à l’article suivant',
@@ -216,7 +226,7 @@ return array(
 		'views' => 'Vues',
 	),
 	'user' => array(
-		'articles_and_size' => '%s articles (%s)',
+		'articles_and_size' => '%s articles (%s)',	// IGNORE
 		'current' => 'Utilisateur actuel',
 		'is_admin' => 'est administrateur',
 		'users' => 'Utilisateurs',

+ 10 - 0
app/i18n/fr/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'Vous n’avez pas le droit d’accéder à cette page !',

+ 52 - 42
app/i18n/fr/gen.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'Actualiser flux',
@@ -69,8 +79,8 @@ return array(
 		'december' => 'décembre',
 		'feb' => 'fév.',
 		'february' => 'février',
-		'format_date' => 'j %s Y',
-		'format_date_hour' => 'j %s Y \\à H\\:i',
+		'format_date' => 'j %s Y',	// IGNORE
+		'format_date_hour' => 'j %s Y \\à H\\:i',	// IGNORE
 		'fri' => 'ven.',
 		'jan' => 'jan.',
 		'january' => 'janvier',
@@ -106,9 +116,9 @@ return array(
 		'wed' => 'mer.',
 		'yesterday' => 'Hier',
 	),
-	'dir' => 'ltr',
+	'dir' => 'ltr',	// IGNORE
 	'freshrss' => array(
-		'_' => 'FreshRSS',
+		'_' => 'FreshRSS',	// IGNORE
 		'about' => 'À propos de FreshRSS',
 	),
 	'js' => array(
@@ -124,36 +134,36 @@ return array(
 		'should_be_activated' => 'Le JavaScript doit être activé.',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'À propos',
 		'account' => 'Compte',
-		'admin' => 'Administration',
+		'admin' => 'Administration',	// IGNORE
 		'archiving' => 'Archivage',
 		'authentication' => 'Authentification',
 		'check_install' => 'Vérification de l’installation',
-		'configuration' => 'Configuration',
+		'configuration' => 'Configuration',	// IGNORE
 		'display' => 'Affichage',
-		'extensions' => 'Extensions',
-		'logs' => 'Logs',
+		'extensions' => 'Extensions',	// IGNORE
+		'logs' => 'Logs',	// IGNORE
 		'queries' => 'Filtres utilisateurs',
 		'reading' => 'Lecture',
 		'search' => 'Rechercher des mots ou des #tags',
@@ -183,25 +193,25 @@ return array(
 	),
 	'share' => array(
 		'Known' => 'Sites basés sur Known',
-		'blogotext' => 'Blogotext',
+		'blogotext' => 'Blogotext',	// IGNORE
 		'clipboard' => 'Presse-papier',
-		'diaspora' => 'Diaspora*',
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'Courriel',
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
 		'print' => 'Imprimer',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => 'Attention !',

+ 14 - 4
app/i18n/fr/index.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => 'À propos',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
 		'bugs_reports' => 'Rapports de bugs',
 		'credits' => 'Crédits',
 		'credits_content' => 'Des éléments de design sont issus du <a href="http://twitter.github.io/bootstrap/">projet Bootstrap</a> bien que FreshRSS n’utilise pas ce framework. Les <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">icônes</a> sont issues du <a href="https://www.gnome.org/">projet GNOME</a>. La police <em>Open Sans</em> utilisée a été créée par <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS repose sur <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, un framework PHP.',
@@ -12,7 +22,7 @@ return array(
 		'license' => 'Licence',
 		'project_website' => 'Site du projet',
 		'title' => 'À propos',
-		'version' => 'Version',
+		'version' => 'Version',	// IGNORE
 	),
 	'feed' => array(
 		'add' => 'Vous pouvez ajouter des flux.',
@@ -23,10 +33,10 @@ return array(
 		'title_global' => 'Vue globale',
 	),
 	'log' => array(
-		'_' => 'Logs',
+		'_' => 'Logs',	// IGNORE
 		'clear' => 'Effacer les logs',
 		'empty' => 'Les logs sont vides.',
-		'title' => 'Logs',
+		'title' => 'Logs',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'À propos de FreshRSS',

+ 12 - 2
app/i18n/fr/install.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => 'Terminer l’installation',
@@ -118,6 +128,6 @@ return array(
 	),
 	'step' => 'étape %d',
 	'steps' => 'Étapes',
-	'this_is_the_end' => 'This is the end',
-	'title' => 'Installation · FreshRSS',
+	'this_is_the_end' => 'This is the end',	// IGNORE
+	'title' => 'Installation · FreshRSS',	// IGNORE
 );

+ 15 - 5
app/i18n/fr/sub.php

@@ -1,14 +1,24 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
 		'documentation' => 'Copier l’URL suivante dans l’outil qui utilisera l’API.',
-		'title' => 'API',
+		'title' => 'API',	// IGNORE
 	),
 	'bookmarklet' => array(
 		'documentation' => 'Glisser ce bouton dans la barre des favoris ou cliquer droit dessus et choisir "Enregistrer ce lien". Ensuite, cliquer sur le bouton "S’abonner" sur les pages auxquelles vous voulez vous abonner.',
 		'label' => 'S’abonner',
-		'title' => 'Bookmarklet',
+		'title' => 'Bookmarklet',	// IGNORE
 	),
 	'category' => array(
 		'_' => 'Catégorie',
@@ -42,7 +52,7 @@ return array(
 		'css_cookie_help' => 'Exemple : <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
 		'css_help' => 'Permet de récupérer les flux tronqués (attention, demande plus de temps !)',
 		'css_path' => 'Sélecteur CSS des articles sur le site d’origine',
-		'description' => 'Description',
+		'description' => 'Description',	// IGNORE
 		'empty' => 'Ce flux est vide. Veuillez vérifier qu’il est toujours maintenu.',
 		'error' => 'Ce flux a rencontré un problème. Veuillez vérifier qu’il est toujours accessible puis actualisez-le.',
 		'filteractions' => array(
@@ -56,12 +66,12 @@ return array(
 			'clear_cache_help' => 'Supprime le cache de ce flux.',
 			'reload_articles' => 'Recharger les articles',
 			'reload_articles_help' => 'Recharge les articles et récupère le contenu complet si un sélecteur est défini.',
-			'title' => 'Maintenance',
+			'title' => 'Maintenance',	// IGNORE
 		),
 		'moved_category_deleted' => 'Lors de la suppression d’une catégorie, ses flux seront automatiquement classés dans <em>%s</em>.',
 		'mute' => 'muet',
 		'no_selected' => 'Aucun flux sélectionné.',
-		'number_entries' => '%d articles',
+		'number_entries' => '%d articles',	// IGNORE
 		'priority' => array(
 			'_' => 'Visibilité',
 			'archived' => 'Ne pas afficher (archivé)',

+ 10 - 0
app/i18n/fr/user.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(

+ 72 - 62
app/i18n/he/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => 'הרשאה לאנונימיים לקרוא את מאמרי משתמש ברירת המחדל (%s)',
@@ -8,7 +18,7 @@ return array(
 		'form' => 'טופס אינטרנטי (מסורתי, דורש JavaScript)',
 		'http' => 'HTTP (למשתמשים מתקדמים עם HTTPS)',
 		'none' => 'ללא (מסוכן)',
-		'title' => 'Authentication',	// TODO - Translation
+		'title' => 'Authentication',	// TODO
 		'token' => 'מחרוזת אימות',
 		'token_help' => 'Allows to access RSS output of the default user without authentication:',
 		'type' => 'שיטת אימות',
@@ -21,11 +31,11 @@ return array(
 		),
 		'categories' => array(
 			'nok' => 'Category table is bad configured.',
-			'ok' => 'Category table is okay.',	// TODO - Translation
+			'ok' => 'Category table is okay.',	// TODO
 		),
 		'connection' => array(
 			'nok' => 'Connection to the database cannot being established.',
-			'ok' => 'Connection to the database is okay.',	// TODO - Translation
+			'ok' => 'Connection to the database is okay.',	// TODO
 		),
 		'ctype' => array(
 			'nok' => 'הספרייה הנדרשת ל character type checking (php-ctype) אינה מותקנת',
@@ -39,35 +49,35 @@ return array(
 			'nok' => 'יש לבדוק את ההרשאות בתיקייה <em>%s</em>. שרת הHTTP חייב להיות בעל הרשאות כתיבה.',
 			'ok' => 'ההרשאות בתיקיית הדאטא תקינות',
 		),
-		'database' => 'Database installation',	// TODO - Translation
+		'database' => 'Database installation',	// TODO
 		'dom' => array(
 			'nok' => 'הספרייה הנדרשת לסיור ב DOM אינה מותקנת	(php-xml package)',
 			'ok' => 'הספרייה הנדרשת לסיור ב DOM מותקנת',
 		),
 		'entries' => array(
-			'nok' => 'Entry table is improperly configured.',	// TODO - Translation
-			'ok' => 'Entry table is okay.',	// TODO - Translation
+			'nok' => 'Entry table is improperly configured.',	// TODO
+			'ok' => 'Entry table is okay.',	// TODO
 		),
 		'favicons' => array(
-			'nok' => 'Check permissions on <em>./data/favicons</em> directory. HTTP server must have write permission.',	// TODO - Translation
+			'nok' => 'Check permissions on <em>./data/favicons</em> directory. HTTP server must have write permission.',	// TODO
 			'ok' => 'ההרשאות בתיקיית הfavicons תקינות',
 		),
 		'feeds' => array(
 			'nok' => 'Feed table is bad configured.',
-			'ok' => 'Feed table is okay.',	// TODO - Translation
+			'ok' => 'Feed table is okay.',	// TODO
 		),
 		'fileinfo' => array(
-			'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',	// TODO - Translation
-			'ok' => 'You have the fileinfo library.',	// TODO - Translation
+			'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',	// TODO
+			'ok' => 'You have the fileinfo library.',	// TODO
 		),
-		'files' => 'File installation',	// TODO - Translation
+		'files' => 'File installation',	// TODO
 		'json' => array(
 			'nok' => 'You lack JSON (php-json package).',
-			'ok' => 'You have the JSON extension.',	// TODO - Translation
+			'ok' => 'You have the JSON extension.',	// TODO
 		),
 		'mbstring' => array(
-			'nok' => 'Cannot find the recommended mbstring library for Unicode.',	// TODO - Translation
-			'ok' => 'You have the recommended mbstring library for Unicode.',	// TODO - Translation
+			'nok' => 'Cannot find the recommended mbstring library for Unicode.',	// TODO
+			'ok' => 'You have the recommended mbstring library for Unicode.',	// TODO
 		),
 		'pcre' => array(
 			'nok' => 'הספרייה הנדרשת לביטויים רגולריים אינה מותקנת (php-pcre)',
@@ -78,7 +88,7 @@ return array(
 			'ok' => 'PDO מותקן ולפחות אחד ממנהלי ההתקן הנתמכים מותקן (pdo_mysql, pdo_sqlite)',
 		),
 		'php' => array(
-			'_' => 'PHP installation',	// TODO - Translation
+			'_' => 'PHP installation',	// TODO
 			'nok' => 'גירסת PHP שלכם היא %s אך FreshRSS דורש לפחות את גירסה %s',
 			'ok' => 'גירסת PHP שלכם היא %s, שתואמת ל FreshRSS',
 		),
@@ -86,38 +96,38 @@ return array(
 			'nok' => 'There is one or more lacking tables in the database.',
 			'ok' => 'Tables are existing in the database.',
 		),
-		'title' => 'Installation check',	// TODO - Translation
+		'title' => 'Installation check',	// TODO
 		'tokens' => array(
-			'nok' => 'Check permissions on <em>./data/tokens</em> directory. HTTP server must have write permission',	// TODO - Translation
-			'ok' => 'Permissions on the tokens directory are good.',	// TODO - Translation
+			'nok' => 'Check permissions on <em>./data/tokens</em> directory. HTTP server must have write permission',	// TODO
+			'ok' => 'Permissions on the tokens directory are good.',	// TODO
 		),
 		'users' => array(
-			'nok' => 'Check permissions on <em>./data/users</em> directory. HTTP server must have write permission',	// TODO - Translation
-			'ok' => 'Permissions on the users directory are good.',	// TODO - Translation
+			'nok' => 'Check permissions on <em>./data/users</em> directory. HTTP server must have write permission',	// TODO
+			'ok' => 'Permissions on the users directory are good.',	// TODO
 		),
 		'zip' => array(
 			'nok' => 'You lack ZIP extension (php-zip package).',
-			'ok' => 'You have the ZIP extension.',	// TODO - Translation
+			'ok' => 'You have the ZIP extension.',	// TODO
 		),
 	),
 	'extensions' => array(
-		'author' => 'Author',	// TODO - Translation
-		'community' => 'Available community extensions',	// TODO - Translation
-		'description' => 'Description',	// TODO - Translation
-		'disabled' => 'Disabled',	// TODO - Translation
+		'author' => 'Author',	// TODO
+		'community' => 'Available community extensions',	// TODO
+		'description' => 'Description',	// TODO
+		'disabled' => 'Disabled',	// TODO
 		'empty_list' => 'There is no installed extension',
-		'enabled' => 'Enabled',	// TODO - Translation
-		'latest' => 'Installed',	// TODO - Translation
-		'name' => 'Name',	// TODO - Translation
-		'no_configure_view' => 'This extension cannot be configured.',	// TODO - Translation
+		'enabled' => 'Enabled',	// TODO
+		'latest' => 'Installed',	// TODO
+		'name' => 'Name',	// TODO
+		'no_configure_view' => 'This extension cannot be configured.',	// TODO
 		'system' => array(
-			'_' => 'System extensions',	// TODO - Translation
-			'no_rights' => 'System extension (you do not have the required permissions)',	// TODO - Translation
+			'_' => 'System extensions',	// TODO
+			'no_rights' => 'System extension (you do not have the required permissions)',	// TODO
 		),
-		'title' => 'Extensions',	// TODO - Translation
-		'update' => 'Update available',	// TODO - Translation
-		'user' => 'User extensions',	// TODO - Translation
-		'version' => 'Version',	// TODO - Translation
+		'title' => 'Extensions',	// TODO
+		'update' => 'Update available',	// TODO
+		'user' => 'User extensions',	// TODO
+		'version' => 'Version',	// TODO
 	),
 	'stats' => array(
 		'_' => 'סטטיסטיקות',
@@ -126,9 +136,9 @@ return array(
 		'entry_count' => 'סכום המאמרים',
 		'entry_per_category' => 'מאמרים על פי קטגוריה',
 		'entry_per_day' => 'מספר מאמרים ליום (30 ימים אחרונים)',
-		'entry_per_day_of_week' => 'Per day of week (average: %.2f messages)',	// TODO - Translation
-		'entry_per_hour' => 'Per hour (average: %.2f messages)',	// TODO - Translation
-		'entry_per_month' => 'Per month (average: %.2f messages)',	// TODO - Translation
+		'entry_per_day_of_week' => 'Per day of week (average: %.2f messages)',	// TODO
+		'entry_per_hour' => 'Per hour (average: %.2f messages)',	// TODO
+		'entry_per_month' => 'Per month (average: %.2f messages)',	// TODO
 		'entry_repartition' => 'חלוקת המאמרים',
 		'feed' => 'הזנה',
 		'feed_per_category' => 'הזנות על פי קטגוריה',
@@ -147,19 +157,19 @@ return array(
 		'top_feed' => 'עשרת ההזנות המובילות',
 	),
 	'system' => array(
-		'_' => 'System configuration',	// TODO - Translation
-		'auto-update-url' => 'Auto-update server URL',	// TODO - Translation
+		'_' => 'System configuration',	// TODO
+		'auto-update-url' => 'Auto-update server URL',	// TODO
 		'cookie-duration' => array(
-			'help' => 'in seconds',	// TODO - Translation
-			'number' => 'Duration to keep logged in',	// TODO - Translation
+			'help' => 'in seconds',	// TODO
+			'number' => 'Duration to keep logged in',	// TODO
 		),
-		'force_email_validation' => 'Force email address validation',	// TODO - Translation
-		'instance-name' => 'Instance name',	// TODO - Translation
-		'max-categories' => 'Max number of categories per user',	// TODO - Translation
-		'max-feeds' => 'Max number of feeds per user',	// TODO - Translation
+		'force_email_validation' => 'Force email address validation',	// TODO
+		'instance-name' => 'Instance name',	// TODO
+		'max-categories' => 'Max number of categories per user',	// TODO
+		'max-feeds' => 'Max number of feeds per user',	// TODO
 		'registration' => array(
-			'help' => '0 means that there is no account limit',	// TODO - Translation
-			'number' => 'Max number of accounts',	// TODO - Translation
+			'help' => '0 means that there is no account limit',	// TODO
+			'number' => 'Max number of accounts',	// TODO
 		),
 	),
 	'update' => array(
@@ -172,23 +182,23 @@ return array(
 		'title' => 'מערכת העדכון',
 	),
 	'user' => array(
-		'admin' => 'Administrator',	// TODO - Translation
-		'article_count' => 'Articles',	// TODO - Translation
-		'back_to_manage' => '← Return to user list',	// TODO - Translation
+		'admin' => 'Administrator',	// TODO
+		'article_count' => 'Articles',	// TODO
+		'back_to_manage' => '← Return to user list',	// TODO
 		'create' => 'יצירת משתמש חדש',
-		'database_size' => 'Database size',	// TODO - Translation
-		'email' => 'Email address',	// TODO - Translation
-		'enabled' => 'Enabled',	// TODO - Translation
-		'feed_count' => 'Feeds',	// TODO - Translation
-		'is_admin' => 'Is admin',	// TODO - Translation
+		'database_size' => 'Database size',	// TODO
+		'email' => 'Email address',	// TODO
+		'enabled' => 'Enabled',	// TODO
+		'feed_count' => 'Feeds',	// TODO
+		'is_admin' => 'Is admin',	// TODO
 		'language' => 'שפה',
-		'last_user_activity' => 'Last user activity',	// TODO - Translation
-		'list' => 'User list',	// TODO - Translation
-		'number' => 'There is %d account created',	// TODO - Translation
-		'numbers' => 'There are %d accounts created',	// TODO - Translation
+		'last_user_activity' => 'Last user activity',	// TODO
+		'list' => 'User list',	// TODO
+		'number' => 'There is %d account created',	// TODO
+		'numbers' => 'There are %d accounts created',	// TODO
 		'password_form' => 'סיסמה<br /><small>(לשימוש בטפוס ההרשמה)</small>',
-		'password_format' => 'At least 7 characters',	// TODO - Translation
-		'title' => 'Manage users',	// TODO - Translation
+		'password_format' => 'At least 7 characters',	// TODO
+		'title' => 'Manage users',	// TODO
 		'username' => 'שם משתמש',
 	),
 );

+ 79 - 69
app/i18n/he/conf.php

@@ -1,21 +1,31 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'ארכוב',
-		'exception' => 'Purge exception',	// TODO - Translation
+		'exception' => 'Purge exception',	// TODO
 		'help' => 'אפשרויות נוספות זמינות בזרמים ספציפיים',
-		'keep_favourites' => 'Never delete favourites',	// TODO - Translation
-		'keep_labels' => 'Never delete labels',	// TODO - Translation
-		'keep_max' => 'Maximum number of articles to keep',	// TODO - Translation
-		'keep_min_by_feed' => 'Minimum number of articles to keep per feed',	// TODO - Translation
-		'keep_period' => 'Maximum age of articles to keep',	// TODO - Translation
-		'keep_unreads' => 'Never delete unread articles',	// TODO - Translation
-		'maintenance' => 'Maintenance',	// TODO - Translation
+		'keep_favourites' => 'Never delete favourites',	// TODO
+		'keep_labels' => 'Never delete labels',	// TODO
+		'keep_max' => 'Maximum number of articles to keep',	// TODO
+		'keep_min_by_feed' => 'Minimum number of articles to keep per feed',	// TODO
+		'keep_period' => 'Maximum age of articles to keep',	// TODO
+		'keep_unreads' => 'Never delete unread articles',	// TODO
+		'maintenance' => 'Maintenance',	// TODO
 		'optimize' => 'מיטוב בסיס הנתונים',
 		'optimize_help' => 'ביצוע לעיתים קרובות על מנת למטב את בסיס הנתונים',
-		'policy' => 'Purge policy',	// TODO - Translation
-		'policy_warning' => 'If no purge policy is selected, every article will be kept.',	// TODO - Translation
+		'policy' => 'Purge policy',	// TODO
+		'policy_warning' => 'If no purge policy is selected, every article will be kept.',	// TODO
 		'purge_now' => 'ניקוי עכשיו',
 		'title' => 'ארכוב',
 		'ttl' => 'אין לרענן אוטומטית יותר מ',
@@ -24,12 +34,12 @@ return array(
 		'_' => 'תצוגה',
 		'icon' => array(
 			'bottom_line' => 'שורה תחתונה',
-			'display_authors' => 'Authors',	// TODO - Translation
+			'display_authors' => 'Authors',	// TODO
 			'entry' => 'סמלילי מאמרים',
 			'publication_date' => 'תאריך הפרסום',
 			'related_tags' => 'תגיות קשורות',
 			'sharing' => 'שיתוף',
-			'summary' => 'Summary',	// TODO - Translation
+			'summary' => 'Summary',	// TODO
 			'top_line' => 'שורה עליונה',
 		),
 		'language' => 'שפה',
@@ -37,15 +47,15 @@ return array(
 			'seconds' => 'שניות (0 משמעותה ללא פג תוקף)',
 			'timeout' => 'HTML5 התראה פג תוקף',
 		),
-		'show_nav_buttons' => 'Show the navigation buttons',	// TODO - Translation
+		'show_nav_buttons' => 'Show the navigation buttons',	// TODO
 		'theme' => 'ערכת נושא',
-		'theme_not_available' => 'The “%s” theme is not available anymore. Please choose another theme.',	// TODO - Translation
+		'theme_not_available' => 'The “%s” theme is not available anymore. Please choose another theme.',	// TODO
 		'thumbnail' => array(
-			'label' => 'Thumbnail',	// TODO - Translation
-			'landscape' => 'Landscape',	// TODO - Translation
-			'none' => 'None',	// TODO - Translation
-			'portrait' => 'Portrait',	// TODO - Translation
-			'square' => 'Square',	// TODO - Translation
+			'label' => 'Thumbnail',	// TODO
+			'landscape' => 'Landscape',	// TODO
+			'none' => 'None',	// TODO
+			'portrait' => 'Portrait',	// TODO
+			'square' => 'Square',	// TODO
 		),
 		'title' => 'תצוגה',
 		'width' => array(
@@ -57,36 +67,36 @@ return array(
 		),
 	),
 	'profile' => array(
-		'_' => 'Profile management',	// TODO - Translation
-		'api' => 'API management',	// TODO - Translation
+		'_' => 'Profile management',	// TODO
+		'api' => 'API management',	// TODO
 		'delete' => array(
-			'_' => 'Account deletion',	// TODO - Translation
-			'warn' => 'Your account and all related data will be deleted.',	// TODO - Translation
+			'_' => 'Account deletion',	// TODO
+			'warn' => 'Your account and all related data will be deleted.',	// TODO
 		),
-		'email' => 'Email address',	// TODO - Translation
+		'email' => 'Email address',	// TODO
 		'password_api' => 'סיסמת API<br /><small>(לדוגמה ליישומים סלולריים)</small>',
 		'password_form' => 'סיסמה<br /><small>(לשימוש בטפוס ההרשמה)</small>',
-		'password_format' => 'At least 7 characters',	// TODO - Translation
-		'title' => 'Profile',	// TODO - Translation
+		'password_format' => 'At least 7 characters',	// TODO
+		'title' => 'Profile',	// TODO
 	),
 	'query' => array(
 		'_' => 'שאילתות',
 		'deprecated' => 'שאילתה זו אינה בתוקף יותר, הפיד או הקטגוריה לייחוס נמחקו.',
 		'filter' => array(
 			'_' => 'מסננים בשימוש:',
-			'categories' => 'Display by category',	// TODO - Translation
-			'feeds' => 'Display by feed',	// TODO - Translation
-			'order' => 'Sort by date',	// TODO - Translation
-			'search' => 'Expression',	// TODO - Translation
-			'state' => 'State',	// TODO - Translation
-			'tags' => 'Display by tag',	// TODO - Translation
-			'type' => 'Type',	// TODO - Translation
+			'categories' => 'Display by category',	// TODO
+			'feeds' => 'Display by feed',	// TODO
+			'order' => 'Sort by date',	// TODO
+			'search' => 'Expression',	// TODO
+			'state' => 'State',	// TODO
+			'tags' => 'Display by tag',	// TODO
+			'type' => 'Type',	// TODO
 		),
 		'get_all' => 'הצגת כל המאמרים',
 		'get_category' => 'הצגת קטגוריה "%s"',
 		'get_favorite' => 'הצגת מאמרים מועדפים',
 		'get_feed' => 'הצגת הזנה %s',
-		'name' => 'Name',	// TODO - Translation
+		'name' => 'Name',	// TODO
 		'no_filter' => 'ללא סינון',
 		'number' => 'שאילתה מספר °%d',
 		'order_asc' => 'הצגת מאמרים ישנים בראש',
@@ -113,39 +123,39 @@ return array(
 	'reading' => array(
 		'_' => 'קריאה',
 		'after_onread' => 'לאחר “סימון הכל כנקרא”,',
-		'always_show_favorites' => 'Show all articles in favourites by default',	// TODO - Translation
+		'always_show_favorites' => 'Show all articles in favourites by default',	// TODO
 		'articles_per_page' => 'מספר המאמרים בעמוד',
 		'auto_load_more' => 'טעינת המאמר הבא סוף העמוד',
-		'auto_remove_article' => 'Hide articles after reading',	// TODO - Translation
+		'auto_remove_article' => 'Hide articles after reading',	// TODO
 		'confirm_enabled' => 'הצגת דו-שיח לאישור “סימון הכל כנקרא” ',
 		'display_articles_unfolded' => 'הצגת מאמרים בשלמותם כברירת מחדל',
-		'display_categories_unfolded' => 'Categories to unfold',	// TODO - Translation
+		'display_categories_unfolded' => 'Categories to unfold',	// TODO
 		'hide_read_feeds' => 'הסתרת קטגוריות &amp; הזנות ללא מאמרים שלא נקראו (לא עובד יחד עם “הצגת כל המאמרים”)',
 		'img_with_lazyload' => 'שימוש ב "טעינה עצלה" על מנת לטעון תמונות',
 		'jump_next' => 'קפיצה לפריט הבא שלא נקרא (הזנה או קטגוריה)',
-		'mark_updated_article_unread' => 'Mark updated articles as unread',	// TODO - Translation
+		'mark_updated_article_unread' => 'Mark updated articles as unread',	// TODO
 		'number_divided_when_reader' => 'חלוקה ב2 במצב קריאה.',
 		'read' => array(
 			'article_open_on_website' => 'כאשר מאמר נפתח באתר המקורי',
 			'article_viewed' => 'כאשר מאמר נצפה',
-			'keep_max_n_unread' => 'Max number of articles to keep unread',	// TODO - Translation
+			'keep_max_n_unread' => 'Max number of articles to keep unread',	// TODO
 			'scroll' => 'כאשר גוללים',
 			'upon_reception' => 'כאשר המאמר מתקבל',
 			'when' => 'סימון מאמרים כנקראו…',
-			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',	// TODO - Translation
+			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',	// TODO
 		),
 		'show' => array(
 			'_' => 'מאמרים להצגה',
-			'active_category' => 'Active category',	// TODO - Translation
+			'active_category' => 'Active category',	// TODO
 			'adaptive' => 'תצוגה מתעדכנת',
 			'all_articles' => 'הצגת כל המאמרים',
-			'all_categories' => 'All categories',	// TODO - Translation
-			'no_category' => 'No category',	// TODO - Translation
-			'remember_categories' => 'Remember open categories',	// TODO - Translation
+			'all_categories' => 'All categories',	// TODO
+			'no_category' => 'No category',	// TODO
+			'remember_categories' => 'Remember open categories',	// TODO
 			'unread' => 'הצגת מאמרים שלא נקראו בלבד',
 		),
-		'show_fav_unread_help' => 'Applies also on labels',	// TODO - Translation
-		'sides_close_article' => 'Clicking outside of article text area closes the article',	// TODO - Translation
+		'show_fav_unread_help' => 'Applies also on labels',	// TODO
+		'sides_close_article' => 'Clicking outside of article text area closes the article',	// TODO
 		'sort' => array(
 			'_' => 'סדר המיון',
 			'newer_first' => 'חדשים בראש',
@@ -162,32 +172,32 @@ return array(
 	),
 	'sharing' => array(
 		'_' => 'שיתוף',
-		'add' => 'Add a sharing method',	// TODO - Translation
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
+		'add' => 'Add a sharing method',	// TODO
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'דואר אלקטרוני',
-		'facebook' => 'Facebook',
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => 'מידע נוסף',
 		'print' => 'הדפסה',
-		'raindrop' => 'Raindrop.io',
-		'remove' => 'Remove sharing method',	// TODO - Translation
-		'shaarli' => 'Shaarli',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'remove' => 'Remove sharing method',	// TODO
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => 'שיתוף שם לתצוגה',
 		'share_url' => 'לשימוש שתפו URL',
 		'title' => 'שיתוף',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => 'קיצורי דרך',
 		'article_action' => 'פעולות על מאמרים',
 		'auto_share' => 'שיתוף',
 		'auto_share_help' => 'אם יש רק מצב שיתוף אחד, הוא מופעל. אחרת המצבים נבחרים על בסיס המספר שלהם.',
-		'close_dropdown' => 'Close menus',	// TODO - Translation
+		'close_dropdown' => 'Close menus',	// TODO
 		'collapse_article' => 'כיווץ',
 		'first_article' => 'דילוג למאמר הראשון',
 		'focus_search' => 'גישה לתיבת החיפוש',
-		'global_view' => 'Switch to global view',	// TODO - Translation
+		'global_view' => 'Switch to global view',	// TODO
 		'help' => 'הצגת התיעוד',
 		'javascript' => 'חובה להפעיל JavaScript על מנת לעשות שימוש בקיצורי דרך',
 		'last_article' => 'דילוג למאמר האחרון',
@@ -196,27 +206,27 @@ return array(
 		'mark_read' => 'סימון כנקרא',
 		'navigation' => 'ניווט',
 		'navigation_help' => 'בעזרת מקש השיפט קיצורי דרך חלים על הזנות .<br/>עם מקש האלט הם חלים על קטגוריות.',
-		'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.',	// TODO - Translation
+		'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.',	// TODO
 		'next_article' => 'דילוג למאמר הבא',
-		'next_unread_article' => 'Open the next unread article',	// TODO - Translation
-		'non_standard' => 'Some keys (<kbd>%s</kbd>) may not work as shortcuts.',	// TODO - Translation
-		'normal_view' => 'Switch to normal view',	// TODO - Translation
+		'next_unread_article' => 'Open the next unread article',	// TODO
+		'non_standard' => 'Some keys (<kbd>%s</kbd>) may not work as shortcuts.',	// TODO
+		'normal_view' => 'Switch to normal view',	// TODO
 		'other_action' => 'פעולות אחרות',
 		'previous_article' => 'דילוג למאמר הקודם',
-		'reading_view' => 'Switch to reading view',	// TODO - Translation
-		'rss_view' => 'Open as RSS feed',	// TODO - Translation
+		'reading_view' => 'Switch to reading view',	// TODO
+		'rss_view' => 'Open as RSS feed',	// TODO
 		'see_on_website' => 'ראו את המקור באתר',
-		'shift_for_all_read' => '+ <kbd>Alt ⎇</kbd> to mark previous articles as read<br />+ <kbd>⇧ Shift</kbd> to mark all articles as read',	// TODO - Translation
-		'skip_next_article' => 'Focus next without opening',	// TODO - Translation
-		'skip_previous_article' => 'Focus previous without opening',	// TODO - Translation
+		'shift_for_all_read' => '+ <kbd>Alt ⎇</kbd> to mark previous articles as read<br />+ <kbd>⇧ Shift</kbd> to mark all articles as read',	// TODO
+		'skip_next_article' => 'Focus next without opening',	// TODO
+		'skip_previous_article' => 'Focus previous without opening',	// TODO
 		'title' => 'קיצורי דרך',
-		'toggle_media' => 'Play/pause media',	// TODO - Translation
+		'toggle_media' => 'Play/pause media',	// TODO
 		'user_filter' => 'גישה למססנים',
 		'user_filter_help' => 'אם יש רק מזנן אחד הוא יהיה בשימוש. אחרת המסננים ישמשו על בסיס המספר שלהם.',
-		'views' => 'Views',	// TODO - Translation
+		'views' => 'Views',	// TODO
 	),
 	'user' => array(
-		'articles_and_size' => '%s articles (%s)',	// TODO - Translation
+		'articles_and_size' => '%s articles (%s)',	// TODO
 		'current' => 'משתמש נוכחי',
 		'is_admin' => 'מנהל',
 		'users' => 'משתמשים',

+ 54 - 44
app/i18n/he/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'אין לך הרשאות לצפות בדף זה',
@@ -10,40 +20,40 @@ return array(
 	),
 	'api' => array(
 		'password' => array(
-			'failed' => 'Your password cannot be modified',	// TODO - Translation
-			'updated' => 'Your password has been modified',	// TODO - Translation
+			'failed' => 'Your password cannot be modified',	// TODO
+			'updated' => 'Your password has been modified',	// TODO
 		),
 	),
 	'auth' => array(
 		'login' => array(
 			'invalid' => 'הכניסה לחשבון שגויה',
-			'success' => 'You are connected',	// TODO - Translation
+			'success' => 'You are connected',	// TODO
 		),
 		'logout' => array(
-			'success' => 'You are disconnected',	// TODO - Translation
+			'success' => 'You are disconnected',	// TODO
 		),
 	),
 	'conf' => array(
-		'error' => 'An error occurred while saving configuration',	// TODO - Translation
+		'error' => 'An error occurred while saving configuration',	// TODO
 		'query_created' => 'השאילתה "%s" נוצרה.',
 		'shortcuts_updated' => 'קיצורי הדרך עודכנו',
 		'updated' => 'ההגדרות עודכנו',
 	),
 	'extensions' => array(
-		'already_enabled' => '%s is already enabled',	// TODO - Translation
-		'cannot_remove' => '%s cannot be removed',	// TODO - Translation
+		'already_enabled' => '%s is already enabled',	// TODO
+		'cannot_remove' => '%s cannot be removed',	// TODO
 		'disable' => array(
-			'ko' => '%s cannot be disabled. <a href="%s">Check FreshRSS logs</a> for details.',	// TODO - Translation
-			'ok' => '%s is now disabled',	// TODO - Translation
+			'ko' => '%s cannot be disabled. <a href="%s">Check FreshRSS logs</a> for details.',	// TODO
+			'ok' => '%s is now disabled',	// TODO
 		),
 		'enable' => array(
-			'ko' => '%s cannot be enabled. <a href="%s">Check FreshRSS logs</a> for details.',	// TODO - Translation
-			'ok' => '%s is now enabled',	// TODO - Translation
+			'ko' => '%s cannot be enabled. <a href="%s">Check FreshRSS logs</a> for details.',	// TODO
+			'ok' => '%s is now enabled',	// TODO
 		),
-		'no_access' => 'You have no access on %s',	// TODO - Translation
+		'no_access' => 'You have no access on %s',	// TODO
 		'not_enabled' => '%s is not enabled yet',
-		'not_found' => '%s does not exist',	// TODO - Translation
-		'removed' => '%s removed',	// TODO - Translation
+		'not_found' => '%s does not exist',	// TODO
+		'removed' => '%s removed',	// TODO
 	),
 	'import_export' => array(
 		'export_no_zip_extension' => 'הרחבת ZIP אינה מותקנת על השרת.',
@@ -54,60 +64,60 @@ return array(
 		'zip_error' => 'אירעה שגיאה במהלך ייבוא קובץ הZIP.',
 	),
 	'profile' => array(
-		'error' => 'Your profile cannot be modified',	// TODO - Translation
-		'updated' => 'Your profile has been modified',	// TODO - Translation
+		'error' => 'Your profile cannot be modified',	// TODO
+		'updated' => 'Your profile has been modified',	// TODO
 	),
 	'sub' => array(
 		'actualize' => 'מימוש',
 		'articles' => array(
-			'marked_read' => 'The selected articles have been marked as read.',	// TODO - Translation
-			'marked_unread' => 'The articles have been marked as unread.',	// TODO - Translation
+			'marked_read' => 'The selected articles have been marked as read.',	// TODO
+			'marked_unread' => 'The articles have been marked as unread.',	// TODO
 		),
 		'category' => array(
-			'created' => 'Category %s has been created.',	// TODO - Translation
-			'deleted' => 'Category has been deleted.',	// TODO - Translation
+			'created' => 'Category %s has been created.',	// TODO
+			'deleted' => 'Category has been deleted.',	// TODO
 			'emptied' => 'הקטגוריה רוקנה',
-			'error' => 'Category cannot be updated',	// TODO - Translation
-			'name_exists' => 'Category name already exists.',	// TODO - Translation
+			'error' => 'Category cannot be updated',	// TODO
+			'name_exists' => 'Category name already exists.',	// TODO
 			'no_id' => 'You must precise the id of the category.',
-			'no_name' => 'Category name cannot be empty.',	// TODO - Translation
-			'not_delete_default' => 'You cannot delete the default category!',	// TODO - Translation
-			'not_exist' => 'The category does not exist!',	// TODO - Translation
-			'over_max' => 'You have reached your limit of categories (%d)',	// TODO - Translation
-			'updated' => 'Category has been updated.',	// TODO - Translation
+			'no_name' => 'Category name cannot be empty.',	// TODO
+			'not_delete_default' => 'You cannot delete the default category!',	// TODO
+			'not_exist' => 'The category does not exist!',	// TODO
+			'over_max' => 'You have reached your limit of categories (%d)',	// TODO
+			'updated' => 'Category has been updated.',	// TODO
 		),
 		'feed' => array(
 			'actualized' => '<em>%s</em> עודכן',
 			'actualizeds' => 'הזנות RSS עודכנו',
 			'added' => 'RSS הזנת <em>%s</em> נוספה',
 			'already_subscribed' => 'אתה כבר רשום ל <em>%s</em>',
-			'cache_cleared' => '<em>%s</em> cache has been cleared',	// TODO - Translation
+			'cache_cleared' => '<em>%s</em> cache has been cleared',	// TODO
 			'deleted' => 'ההזנה נמחקה',
-			'error' => 'Feed cannot be updated',	// TODO - Translation
+			'error' => 'Feed cannot be updated',	// TODO
 			'internal_problem' => 'אין אפשרות להוסיף את ההזנה. <a href="%s">בדקו את הלוגים</a> לפרטים.',
 			'invalid_url' => 'URL <em>%s</em> אינו תקין',
 			'n_actualized' => '%d הזנות עודכנו',
 			'n_entries_deleted' => '%d המאמרים נמחקו',
 			'no_refresh' => 'אין הזנה שניתן לרענן…',
 			'not_added' => '<em>%s</em> אין אפשרות להוסיף את',
-			'not_found' => 'Feed cannot be found',	// TODO - Translation
-			'over_max' => 'You have reached your limit of feeds (%d)',	// TODO - Translation
-			'reloaded' => '<em>%s</em> has been reloaded',	// TODO - Translation
+			'not_found' => 'Feed cannot be found',	// TODO
+			'over_max' => 'You have reached your limit of feeds (%d)',	// TODO
+			'reloaded' => '<em>%s</em> has been reloaded',	// TODO
 			'selector_preview' => array(
-				'http_error' => 'Failed to load website content.',	// TODO - Translation
-				'no_entries' => 'There are no articles in this feed. You need at least one article to create a preview.',	// TODO - Translation
-				'no_feed' => 'Internal error (feed cannot be found).',	// TODO - Translation
-				'no_result' => 'The selector didn\'t match anything. As a fallback the original feed text will be displayed instead.',	// TODO - Translation
-				'selector_empty' => 'The selector is empty. You need to define one to create a preview.',	// TODO - Translation
+				'http_error' => 'Failed to load website content.',	// TODO
+				'no_entries' => 'There are no articles in this feed. You need at least one article to create a preview.',	// TODO
+				'no_feed' => 'Internal error (feed cannot be found).',	// TODO
+				'no_result' => 'The selector didn\'t match anything. As a fallback the original feed text will be displayed instead.',	// TODO
+				'selector_empty' => 'The selector is empty. You need to define one to create a preview.',	// TODO
 			),
 			'updated' => 'ההזנה התעדכנה',
 		),
 		'purge_completed' => 'הניקוי הושלם (%d מאמרים נמחקו)',
 	),
 	'tag' => array(
-		'created' => 'Tag "%s" has been created.',	// TODO - Translation
-		'name_exists' => 'Tag name already exists.',	// TODO - Translation
-		'renamed' => 'Tag "%s" has been renamed to "%s".',	// TODO - Translation
+		'created' => 'Tag "%s" has been created.',	// TODO
+		'name_exists' => 'Tag name already exists.',	// TODO
+		'renamed' => 'Tag "%s" has been renamed to "%s".',	// TODO
 	),
 	'update' => array(
 		'can_apply' => 'FreshRSS will be now updated to the <strong>version %s</strong>.',
@@ -120,15 +130,15 @@ return array(
 	'user' => array(
 		'created' => array(
 			'_' => 'המשתמש %s נוצר',
-			'error' => 'User %s cannot be created',	// TODO - Translation
+			'error' => 'User %s cannot be created',	// TODO
 		),
 		'deleted' => array(
 			'_' => 'המשתמש %s נמחק',
-			'error' => 'User %s cannot be deleted',	// TODO - Translation
+			'error' => 'User %s cannot be deleted',	// TODO
 		),
 		'updated' => array(
-			'_' => 'User %s has been updated',	// TODO - Translation
-			'error' => 'User %s has not been updated',	// TODO - Translation
+			'_' => 'User %s has been updated',	// TODO
+			'error' => 'User %s has not been updated',	// TODO
 		),
 	),
 );

+ 108 - 98
app/i18n/he/gen.php

@@ -1,65 +1,75 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'מימוש',
-		'add' => 'Add',	// TODO - Translation
-		'back' => '← Go back',	// TODO - Translation
+		'add' => 'Add',	// TODO
+		'back' => '← Go back',	// TODO
 		'back_to_rss_feeds' => '← חזרה להזנות הRSS שלך',
 		'cancel' => 'ביטול',
 		'create' => 'יצירה',
-		'demote' => 'Demote',	// TODO - Translation
-		'disable' => 'Disable',	// TODO - Translation
-		'empty' => 'Empty',	// TODO - Translation
-		'enable' => 'Enable',	// TODO - Translation
+		'demote' => 'Demote',	// TODO
+		'disable' => 'Disable',	// TODO
+		'empty' => 'Empty',	// TODO
+		'enable' => 'Enable',	// TODO
 		'export' => 'ייצוא',
 		'filter' => 'מסנן',
 		'import' => 'ייבוא',
-		'load_default_shortcuts' => 'Load default shortcuts',	// TODO - Translation
+		'load_default_shortcuts' => 'Load default shortcuts',	// TODO
 		'manage' => 'ניהול',
 		'mark_read' => 'סימון כנקרא',
-		'promote' => 'Promote',	// TODO - Translation
-		'purge' => 'Purge',	// TODO - Translation
-		'remove' => 'Remove',	// TODO - Translation
-		'rename' => 'Rename',	// TODO - Translation
+		'promote' => 'Promote',	// TODO
+		'purge' => 'Purge',	// TODO
+		'remove' => 'Remove',	// TODO
+		'rename' => 'Rename',	// TODO
 		'see_website' => 'ראו אתר',
 		'submit' => 'אישור',
 		'truncate' => 'מחיקת כל המאמרים',
-		'update' => 'Update',	// TODO - Translation
+		'update' => 'Update',	// TODO
 	),
 	'auth' => array(
-		'accept_tos' => 'I accept the <a href="%s">Terms of Service</a>.',	// TODO - Translation
-		'email' => 'Email address',	// TODO - Translation
+		'accept_tos' => 'I accept the <a href="%s">Terms of Service</a>.',	// TODO
+		'email' => 'Email address',	// TODO
 		'keep_logged_in' => 'השאר מחובר <small>חודש</small>',
 		'login' => 'כניסה לחשבון',
 		'logout' => 'יציאה מהחשבון',
 		'password' => array(
 			'_' => 'סיסמה',
-			'format' => '<small>At least 7 characters</small>',	// TODO - Translation
+			'format' => '<small>At least 7 characters</small>',	// TODO
 		),
 		'registration' => array(
-			'_' => 'New account',	// TODO - Translation
-			'ask' => 'Create an account?',	// TODO - Translation
-			'title' => 'Account creation',	// TODO - Translation
+			'_' => 'New account',	// TODO
+			'ask' => 'Create an account?',	// TODO
+			'title' => 'Account creation',	// TODO
 		),
 		'username' => array(
 			'_' => 'שם משתמש',
-			'format' => '<small>Maximum 16 alphanumeric characters</small>',	// TODO - Translation
+			'format' => '<small>Maximum 16 alphanumeric characters</small>',	// TODO
 		),
 	),
 	'date' => array(
-		'Apr' => '\\A\\p\\r\\i\\l',	// TODO - Translation
-		'Aug' => '\\A\\u\\g\\u\\s\\t',	// TODO - Translation
-		'Dec' => '\\D\\e\\c\\e\\m\\b\\e\\r',	// TODO - Translation
-		'Feb' => '\\F\\e\\b\\r\\u\\a\\r\\y',	// TODO - Translation
-		'Jan' => '\\J\\a\\n\\u\\a\\r\\y',	// TODO - Translation
-		'Jul' => '\\J\\u\\l\\y',	// TODO - Translation
-		'Jun' => '\\J\\u\\n\\e',	// TODO - Translation
-		'Mar' => '\\M\\a\\r\\c\\h',	// TODO - Translation
-		'May' => '\\M\\a\\y',	// TODO - Translation
-		'Nov' => '\\N\\o\\v\\e\\m\\b\\e\\r',	// TODO - Translation
-		'Oct' => '\\O\\c\\t\\o\\b\\e\\r',	// TODO - Translation
-		'Sep' => '\\S\\e\\p\\t\\e\\m\\b\\e\\r',	// TODO - Translation
+		'Apr' => '\\A\\p\\r\\i\\l',	// TODO
+		'Aug' => '\\A\\u\\g\\u\\s\\t',	// TODO
+		'Dec' => '\\D\\e\\c\\e\\m\\b\\e\\r',	// TODO
+		'Feb' => '\\F\\e\\b\\r\\u\\a\\r\\y',	// TODO
+		'Jan' => '\\J\\a\\n\\u\\a\\r\\y',	// TODO
+		'Jul' => '\\J\\u\\l\\y',	// TODO
+		'Jun' => '\\J\\u\\n\\e',	// TODO
+		'Mar' => '\\M\\a\\r\\c\\h',	// TODO
+		'May' => '\\M\\a\\y',	// TODO
+		'Nov' => '\\N\\o\\v\\e\\m\\b\\e\\r',	// TODO
+		'Oct' => '\\O\\c\\t\\o\\b\\e\\r',	// TODO
+		'Sep' => '\\S\\e\\p\\t\\e\\m\\b\\e\\r',	// TODO
 		'apr' => 'apr',
 		'april' => 'Apr',
 		'aug' => 'aug',
@@ -69,90 +79,90 @@ return array(
 		'december' => 'Dec',
 		'feb' => 'feb',
 		'february' => 'Feb',
-		'format_date' => 'j %s Y',
-		'format_date_hour' => 'j %s Y \\a\\t H\\:i',
-		'fri' => 'Fri',	// TODO - Translation
+		'format_date' => 'j %s Y',	// IGNORE
+		'format_date_hour' => 'j %s Y \\a\\t H\\:i',	// IGNORE
+		'fri' => 'Fri',	// TODO
 		'jan' => 'jan',
 		'january' => 'Jan',
 		'jul' => 'jul',
 		'july' => 'Jul',
 		'jun' => 'jun',
 		'june' => 'Jun',
-		'last_2_year' => 'Last two years',	// TODO - Translation
+		'last_2_year' => 'Last two years',	// TODO
 		'last_3_month' => 'בשלושת החודשים האחרונים',
-		'last_3_year' => 'Last three years',	// TODO - Translation
-		'last_5_year' => 'Last five years',	// TODO - Translation
+		'last_3_year' => 'Last three years',	// TODO
+		'last_5_year' => 'Last five years',	// TODO
 		'last_6_month' => 'בששת החודשים האחרונים',
 		'last_month' => 'בחודש שעבר',
 		'last_week' => 'בשבוע שעבר',
 		'last_year' => 'בשנה האחרונה',
 		'mar' => 'mar',
 		'march' => 'Mar',
-		'may' => 'May',	// TODO - Translation
-		'may_' => 'May',	// TODO - Translation
-		'mon' => 'Mon',	// TODO - Translation
+		'may' => 'May',	// TODO
+		'may_' => 'May',	// TODO
+		'mon' => 'Mon',	// TODO
 		'month' => 'חודשים',
 		'nov' => 'nov',
 		'november' => 'Nov',
 		'oct' => 'oct',
 		'october' => 'Oct',
-		'sat' => 'Sat',	// TODO - Translation
+		'sat' => 'Sat',	// TODO
 		'sep' => 'sep',
 		'september' => 'Sep',
-		'sun' => 'Sun',	// TODO - Translation
-		'thu' => 'Thu',	// TODO - Translation
+		'sun' => 'Sun',	// TODO
+		'thu' => 'Thu',	// TODO
 		'today' => 'היום',
-		'tue' => 'Tue',	// TODO - Translation
-		'wed' => 'Wed',	// TODO - Translation
+		'tue' => 'Tue',	// TODO
+		'wed' => 'Wed',	// TODO
 		'yesterday' => 'אתמול',
 	),
 	'dir' => 'rtl',
 	'freshrss' => array(
-		'_' => 'FreshRSS',	// TODO - Translation
+		'_' => 'FreshRSS',	// TODO
 		'about' => 'אודות FreshRSS',
 	),
 	'js' => array(
-		'category_empty' => 'Empty category',	// TODO - Translation
+		'category_empty' => 'Empty category',	// TODO
 		'confirm_action' => 'האם אתם בטוחים שברצונכם לבצע פעולה זו? אין אפשרות לבטל אותה!',
 		'confirm_action_feed_cat' => 'האם אתם בטוחים שברצוניכם לבצע פעולה זו? מועדפים ושאילתות עשויות לאבוד. אין אפשרות לבטל אותה!',
 		'feedback' => array(
 			'body_new_articles' => 'ישנם	\\d מאמרים חדשים לקרוא ב FreshRSS.',
-			'request_failed' => 'A request has failed, it may have been caused by internet connection problems.',	// TODO - Translation
+			'request_failed' => 'A request has failed, it may have been caused by internet connection problems.',	// TODO
 			'title_new_articles' => 'FreshRSS: מאמרים חדשים!',
 		),
 		'new_article' => 'מאמרים חדשים זמינים, לחצו לרענון העמוד.',
 		'should_be_activated' => 'חובה להפעיל JavaScript',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'אודות',
-		'account' => 'Account',	// TODO - Translation
+		'account' => 'Account',	// TODO
 		'admin' => 'ניהול',
 		'archiving' => 'ארכוב',
-		'authentication' => 'Authentication',	// TODO - Translation
-		'check_install' => 'Installation check',	// TODO - Translation
+		'authentication' => 'Authentication',	// TODO
+		'check_install' => 'Installation check',	// TODO
 		'configuration' => 'הגדרות',
 		'display' => 'תצוגה',
-		'extensions' => 'Extensions',	// TODO - Translation
+		'extensions' => 'Extensions',	// TODO
 		'logs' => 'לוגים',
 		'queries' => 'שאילתות',
 		'reading' => 'קריאה',
@@ -160,10 +170,10 @@ return array(
 		'sharing' => 'שיתוף',
 		'shortcuts' => 'קיצורי דרך',
 		'stats' => 'סטטיסטיקות',
-		'system' => 'System configuration',	// TODO - Translation
+		'system' => 'System configuration',	// TODO
 		'update' => 'עדכון',
-		'user_management' => 'Manage users',	// TODO - Translation
-		'user_profile' => 'Profile',	// TODO - Translation
+		'user_management' => 'Manage users',	// TODO
+		'user_profile' => 'Profile',	// TODO
 	),
 	'pagination' => array(
 		'first' => 'הראשון',
@@ -175,33 +185,33 @@ return array(
 		'previous' => 'הקודם',
 	),
 	'period' => array(
-		'days' => 'days',	// TODO - Translation
-		'hours' => 'hours',	// TODO - Translation
-		'months' => 'months',	// TODO - Translation
-		'weeks' => 'weeks',	// TODO - Translation
-		'years' => 'years',	// TODO - Translation
+		'days' => 'days',	// TODO
+		'hours' => 'hours',	// TODO
+		'months' => 'months',	// TODO
+		'weeks' => 'weeks',	// TODO
+		'years' => 'years',	// TODO
 	),
 	'share' => array(
-		'Known' => 'Known based sites',	// TODO - Translation
-		'blogotext' => 'Blogotext',
-		'clipboard' => 'Clipboard',	// TODO - Translation
-		'diaspora' => 'Diaspora*',
+		'Known' => 'Known based sites',	// TODO
+		'blogotext' => 'Blogotext',	// IGNORE
+		'clipboard' => 'Clipboard',	// TODO
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'דואר אלקטרוני',
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
 		'print' => 'הדפסה',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => 'זהירות!',
@@ -210,8 +220,8 @@ return array(
 		'by_default' => 'ברירת מחדל',
 		'damn' => 'הו לא!',
 		'default_category' => 'ללא קטגוריה',
-		'no' => 'לא',
-		'not_applicable' => 'Not available',	// TODO - Translation
+		'no' => 'לא',	// IGNORE
+		'not_applicable' => 'Not available',	// TODO
 		'ok' => 'כן!',
 		'or' => 'או',
 		'yes' => 'כן',

+ 15 - 5
app/i18n/he/index.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => 'אודות',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
 		'bugs_reports' => 'דיווח באגים',
 		'credits' => 'קרדיטים',
 		'credits_content' => 'מאפייני עיצוב מסויימים הגיעו מ <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> אף על פי ש FreshRSS אינו משתמש בתשתית הזו. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">סמלילים</a> הגיעו מ <a href="https://www.gnome.org/"> פרוייקט GNOME </a>. <em>Open Sans</em> הגופן police נוצר על ידי <a href="https://www.google.com/webfonts/specimen/Open+Sans">Steve Matteson</a>. Favicons נאספים בעזרת <a href="https://getfavicon.appspot.com/">getFavicon API</a>. FreshRSS מבוסס על <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, תשתית PHP.',
@@ -32,14 +42,14 @@ return array(
 		'about' => 'אודות FreshRSS',
 		'before_one_day' => 'אתמול',
 		'before_one_week' => 'לפני שבוע',
-		'bookmark_query' => 'Bookmark current query',	// TODO - Translation
+		'bookmark_query' => 'Bookmark current query',	// TODO
 		'favorites' => 'מועדפים (%s)',
 		'global_view' => 'תצוגה גלובלית',
 		'main_stream' => 'הזנה ראשית',
 		'mark_all_read' => 'סימון הכל כנקרא',
 		'mark_cat_read' => 'סימון קטגוריה כנקראה',
 		'mark_feed_read' => 'סימון הזנה כנקראה',
-		'mark_selection_unread' => 'Mark selection as unread',	// TODO - Translation
+		'mark_selection_unread' => 'Mark selection as unread',	// TODO
 		'newer_first' => 'חדשים בראש',
 		'non-starred' => 'הצגת הכל פרט למועדפים',
 		'normal_view' => 'תצוגה רגילה',
@@ -52,7 +62,7 @@ return array(
 		'starred' => 'הצגת מועדפים בלבד',
 		'stats' => 'סטטיסטיקות',
 		'subscription' => 'ניהול הרשמות',
-		'tags' => 'My labels',	// TODO - Translation
+		'tags' => 'My labels',	// TODO
 		'unread' => 'הצגת מאמרים שלא נקראו בלבד',
 	),
 	'share' => 'שיתוף',
@@ -60,6 +70,6 @@ return array(
 		'related' => 'תגיות קשורות',
 	),
 	'tos' => array(
-		'title' => 'Terms of Service',	// TODO - Translation
+		'title' => 'Terms of Service',	// TODO
 	),
 );

+ 32 - 22
app/i18n/he/install.php

@@ -1,19 +1,29 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => 'השלמת ההתקנה',
 		'fix_errors_before' => 'יש לתקן את השגיאות לפני המעבר לשלב הבא.',
-		'keep_install' => 'Keep previous configuration',	// TODO - Translation
+		'keep_install' => 'Keep previous configuration',	// TODO
 		'next_step' => 'לשלב הבא',
-		'reinstall' => 'Reinstall FreshRSS',	// TODO - Translation
+		'reinstall' => 'Reinstall FreshRSS',	// TODO
 	),
 	'auth' => array(
 		'form' => 'טופס אינטרנטי (מסורתי, דורש JavaScript)',
 		'http' => 'HTTP (למשתמשים מתקדמים עם HTTPS)',
 		'none' => 'ללא (מסוכן)',
 		'password_form' => 'סיסמה<br /><small>(לשימוש בטפוס ההרשמה)</small>',
-		'password_format' => 'At least 7 characters',	// TODO - Translation
+		'password_format' => 'At least 7 characters',	// TODO
 		'type' => 'שיטת אימות',
 	),
 	'bdd' => array(
@@ -31,7 +41,7 @@ return array(
 	),
 	'check' => array(
 		'_' => 'בדיקות',
-		'already_installed' => 'We have detected that FreshRSS is already installed!',	// TODO - Translation
+		'already_installed' => 'We have detected that FreshRSS is already installed!',	// TODO
 		'cache' => array(
 			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',
 			'ok' => 'ההרשאות בתיקיית המטמון תקינות',
@@ -57,16 +67,16 @@ return array(
 			'ok' => 'ההרשאות בתיקיית הfavicons תקינות',
 		),
 		'fileinfo' => array(
-			'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',	// TODO - Translation
-			'ok' => 'You have the fileinfo library.',	// TODO - Translation
+			'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',	// TODO
+			'ok' => 'You have the fileinfo library.',	// TODO
 		),
 		'json' => array(
-			'nok' => 'Cannot find the recommended library to parse JSON.',	// TODO - Translation
-			'ok' => 'You have the recommended library to parse JSON.',	// TODO - Translation
+			'nok' => 'Cannot find the recommended library to parse JSON.',	// TODO
+			'ok' => 'You have the recommended library to parse JSON.',	// TODO
 		),
 		'mbstring' => array(
-			'nok' => 'Cannot find the recommended library mbstring for Unicode.',	// TODO - Translation
-			'ok' => 'You have the recommended library mbstring for Unicode.',	// TODO - Translation
+			'nok' => 'Cannot find the recommended library mbstring for Unicode.',	// TODO
+			'ok' => 'You have the recommended library mbstring for Unicode.',	// TODO
 		),
 		'pcre' => array(
 			'nok' => 'הספרייה הנדרשת לביטויים רגולריים אינה מותקנת (php-pcre)',
@@ -82,17 +92,17 @@ return array(
 		),
 		'reload' => 'בדוק שוב',
 		'tmp' => array(
-			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',	// TODO - Translation
-			'ok' => 'Permissions on the temp directory are good.',	// TODO - Translation
+			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',	// TODO
+			'ok' => 'Permissions on the temp directory are good.',	// TODO
 		),
-		'unknown_process_username' => 'unknown',	// TODO - Translation
+		'unknown_process_username' => 'unknown',	// TODO
 		'users' => array(
-			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',	// TODO - Translation
-			'ok' => 'Permissions on the users directory are good.',	// TODO - Translation
+			'nok' => 'Check permissions on the <em>%1$s</em> directory for <em>%2$s</em> user. The HTTP server must have write permissions.',	// TODO
+			'ok' => 'Permissions on the users directory are good.',	// TODO
 		),
 		'xml' => array(
-			'nok' => 'Cannot find the required library to parse XML.',	// TODO - Translation
-			'ok' => 'You have the required library to parse XML.',	// TODO - Translation
+			'nok' => 'Cannot find the required library to parse XML.',	// TODO
+			'ok' => 'You have the required library to parse XML.',	// TODO
 		),
 	),
 	'conf' => array(
@@ -104,19 +114,19 @@ return array(
 	'fix_errors_before' => 'יש לתקן את השגיאות לפני המעבר לשלב הבא.',
 	'javascript_is_better' => 'FreshRSS מעדיף שתאפשרו JavaScript',
 	'js' => array(
-		'confirm_reinstall' => 'You will lose your previous configuration by reinstalling FreshRSS. Are you sure you want to continue?',	// TODO - Translation
+		'confirm_reinstall' => 'You will lose your previous configuration by reinstalling FreshRSS. Are you sure you want to continue?',	// TODO
 	),
 	'language' => array(
 		'_' => 'שפה',
 		'choose' => 'בחירת שפה ל FreshRSS',
 		'defined' => 'השפה הוגדרה.',
 	),
-	'missing_applied_migrations' => 'Something went wrong; you should create an empty file <em>%s</em> manually.',	// TODO - Translation
-	'ok' => 'The installation process was successful.',	// TODO - Translation
+	'missing_applied_migrations' => 'Something went wrong; you should create an empty file <em>%s</em> manually.',	// TODO
+	'ok' => 'The installation process was successful.',	// TODO
 	'session' => array(
-		'nok' => 'The web server seems to be incorrectly configured for cookies required for PHP sessions!',	// TODO - Translation
+		'nok' => 'The web server seems to be incorrectly configured for cookies required for PHP sessions!',	// TODO
 	),
-	'step' => 'step %d',	// TODO - Translation
+	'step' => 'step %d',	// TODO
 	'steps' => 'שלבים',
 	'this_is_the_end' => 'סיום',
 	'title' => 'התקנה · FreshRSS',

+ 63 - 53
app/i18n/he/sub.php

@@ -1,23 +1,33 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
-		'documentation' => 'Copy the following URL to use it within an external tool.',	// TODO - Translation
-		'title' => 'API',	// TODO - Translation
+		'documentation' => 'Copy the following URL to use it within an external tool.',	// TODO
+		'title' => 'API',	// TODO
 	),
 	'bookmarklet' => array(
-		'documentation' => 'Drag this button to your bookmarks toolbar or right-click it and choose "Bookmark This Link". Then click the "Subscribe" button in any page you want to subscribe to.',	// TODO - Translation
-		'label' => 'Subscribe',	// TODO - Translation
-		'title' => 'Bookmarklet',	// TODO - Translation
+		'documentation' => 'Drag this button to your bookmarks toolbar or right-click it and choose "Bookmark This Link". Then click the "Subscribe" button in any page you want to subscribe to.',	// TODO
+		'label' => 'Subscribe',	// TODO
+		'title' => 'Bookmarklet',	// TODO
 	),
 	'category' => array(
 		'_' => 'קטגוריה',
-		'add' => 'Add a category',	// TODO - Translation
+		'add' => 'Add a category',	// TODO
 		'archiving' => 'ארכוב',
-		'empty' => 'Empty category',	// TODO - Translation
+		'empty' => 'Empty category',	// TODO
 		'information' => 'מידע',
-		'position' => 'Display position',	// TODO - Translation
-		'position_help' => 'To control category sort order',	// TODO - Translation
+		'position' => 'Display position',	// TODO
+		'position_help' => 'To control category sort order',	// TODO
 		'title' => 'כותרת',
 	),
 	'feed' => array(
@@ -31,73 +41,73 @@ return array(
 			'password' => 'HTTP סיסמה',
 			'username' => 'HTTP שם משתמש',
 		),
-		'clear_cache' => 'Always clear cache',	// TODO - Translation
+		'clear_cache' => 'Always clear cache',	// TODO
 		'content_action' => array(
-			'_' => 'Content action when fetching the article content',	// TODO - Translation
-			'append' => 'Add after existing content',	// TODO - Translation
-			'prepend' => 'Add before existing content',	// TODO - Translation
-			'replace' => 'Replace existing content',	// TODO - Translation
+			'_' => 'Content action when fetching the article content',	// TODO
+			'append' => 'Add after existing content',	// TODO
+			'prepend' => 'Add before existing content',	// TODO
+			'replace' => 'Replace existing content',	// TODO
 		),
-		'css_cookie' => 'Use Cookies when fetching the article content',	// TODO - Translation
-		'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',	// TODO - Translation
+		'css_cookie' => 'Use Cookies when fetching the article content',	// TODO
+		'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',	// TODO
 		'css_help' => 'קבלת הזנות RSS קטומות	(זהירות, לוקח זמן רב יותר!)',
 		'css_path' => 'נתיב הCSS של המאמר באתר המקורי',
 		'description' => 'תיאור',
 		'empty' => 'הזנה זו ריקה. אנא ודאו שהיא עדיין מתוחזקת.',
 		'error' => 'הזנה זו נתקלה בשגיאה, אנא ודאו שהיא תקינה ואז נסו שנית.',
 		'filteractions' => array(
-			'_' => 'Filter actions',	// TODO - Translation
-			'help' => 'Write one search filter per line.',	// TODO - Translation
+			'_' => 'Filter actions',	// TODO
+			'help' => 'Write one search filter per line.',	// TODO
 		),
 		'information' => 'מידע',
 		'keep_min' => 'מסםר מינימלי של מאמרים לשמור',
 		'maintenance' => array(
-			'clear_cache' => 'Clear cache',	// TODO - Translation
-			'clear_cache_help' => 'Clear the cache for this feed.',	// TODO - Translation
-			'reload_articles' => 'Reload articles',	// TODO - Translation
-			'reload_articles_help' => 'Reload articles and fetch complete content if a selector is defined.',	// TODO - Translation
-			'title' => 'Maintenance',	// TODO - Translation
+			'clear_cache' => 'Clear cache',	// TODO
+			'clear_cache_help' => 'Clear the cache for this feed.',	// TODO
+			'reload_articles' => 'Reload articles',	// TODO
+			'reload_articles_help' => 'Reload articles and fetch complete content if a selector is defined.',	// TODO
+			'title' => 'Maintenance',	// TODO
 		),
 		'moved_category_deleted' => 'כאשר הקטגוריה נמחקת ההזנות שבתוכה אוטומטית מקוטלגות תחת	<em>%s</em>.',
-		'mute' => 'mute',	// TODO - Translation
+		'mute' => 'mute',	// TODO
 		'no_selected' => 'אף הזנה לא נבחרה.',
 		'number_entries' => '%d מאמרים',
 		'priority' => array(
-			'_' => 'Visibility',	// TODO - Translation
-			'archived' => 'Do not show (archived)',	// TODO - Translation
+			'_' => 'Visibility',	// TODO
+			'archived' => 'Do not show (archived)',	// TODO
 			'main_stream' => 'הצגה בזרם המרכזי',
-			'normal' => 'Show in its category',	// TODO - Translation
+			'normal' => 'Show in its category',	// TODO
 		),
-		'proxy' => 'Set a proxy for fetching this feed',	// TODO - Translation
-		'proxy_help' => 'Select a protocol (e.g: SOCKS5) and enter the proxy address (e.g: <kbd>127.0.0.1:1080</kbd>)',	// TODO - Translation
+		'proxy' => 'Set a proxy for fetching this feed',	// TODO
+		'proxy_help' => 'Select a protocol (e.g: SOCKS5) and enter the proxy address (e.g: <kbd>127.0.0.1:1080</kbd>)',	// TODO
 		'selector_preview' => array(
-			'show_raw' => 'Show source code',	// TODO - Translation
-			'show_rendered' => 'Show content',	// TODO - Translation
+			'show_raw' => 'Show source code',	// TODO
+			'show_rendered' => 'Show content',	// TODO
 		),
 		'show' => array(
-			'all' => 'Show all feeds',	// TODO - Translation
-			'error' => 'Show only feeds with errors',	// TODO - Translation
+			'all' => 'Show all feeds',	// TODO
+			'error' => 'Show only feeds with errors',	// TODO
 		),
 		'showing' => array(
-			'error' => 'Showing only feeds with errors',	// TODO - Translation
+			'error' => 'Showing only feeds with errors',	// TODO
 		),
-		'ssl_verify' => 'Verify SSL security',	// TODO - Translation
+		'ssl_verify' => 'Verify SSL security',	// TODO
 		'stats' => 'סטטיסטיקות',
 		'think_to_add' => 'ניתן להוסיף הזנות חדשות.',
-		'timeout' => 'Timeout in seconds',	// TODO - Translation
+		'timeout' => 'Timeout in seconds',	// TODO
 		'title' => 'כותרת',
 		'title_add' => 'הוספת הזנה',
 		'ttl' => 'אין לרענן אוטומטית יותר מ',
 		'url' => 'הזנה URL',
-		'useragent' => 'Set the user agent for fetching this feed',	// TODO - Translation
-		'useragent_help' => 'Example: <kbd>Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0)</kbd>',	// TODO - Translation
+		'useragent' => 'Set the user agent for fetching this feed',	// TODO
+		'useragent_help' => 'Example: <kbd>Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0)</kbd>',	// TODO
 		'validator' => 'בדיקות תקינות ההזנה',
 		'website' => 'אתר URL',
-		'websub' => 'Instant notification with WebSub',	// TODO - Translation
+		'websub' => 'Instant notification with WebSub',	// TODO
 	),
 	'import_export' => array(
 		'export' => 'ייצוא',
-		'export_labelled' => 'Export your labelled articles',	// TODO - Translation
+		'export_labelled' => 'Export your labelled articles',	// TODO
 		'export_opml' => 'ייצוא רשימת הזנות (OPML)',
 		'export_starred' => 'ייצוא מועדפים',
 		'feed_list' => 'רשימה של %s מאמרים',
@@ -108,31 +118,31 @@ return array(
 		'title' => 'יבוא / יצוא ',
 	),
 	'menu' => array(
-		'add' => 'Add a feed or category',	// TODO - Translation
+		'add' => 'Add a feed or category',	// TODO
 		'import_export' => 'יבוא / יצוא ',
-		'label_management' => 'Label management',	// TODO - Translation
+		'label_management' => 'Label management',	// TODO
 		'stats' => array(
 			'idle' => 'הזנות שלא עודכנו',
 			'main' => 'סטטיסטיקות ראשיות',
 			'repartition' => 'חלוקת המאמרים',
 		),
 		'subscription_management' => 'ניהול הרשמות',
-		'subscription_tools' => 'Subscription tools',	// TODO - Translation
+		'subscription_tools' => 'Subscription tools',	// TODO
 	),
 	'tag' => array(
-		'name' => 'Name',	// TODO - Translation
-		'new_name' => 'New name',	// TODO - Translation
-		'old_name' => 'Old name',	// TODO - Translation
+		'name' => 'Name',	// TODO
+		'new_name' => 'New name',	// TODO
+		'old_name' => 'Old name',	// TODO
 	),
 	'title' => array(
 		'_' => 'ניהול הרשמות',
-		'add' => 'Add a feed or category',	// TODO - Translation
-		'add_category' => 'Add a category',	// TODO - Translation
-		'add_feed' => 'Add a feed',	// TODO - Translation
-		'add_label' => 'Add a label',	// TODO - Translation
-		'delete_label' => 'Delete a label',	// TODO - Translation
+		'add' => 'Add a feed or category',	// TODO
+		'add_category' => 'Add a category',	// TODO
+		'add_feed' => 'Add a feed',	// TODO
+		'add_label' => 'Add a label',	// TODO
+		'delete_label' => 'Delete a label',	// TODO
 		'feed_management' => 'ניהול הזנות RSS',
-		'rename_label' => 'Rename a label',	// TODO - Translation
-		'subscription_tools' => 'Subscription tools',	// TODO - Translation
+		'rename_label' => 'Rename a label',	// TODO
+		'subscription_tools' => 'Subscription tools',	// TODO
 	),
 );

+ 30 - 20
app/i18n/he/user.php

@@ -1,44 +1,54 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(
-			'invalid' => 'This email address is invalid.',	// TODO - Translation
-			'required' => 'An email address is required.',	// TODO - Translation
+			'invalid' => 'This email address is invalid.',	// TODO
+			'required' => 'An email address is required.',	// TODO
 		),
 		'validation' => array(
-			'change_email' => 'You can change your email address <a href="%s">on the profile page</a>.',	// TODO - Translation
-			'email_sent_to' => 'We sent you an email at <strong>%s</strong>. Please follow its instructions to validate your address.',	// TODO - Translation
+			'change_email' => 'You can change your email address <a href="%s">on the profile page</a>.',	// TODO
+			'email_sent_to' => 'We sent you an email at <strong>%s</strong>. Please follow its instructions to validate your address.',	// TODO
 			'feedback' => array(
-				'email_failed' => 'We couldn’t send you an email because of a server configuration error.',	// TODO - Translation
-				'email_sent' => 'An email has been sent to your address.',	// TODO - Translation
-				'error' => 'Email address validation failed.',	// TODO - Translation
-				'ok' => 'This email address has been validated.',	// TODO - Translation
-				'unnecessary' => 'This email address was already validated.',	// TODO - Translation
-				'wrong_token' => 'This email address failed to be validated due to a wrong token.',	// TODO - Translation
+				'email_failed' => 'We couldn’t send you an email because of a server configuration error.',	// TODO
+				'email_sent' => 'An email has been sent to your address.',	// TODO
+				'error' => 'Email address validation failed.',	// TODO
+				'ok' => 'This email address has been validated.',	// TODO
+				'unnecessary' => 'This email address was already validated.',	// TODO
+				'wrong_token' => 'This email address failed to be validated due to a wrong token.',	// TODO
 			),
-			'need_to' => 'You need to validate your email address before being able to use %s.',	// TODO - Translation
-			'resend_email' => 'Resend the email',	// TODO - Translation
-			'title' => 'Email address validation',	// TODO - Translation
+			'need_to' => 'You need to validate your email address before being able to use %s.',	// TODO
+			'resend_email' => 'Resend the email',	// TODO
+			'title' => 'Email address validation',	// TODO
 		),
 	),
 	'mailer' => array(
 		'email_need_validation' => array(
-			'body' => 'You’ve just registered on %s, but you still need to validate your email address. For that, just follow the link:',	// TODO - Translation
-			'title' => 'You need to validate your account',	// TODO - Translation
-			'welcome' => 'Welcome %s,',	// TODO - Translation
+			'body' => 'You’ve just registered on %s, but you still need to validate your email address. For that, just follow the link:',	// TODO
+			'title' => 'You need to validate your account',	// TODO
+			'welcome' => 'Welcome %s,',	// TODO
 		),
 	),
 	'password' => array(
-		'invalid' => 'The password is invalid.',	// TODO - Translation
+		'invalid' => 'The password is invalid.',	// TODO
 	),
 	'tos' => array(
 		'feedback' => array(
-			'invalid' => 'You must accept the Terms of Service to be able to register.',	// TODO - Translation
+			'invalid' => 'You must accept the Terms of Service to be able to register.',	// TODO
 		),
 	),
 	'username' => array(
-		'invalid' => 'This username is invalid.',	// TODO - Translation
-		'taken' => 'This username, %s, is taken.',	// TODO - Translation
+		'invalid' => 'This username is invalid.',	// TODO
+		'taken' => 'This username, %s, is taken.',	// TODO
 	),
 );

+ 21 - 11
app/i18n/it/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => 'Consenti la lettura agli utenti anonimi degli articoli dell utente predefinito (%s)',
@@ -130,7 +140,7 @@ return array(
 		'entry_per_hour' => 'Per ora (media: %.2f articoli)',
 		'entry_per_month' => 'Per mese (media: %.2f articoli)',
 		'entry_repartition' => 'Ripartizione contenuti',
-		'feed' => 'Feed',	// TODO - Translation
+		'feed' => 'Feed',	// TODO
 		'feed_per_category' => 'Feeds per categoria',
 		'idle' => 'Feeds non aggiornati',
 		'main' => 'Statistiche principali',
@@ -148,12 +158,12 @@ return array(
 	),
 	'system' => array(
 		'_' => 'Configurazione di sistema',
-		'auto-update-url' => 'Auto-update server URL',	// TODO - Translation
+		'auto-update-url' => 'Auto-update server URL',	// TODO
 		'cookie-duration' => array(
-			'help' => 'in seconds',	// TODO - Translation
-			'number' => 'Duration to keep logged in',	// TODO - Translation
+			'help' => 'in seconds',	// TODO
+			'number' => 'Duration to keep logged in',	// TODO
 		),
-		'force_email_validation' => 'Force email address validation',	// TODO - Translation
+		'force_email_validation' => 'Force email address validation',	// TODO
 		'instance-name' => 'Nome istanza',
 		'max-categories' => 'Limite categorie per utente',
 		'max-feeds' => 'Limite feeds per utente',
@@ -174,16 +184,16 @@ return array(
 	'user' => array(
 		'admin' => 'Amministratore',
 		'article_count' => 'Articoli',
-		'back_to_manage' => '← Return to user list',	// TODO - Translation
+		'back_to_manage' => '← Return to user list',	// TODO
 		'create' => 'Crea nuovo utente',
-		'database_size' => 'Database size',	// TODO - Translation
+		'database_size' => 'Database size',	// TODO
 		'email' => 'Indirizzo e-mail',
-		'enabled' => 'Enabled',	// TODO - Translation
-		'feed_count' => 'Feeds',	// TODO - Translation
-		'is_admin' => 'Is admin',	// TODO - Translation
+		'enabled' => 'Enabled',	// TODO
+		'feed_count' => 'Feeds',	// TODO
+		'is_admin' => 'Is admin',	// TODO
 		'language' => 'Lingua',
 		'last_user_activity' => 'Ultime attività degli utenti',
-		'list' => 'User list',	// TODO - Translation
+		'list' => 'User list',	// TODO
 		'number' => ' %d profilo utente creato',
 		'numbers' => 'Sono presenti %d profili utente',
 		'password_form' => 'Password<br /><small>(per il login classico)</small>',

+ 69 - 59
app/i18n/it/conf.php

@@ -1,21 +1,31 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'Archiviazione',
-		'exception' => 'Purge exception',	// TODO - Translation
+		'exception' => 'Purge exception',	// TODO
 		'help' => 'Altre opzioni sono disponibili nelle impostazioni dei singoli feed',
-		'keep_favourites' => 'Never delete favourites',	// TODO - Translation
-		'keep_labels' => 'Never delete labels',	// TODO - Translation
-		'keep_max' => 'Maximum number of articles to keep',	// TODO - Translation
+		'keep_favourites' => 'Never delete favourites',	// TODO
+		'keep_labels' => 'Never delete labels',	// TODO
+		'keep_max' => 'Maximum number of articles to keep',	// TODO
 		'keep_min_by_feed' => 'Numero minimo di articoli da mantenere per feed',
-		'keep_period' => 'Maximum age of articles to keep',	// TODO - Translation
-		'keep_unreads' => 'Never delete unread articles',	// TODO - Translation
-		'maintenance' => 'Maintenance',	// TODO - Translation
+		'keep_period' => 'Maximum age of articles to keep',	// TODO
+		'keep_unreads' => 'Never delete unread articles',	// TODO
+		'maintenance' => 'Maintenance',	// TODO
 		'optimize' => 'Ottimizza database',
 		'optimize_help' => 'Da fare occasionalmente per ridurre le dimensioni del database',
-		'policy' => 'Purge policy',	// TODO - Translation
-		'policy_warning' => 'If no purge policy is selected, every article will be kept.',	// TODO - Translation
+		'policy' => 'Purge policy',	// TODO
+		'policy_warning' => 'If no purge policy is selected, every article will be kept.',	// TODO
 		'purge_now' => 'Cancella ora',
 		'title' => 'Archiviazione',
 		'ttl' => 'Non effettuare aggiornamenti per più di',
@@ -24,12 +34,12 @@ return array(
 		'_' => 'Visualizzazione',
 		'icon' => array(
 			'bottom_line' => 'Barra in fondo',
-			'display_authors' => 'Authors',	// TODO - Translation
+			'display_authors' => 'Authors',	// TODO
 			'entry' => 'Icone degli articoli',
 			'publication_date' => 'Data di pubblicazione',
 			'related_tags' => 'Tags correlati',
 			'sharing' => 'Condivisione',
-			'summary' => 'Summary',	// TODO - Translation
+			'summary' => 'Summary',	// TODO
 			'top_line' => 'Barra in alto',
 		),
 		'language' => 'Lingua',
@@ -37,15 +47,15 @@ return array(
 			'seconds' => 'secondi (0 significa nessun timeout)',
 			'timeout' => 'Notifica timeout HTML5',
 		),
-		'show_nav_buttons' => 'Show the navigation buttons',	// TODO - Translation
+		'show_nav_buttons' => 'Show the navigation buttons',	// TODO
 		'theme' => 'Tema',
-		'theme_not_available' => 'The “%s” theme is not available anymore. Please choose another theme.',	// TODO - Translation
+		'theme_not_available' => 'The “%s” theme is not available anymore. Please choose another theme.',	// TODO
 		'thumbnail' => array(
-			'label' => 'Thumbnail',	// TODO - Translation
-			'landscape' => 'Landscape',	// TODO - Translation
-			'none' => 'None',	// TODO - Translation
-			'portrait' => 'Portrait',	// TODO - Translation
-			'square' => 'Square',	// TODO - Translation
+			'label' => 'Thumbnail',	// TODO
+			'landscape' => 'Landscape',	// TODO
+			'none' => 'None',	// TODO
+			'portrait' => 'Portrait',	// TODO
+			'square' => 'Square',	// TODO
 		),
 		'title' => 'Visualizzazione',
 		'width' => array(
@@ -58,7 +68,7 @@ return array(
 	),
 	'profile' => array(
 		'_' => 'Gestione profili',
-		'api' => 'API management',	// TODO - Translation
+		'api' => 'API management',	// TODO
 		'delete' => array(
 			'_' => 'Cancellazione account',
 			'warn' => 'Il tuo account e tutti i dati associati saranno cancellati.',
@@ -74,19 +84,19 @@ return array(
 		'deprecated' => 'Questa query non è più valida. La categoria o il feed di riferimento non stati cancellati.',
 		'filter' => array(
 			'_' => 'Filtro applicato:',
-			'categories' => 'Display by category',	// TODO - Translation
-			'feeds' => 'Display by feed',	// TODO - Translation
-			'order' => 'Sort by date',	// TODO - Translation
-			'search' => 'Expression',	// TODO - Translation
-			'state' => 'State',	// TODO - Translation
-			'tags' => 'Display by tag',	// TODO - Translation
-			'type' => 'Type',	// TODO - Translation
+			'categories' => 'Display by category',	// TODO
+			'feeds' => 'Display by feed',	// TODO
+			'order' => 'Sort by date',	// TODO
+			'search' => 'Expression',	// TODO
+			'state' => 'State',	// TODO
+			'tags' => 'Display by tag',	// TODO
+			'type' => 'Type',	// TODO
 		),
 		'get_all' => 'Mostra tutti gli articoli',
 		'get_category' => 'Mostra la categoria "%s" ',
 		'get_favorite' => 'Mostra articoli preferiti',
 		'get_feed' => 'Mostra feed "%s" ',
-		'name' => 'Name',	// TODO - Translation
+		'name' => 'Name',	// TODO
 		'no_filter' => 'Nessun filtro',
 		'number' => 'Ricerca n°%d',
 		'order_asc' => 'Mostra prima gli articoli più vecchi',
@@ -113,13 +123,13 @@ return array(
 	'reading' => array(
 		'_' => 'Lettura',
 		'after_onread' => 'Dopo “segna tutto come letto”,',
-		'always_show_favorites' => 'Show all articles in favourites by default',	// TODO - Translation
+		'always_show_favorites' => 'Show all articles in favourites by default',	// TODO
 		'articles_per_page' => 'Numero di articoli per pagina',
 		'auto_load_more' => 'Carica articoli successivi a fondo pagina',
 		'auto_remove_article' => 'Nascondi articoli dopo la lettura',
 		'confirm_enabled' => 'Mostra una conferma per “segna tutto come letto”',
 		'display_articles_unfolded' => 'Mostra articoli aperti di predefinito',
-		'display_categories_unfolded' => 'Categories to unfold',	// TODO - Translation
+		'display_categories_unfolded' => 'Categories to unfold',	// TODO
 		'hide_read_feeds' => 'Nascondi categorie e feeds con articoli già letti (non funziona se “Mostra tutti gli articoli” è selezionato)',
 		'img_with_lazyload' => 'Usa la modalità "caricamento ritardato" per le immagini',
 		'jump_next' => 'Salta al successivo feed o categoria non letto',
@@ -128,24 +138,24 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'Quando un articolo è aperto nel suo sito di origine',
 			'article_viewed' => 'Quando un articolo viene letto',
-			'keep_max_n_unread' => 'Max number of articles to keep unread',	// TODO - Translation
+			'keep_max_n_unread' => 'Max number of articles to keep unread',	// TODO
 			'scroll' => 'Scorrendo la pagina',
 			'upon_reception' => 'Alla ricezione del contenuto',
 			'when' => 'Segna articoli come letti…',
-			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',	// TODO - Translation
+			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',	// TODO
 		),
 		'show' => array(
 			'_' => 'Articoli da visualizzare',
-			'active_category' => 'Active category',	// TODO - Translation
+			'active_category' => 'Active category',	// TODO
 			'adaptive' => 'Adatta visualizzazione',
 			'all_articles' => 'Mostra tutti gli articoli',
-			'all_categories' => 'All categories',	// TODO - Translation
-			'no_category' => 'No category',	// TODO - Translation
-			'remember_categories' => 'Remember open categories',	// TODO - Translation
+			'all_categories' => 'All categories',	// TODO
+			'no_category' => 'No category',	// TODO
+			'remember_categories' => 'Remember open categories',	// TODO
 			'unread' => 'Mostra solo non letti',
 		),
-		'show_fav_unread_help' => 'Applies also on labels',	// TODO - Translation
-		'sides_close_article' => 'Clicking outside of article text area closes the article',	// TODO - Translation
+		'show_fav_unread_help' => 'Applies also on labels',	// TODO
+		'sides_close_article' => 'Clicking outside of article text area closes the article',	// TODO
 		'sort' => array(
 			'_' => 'Ordinamento',
 			'newer_first' => 'Prima i più recenti',
@@ -162,21 +172,21 @@ return array(
 	),
 	'sharing' => array(
 		'_' => 'Condivisione',
-		'add' => 'Add a sharing method',	// TODO - Translation
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
-		'email' => 'Email',	// TODO - Translation
-		'facebook' => 'Facebook',
+		'add' => 'Add a sharing method',	// TODO
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
+		'email' => 'Email',	// TODO
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => 'Ulteriori informazioni',
 		'print' => 'Stampa',
-		'raindrop' => 'Raindrop.io',
-		'remove' => 'Remove sharing method',	// TODO - Translation
-		'shaarli' => 'Shaarli',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'remove' => 'Remove sharing method',	// TODO
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => 'Nome condivisione',
 		'share_url' => 'URL condivisione',
 		'title' => 'Condividi',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => 'Comandi tastiera',
@@ -187,7 +197,7 @@ return array(
 		'collapse_article' => 'Collassa articoli',
 		'first_article' => 'Salta al primo articolo',
 		'focus_search' => 'Modulo di ricerca',
-		'global_view' => 'Switch to global view',	// TODO - Translation
+		'global_view' => 'Switch to global view',	// TODO
 		'help' => 'Mostra documentazione',
 		'javascript' => 'JavaScript deve essere abilitato per poter usare i comandi da tastiera',
 		'last_article' => 'Salta all ultimo articolo',
@@ -196,24 +206,24 @@ return array(
 		'mark_read' => 'Segna come letto',
 		'navigation' => 'Navigazione',
 		'navigation_help' => 'Con il tasto <kbd>⇧ Shift</kbd> i comandi di navigazione verranno applicati ai feeds.<br/>Con il tasto <kbd>Alt ⎇</kbd> i comandi di navigazione verranno applicati alle categorie.',
-		'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.',	// TODO - Translation
+		'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.',	// TODO
 		'next_article' => 'Salta al contenuto successivo',
-		'next_unread_article' => 'Open the next unread article',	// TODO - Translation
-		'non_standard' => 'Some keys (<kbd>%s</kbd>) may not work as shortcuts.',	// TODO - Translation
-		'normal_view' => 'Switch to normal view',	// TODO - Translation
+		'next_unread_article' => 'Open the next unread article',	// TODO
+		'non_standard' => 'Some keys (<kbd>%s</kbd>) may not work as shortcuts.',	// TODO
+		'normal_view' => 'Switch to normal view',	// TODO
 		'other_action' => 'Altre azioni',
 		'previous_article' => 'Salta al contenuto precedente',
-		'reading_view' => 'Switch to reading view',	// TODO - Translation
-		'rss_view' => 'Open as RSS feed',	// TODO - Translation
+		'reading_view' => 'Switch to reading view',	// TODO
+		'rss_view' => 'Open as RSS feed',	// TODO
 		'see_on_website' => 'Vai al sito fonte',
-		'shift_for_all_read' => '+ <kbd>Alt ⎇</kbd> to mark previous articles as read<br />+ <kbd>⇧ Shift</kbd> to mark all articles as read',	// TODO - Translation
-		'skip_next_article' => 'Focus next without opening',	// TODO - Translation
-		'skip_previous_article' => 'Focus previous without opening',	// TODO - Translation
+		'shift_for_all_read' => '+ <kbd>Alt ⎇</kbd> to mark previous articles as read<br />+ <kbd>⇧ Shift</kbd> to mark all articles as read',	// TODO
+		'skip_next_article' => 'Focus next without opening',	// TODO
+		'skip_previous_article' => 'Focus previous without opening',	// TODO
 		'title' => 'Comandi da tastiera',
-		'toggle_media' => 'Play/pause media',	// TODO - Translation
+		'toggle_media' => 'Play/pause media',	// TODO
 		'user_filter' => 'Accedi alle ricerche personali',
 		'user_filter_help' => 'Se è presente una sola ricerca personale verrà usata quella, altrimenti usare anche il numero associato.',
-		'views' => 'Views',	// TODO - Translation
+		'views' => 'Views',	// TODO
 	),
 	'user' => array(
 		'articles_and_size' => '%s articoli (%s)',

+ 29 - 19
app/i18n/it/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'Non hai i permessi per accedere a questa pagina',
@@ -10,8 +20,8 @@ return array(
 	),
 	'api' => array(
 		'password' => array(
-			'failed' => 'Your password cannot be modified',	// TODO - Translation
-			'updated' => 'Your password has been modified',	// TODO - Translation
+			'failed' => 'Your password cannot be modified',	// TODO
+			'updated' => 'Your password has been modified',	// TODO
 		),
 	),
 	'auth' => array(
@@ -31,7 +41,7 @@ return array(
 	),
 	'extensions' => array(
 		'already_enabled' => '%s è già abilitata',
-		'cannot_remove' => '%s cannot be removed',	// TODO - Translation
+		'cannot_remove' => '%s cannot be removed',	// TODO
 		'disable' => array(
 			'ko' => '%s non può essere disabilitata. <a href="%s">Verifica i logs</a> per dettagli.',
 			'ok' => '%s è disabilitata',
@@ -43,7 +53,7 @@ return array(
 		'no_access' => 'Accesso negato a %s',
 		'not_enabled' => '%s non abilitato',
 		'not_found' => '%s non disponibile',
-		'removed' => '%s removed',	// TODO - Translation
+		'removed' => '%s removed',	// TODO
 	),
 	'import_export' => array(
 		'export_no_zip_extension' => 'Estensione ZIP non presente sul server. Per favore esporta i files singolarmente.',
@@ -60,8 +70,8 @@ return array(
 	'sub' => array(
 		'actualize' => 'Aggiorna',
 		'articles' => array(
-			'marked_read' => 'The selected articles have been marked as read.',	// TODO - Translation
-			'marked_unread' => 'The articles have been marked as unread.',	// TODO - Translation
+			'marked_read' => 'The selected articles have been marked as read.',	// TODO
+			'marked_unread' => 'The articles have been marked as unread.',	// TODO
 		),
 		'category' => array(
 			'created' => 'Categoria %s creata.',
@@ -81,7 +91,7 @@ return array(
 			'actualizeds' => 'RSS feeds aggiornati',
 			'added' => 'RSS feed <em>%s</em> aggiunti',
 			'already_subscribed' => 'Hai già sottoscritto <em>%s</em>',
-			'cache_cleared' => '<em>%s</em> cache has been cleared',	// TODO - Translation
+			'cache_cleared' => '<em>%s</em> cache has been cleared',	// TODO
 			'deleted' => 'Feed cancellato',
 			'error' => 'Feed non aggiornato',
 			'internal_problem' => 'RSS feed non aggiunto. <a href="%s">Verifica i logs</a> per dettagli.',
@@ -90,24 +100,24 @@ return array(
 			'n_entries_deleted' => '%d articoli cancellati',
 			'no_refresh' => 'Nessun aggiornamento disponibile…',
 			'not_added' => '<em>%s</em> non può essere aggiunto',
-			'not_found' => 'Feed cannot be found',	// TODO - Translation
+			'not_found' => 'Feed cannot be found',	// TODO
 			'over_max' => 'Hai raggiunto il numero limite di feed (%d)',
-			'reloaded' => '<em>%s</em> has been reloaded',	// TODO - Translation
+			'reloaded' => '<em>%s</em> has been reloaded',	// TODO
 			'selector_preview' => array(
-				'http_error' => 'Failed to load website content.',	// TODO - Translation
-				'no_entries' => 'There are no articles in this feed. You need at least one article to create a preview.',	// TODO - Translation
-				'no_feed' => 'Internal error (feed cannot be found).',	// TODO - Translation
-				'no_result' => 'The selector didn\'t match anything. As a fallback the original feed text will be displayed instead.',	// TODO - Translation
-				'selector_empty' => 'The selector is empty. You need to define one to create a preview.',	// TODO - Translation
+				'http_error' => 'Failed to load website content.',	// TODO
+				'no_entries' => 'There are no articles in this feed. You need at least one article to create a preview.',	// TODO
+				'no_feed' => 'Internal error (feed cannot be found).',	// TODO
+				'no_result' => 'The selector didn\'t match anything. As a fallback the original feed text will be displayed instead.',	// TODO
+				'selector_empty' => 'The selector is empty. You need to define one to create a preview.',	// TODO
 			),
 			'updated' => 'Feed aggiornato',
 		),
 		'purge_completed' => 'Svecchiamento completato (%d articoli cancellati)',
 	),
 	'tag' => array(
-		'created' => 'Tag "%s" has been created.',	// TODO - Translation
-		'name_exists' => 'Tag name already exists.',	// TODO - Translation
-		'renamed' => 'Tag "%s" has been renamed to "%s".',	// TODO - Translation
+		'created' => 'Tag "%s" has been created.',	// TODO
+		'name_exists' => 'Tag name already exists.',	// TODO
+		'renamed' => 'Tag "%s" has been renamed to "%s".',	// TODO
 	),
 	'update' => array(
 		'can_apply' => 'FreshRSS verrà aggiornato alla <strong>versione %s</strong>.',
@@ -127,8 +137,8 @@ return array(
 			'error' => 'Utente %s non cancellato',
 		),
 		'updated' => array(
-			'_' => 'User %s has been updated',	// TODO - Translation
-			'error' => 'User %s has not been updated',	// TODO - Translation
+			'_' => 'User %s has been updated',	// TODO
+			'error' => 'User %s has not been updated',	// TODO
 		),
 	),
 );

+ 77 - 67
app/i18n/it/gen.php

@@ -1,40 +1,50 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'Aggiorna feeds',
-		'add' => 'Add',	// TODO - Translation
-		'back' => '← Go back',	// TODO - Translation
+		'add' => 'Add',	// TODO
+		'back' => '← Go back',	// TODO
 		'back_to_rss_feeds' => '← Indietro',
 		'cancel' => 'Annulla',
 		'create' => 'Crea',
-		'demote' => 'Demote',	// TODO - Translation
+		'demote' => 'Demote',	// TODO
 		'disable' => 'Disabilita',
 		'empty' => 'Vuoto',
 		'enable' => 'Abilita',
 		'export' => 'Esporta',
 		'filter' => 'Filtra',
 		'import' => 'Importa',
-		'load_default_shortcuts' => 'Load default shortcuts',	// TODO - Translation
+		'load_default_shortcuts' => 'Load default shortcuts',	// TODO
 		'manage' => 'Gestisci',
 		'mark_read' => 'Segna come letto',
-		'promote' => 'Promote',	// TODO - Translation
-		'purge' => 'Purge',	// TODO - Translation
+		'promote' => 'Promote',	// TODO
+		'purge' => 'Purge',	// TODO
 		'remove' => 'Rimuovi',
-		'rename' => 'Rename',	// TODO - Translation
+		'rename' => 'Rename',	// TODO
 		'see_website' => 'Vai al sito',
 		'submit' => 'Conferma',
 		'truncate' => 'Cancella tutti gli articoli',
-		'update' => 'Update',	// TODO - Translation
+		'update' => 'Update',	// TODO
 	),
 	'auth' => array(
-		'accept_tos' => 'I accept the <a href="%s">Terms of Service</a>.',	// TODO - Translation
+		'accept_tos' => 'I accept the <a href="%s">Terms of Service</a>.',	// TODO
 		'email' => 'Indirizzo email',
 		'keep_logged_in' => 'Ricorda i dati <small>(%s giorni)</small>',
 		'login' => 'Accedi',
 		'logout' => 'Esci',
 		'password' => array(
-			'_' => 'Password',	// TODO - Translation
+			'_' => 'Password',	// TODO
 			'format' => '<small>almeno 7 caratteri</small>',
 		),
 		'registration' => array(
@@ -43,7 +53,7 @@ return array(
 			'title' => 'Creazione profilo',
 		),
 		'username' => array(
-			'_' => 'Username',	// TODO - Translation
+			'_' => 'Username',	// TODO
 			'format' => '<small>Massimo 16 caratteri alfanumerici</small>',
 		),
 	),
@@ -71,17 +81,17 @@ return array(
 		'february' => 'febbraio',
 		'format_date' => 'j\\ %s Y',
 		'format_date_hour' => 'j\\ %s Y \\o\\r\\e H\\:i',
-		'fri' => 'Fri',	// TODO - Translation
+		'fri' => 'Fri',	// TODO
 		'jan' => 'genn.',
 		'january' => 'gennaio',
 		'jul' => 'jul',
 		'july' => 'luglio',
 		'jun' => 'jun',
 		'june' => 'giugno',
-		'last_2_year' => 'Last two years',	// TODO - Translation
+		'last_2_year' => 'Last two years',	// TODO
 		'last_3_month' => 'Ultimi 3 mesi',
-		'last_3_year' => 'Last three years',	// TODO - Translation
-		'last_5_year' => 'Last five years',	// TODO - Translation
+		'last_3_year' => 'Last three years',	// TODO
+		'last_5_year' => 'Last five years',	// TODO
 		'last_6_month' => 'Ultimi 6 mesi',
 		'last_month' => 'Ultimo mese',
 		'last_week' => 'Ultima settimana',
@@ -89,24 +99,24 @@ return array(
 		'mar' => 'mar.',
 		'march' => 'marzo',
 		'may' => 'maggio',
-		'may_' => 'May',	// TODO - Translation
-		'mon' => 'Mon',	// TODO - Translation
+		'may_' => 'May',	// TODO
+		'mon' => 'Mon',	// TODO
 		'month' => 'mesi',
 		'nov' => 'nov.',
 		'november' => 'novembre',
 		'oct' => 'ott.',
 		'october' => 'ottobre',
-		'sat' => 'Sat',	// TODO - Translation
+		'sat' => 'Sat',	// TODO
 		'sep' => 'sett.',
 		'september' => 'settembre',
-		'sun' => 'Sun',	// TODO - Translation
-		'thu' => 'Thu',	// TODO - Translation
+		'sun' => 'Sun',	// TODO
+		'thu' => 'Thu',	// TODO
 		'today' => 'Oggi',
-		'tue' => 'Tue',	// TODO - Translation
-		'wed' => 'Wed',	// TODO - Translation
+		'tue' => 'Tue',	// TODO
+		'wed' => 'Wed',	// TODO
 		'yesterday' => 'Ieri',
 	),
-	'dir' => 'ltr',
+	'dir' => 'ltr',	// IGNORE
 	'freshrss' => array(
 		'_' => 'Feed RSS Reader',
 		'about' => 'Informazioni',
@@ -124,28 +134,28 @@ return array(
 		'should_be_activated' => 'JavaScript deve essere abilitato',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'Informazioni',
-		'account' => 'Account',	// TODO - Translation
+		'account' => 'Account',	// TODO
 		'admin' => 'Amministrazione',
 		'archiving' => 'Archiviazione',
 		'authentication' => 'Autenticazione',
@@ -153,7 +163,7 @@ return array(
 		'configuration' => 'Configurazione',
 		'display' => 'Visualizzazione',
 		'extensions' => 'Estensioni',
-		'logs' => 'Logs',	// TODO - Translation
+		'logs' => 'Logs',	// TODO
 		'queries' => 'Ricerche personali',
 		'reading' => 'Lettura',
 		'search' => 'Ricerca parole o #tags',
@@ -175,33 +185,33 @@ return array(
 		'previous' => 'Precedente',
 	),
 	'period' => array(
-		'days' => 'days',	// TODO - Translation
-		'hours' => 'hours',	// TODO - Translation
-		'months' => 'months',	// TODO - Translation
-		'weeks' => 'weeks',	// TODO - Translation
-		'years' => 'years',	// TODO - Translation
+		'days' => 'days',	// TODO
+		'hours' => 'hours',	// TODO
+		'months' => 'months',	// TODO
+		'weeks' => 'weeks',	// TODO
+		'years' => 'years',	// TODO
 	),
 	'share' => array(
 		'Known' => 'Siti basati su Known',
-		'blogotext' => 'Blogotext',
-		'clipboard' => 'Clipboard',	// TODO - Translation
-		'diaspora' => 'Diaspora*',
-		'email' => 'Email',	// TODO - Translation
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
+		'blogotext' => 'Blogotext',	// IGNORE
+		'clipboard' => 'Clipboard',	// TODO
+		'diaspora' => 'Diaspora*',	// IGNORE
+		'email' => 'Email',	// TODO
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
 		'print' => 'Stampa',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => 'Attenzione!',
@@ -210,7 +220,7 @@ return array(
 		'by_default' => 'predefinito',
 		'damn' => 'Ops!',
 		'default_category' => 'Senza categoria',
-		'no' => 'No',
+		'no' => 'No',	// IGNORE
 		'not_applicable' => 'Non disponibile',
 		'ok' => 'OK!',
 		'or' => 'o',

+ 18 - 8
app/i18n/it/index.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => 'Informazioni',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
 		'bugs_reports' => 'Bugs',
 		'credits' => 'Crediti',
 		'credits_content' => 'Alcuni elementi di design provengono da <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> sebbene FreshRSS non usi questo framework. Le <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">icone</a> provengono dal progetto <a href="https://www.gnome.org/">GNOME</a>. Il carattere <em>Open Sans</em> è stato creato da <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS è basato su <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, un framework PHP.',
@@ -23,23 +33,23 @@ return array(
 		'title_global' => 'Vista globale per categorie',
 	),
 	'log' => array(
-		'_' => 'Logs',	// TODO - Translation
+		'_' => 'Logs',	// TODO
 		'clear' => 'Svuota logs',
 		'empty' => 'File di log vuoto',
-		'title' => 'Logs',	// TODO - Translation
+		'title' => 'Logs',	// TODO
 	),
 	'menu' => array(
 		'about' => 'Informazioni',
 		'before_one_day' => 'Giorno precedente',
 		'before_one_week' => 'Settimana precedente',
-		'bookmark_query' => 'Bookmark current query',	// TODO - Translation
+		'bookmark_query' => 'Bookmark current query',	// TODO
 		'favorites' => 'Preferiti (%s)',
 		'global_view' => 'Vista globale per categorie',
 		'main_stream' => 'Flusso principale',
 		'mark_all_read' => 'Segna tutto come letto',
 		'mark_cat_read' => 'Segna la categoria come letta',
 		'mark_feed_read' => 'Segna il feed come letto',
-		'mark_selection_unread' => 'Mark selection as unread',	// TODO - Translation
+		'mark_selection_unread' => 'Mark selection as unread',	// TODO
 		'newer_first' => 'Mostra prima i recenti',
 		'non-starred' => 'Escludi preferiti',
 		'normal_view' => 'Vista elenco',
@@ -47,12 +57,12 @@ return array(
 		'queries' => 'Chiavi di ricerca',
 		'read' => 'Mostra solo letti',
 		'reader_view' => 'Modalità di lettura',
-		'rss_view' => 'RSS feed',	// TODO - Translation
+		'rss_view' => 'RSS feed',	// TODO
 		'search_short' => 'Cerca',
 		'starred' => 'Mostra solo preferiti',
 		'stats' => 'Statistiche',
 		'subscription' => 'Gestione sottoscrizioni',
-		'tags' => 'My labels',	// TODO - Translation
+		'tags' => 'My labels',	// TODO
 		'unread' => 'Mostra solo non letti',
 	),
 	'share' => 'Condividi',
@@ -60,6 +70,6 @@ return array(
 		'related' => 'Tags correlati',
 	),
 	'tos' => array(
-		'title' => 'Terms of Service',	// TODO - Translation
+		'title' => 'Terms of Service',	// TODO
 	),
 );

+ 20 - 10
app/i18n/it/install.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => 'Installazione completata',
@@ -17,13 +27,13 @@ return array(
 		'type' => 'Metodo di autenticazione',
 	),
 	'bdd' => array(
-		'_' => 'Database',	// TODO - Translation
+		'_' => 'Database',	// TODO
 		'conf' => array(
 			'_' => 'Configurazione database',
 			'ko' => 'Verifica le informazioni del database.',
 			'ok' => 'Le configurazioni del database sono state salvate.',
 		),
-		'host' => 'Host',	// TODO - Translation
+		'host' => 'Host',	// TODO
 		'password' => 'Password del database',
 		'prefix' => 'Prefisso tabella',
 		'type' => 'Tipo di database',
@@ -62,11 +72,11 @@ return array(
 		),
 		'json' => array(
 			'nok' => 'You lack a recommended library to parse JSON.',
-			'ok' => 'You have the recommended library to parse JSON.',	// TODO - Translation
+			'ok' => 'You have the recommended library to parse JSON.',	// TODO
 		),
 		'mbstring' => array(
-			'nok' => 'Cannot find the recommended library mbstring for Unicode.',	// TODO - Translation
-			'ok' => 'You have the recommended library mbstring for Unicode.',	// TODO - Translation
+			'nok' => 'Cannot find the recommended library mbstring for Unicode.',	// TODO
+			'ok' => 'You have the recommended library mbstring for Unicode.',	// TODO
 		),
 		'pcre' => array(
 			'nok' => 'Manca una libreria richiesta per le regular expressions (php-pcre).',
@@ -83,16 +93,16 @@ return array(
 		'reload' => 'Controlla di nuovo',
 		'tmp' => array(
 			'nok' => 'Verifica i permessi sulla cartella <em>%s</em>. Il server HTTP deve avere i permessi per scriverci dentro.',
-			'ok' => 'Permissions on the temp directory are good.',	// TODO - Translation
+			'ok' => 'Permissions on the temp directory are good.',	// TODO
 		),
-		'unknown_process_username' => 'unknown',	// TODO - Translation
+		'unknown_process_username' => 'unknown',	// TODO
 		'users' => array(
 			'nok' => 'Verifica i permessi sulla cartella <em>%s</em>. Il server HTTP deve avere i permessi per scriverci dentro.',
 			'ok' => 'I permessi sulla cartella users sono corretti.',
 		),
 		'xml' => array(
 			'nok' => 'You lack the required library to parse XML.',
-			'ok' => 'You have the required library to parse XML.',	// TODO - Translation
+			'ok' => 'You have the required library to parse XML.',	// TODO
 		),
 	),
 	'conf' => array(
@@ -111,10 +121,10 @@ return array(
 		'choose' => 'Seleziona la lingua per FreshRSS',
 		'defined' => 'Lingua impostata.',
 	),
-	'missing_applied_migrations' => 'Something went wrong; you should create an empty file <em>%s</em> manually.',	// TODO - Translation
+	'missing_applied_migrations' => 'Something went wrong; you should create an empty file <em>%s</em> manually.',	// TODO
 	'ok' => 'Processo di installazione terminato con successo.',
 	'session' => array(
-		'nok' => 'The web server seems to be incorrectly configured for cookies required for PHP sessions!',	// TODO - Translation
+		'nok' => 'The web server seems to be incorrectly configured for cookies required for PHP sessions!',	// TODO
 	),
 	'step' => 'Passaggio %d',
 	'steps' => 'Passaggi',

+ 63 - 53
app/i18n/it/sub.php

@@ -1,14 +1,24 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
-		'documentation' => 'Copy the following URL to use it within an external tool.',	// TODO - Translation
-		'title' => 'API',	// TODO - Translation
+		'documentation' => 'Copy the following URL to use it within an external tool.',	// TODO
+		'title' => 'API',	// TODO
 	),
 	'bookmarklet' => array(
-		'documentation' => 'Drag this button to your bookmarks toolbar or right-click it and choose "Bookmark This Link". Then click the "Subscribe" button in any page you want to subscribe to.',	// TODO - Translation
-		'label' => 'Subscribe',	// TODO - Translation
-		'title' => 'Bookmarklet',	// TODO - Translation
+		'documentation' => 'Drag this button to your bookmarks toolbar or right-click it and choose "Bookmark This Link". Then click the "Subscribe" button in any page you want to subscribe to.',	// TODO
+		'label' => 'Subscribe',	// TODO
+		'title' => 'Bookmarklet',	// TODO
 	),
 	'category' => array(
 		'_' => 'Categoria',
@@ -16,8 +26,8 @@ return array(
 		'archiving' => 'Archiviazione',
 		'empty' => 'Categoria vuota',
 		'information' => 'Informazioni',
-		'position' => 'Display position',	// TODO - Translation
-		'position_help' => 'To control category sort order',	// TODO - Translation
+		'position' => 'Display position',	// TODO
+		'position_help' => 'To control category sort order',	// TODO
 		'title' => 'Titolo',
 	),
 	'feed' => array(
@@ -28,76 +38,76 @@ return array(
 			'configuration' => 'Autenticazione',
 			'help' => 'Accesso per feeds protetti',
 			'http' => 'Autenticazione HTTP',
-			'password' => 'HTTP password',	// TODO - Translation
-			'username' => 'HTTP username',	// TODO - Translation
+			'password' => 'HTTP password',	// TODO
+			'username' => 'HTTP username',	// TODO
 		),
-		'clear_cache' => 'Always clear cache',	// TODO - Translation
+		'clear_cache' => 'Always clear cache',	// TODO
 		'content_action' => array(
-			'_' => 'Content action when fetching the article content',	// TODO - Translation
-			'append' => 'Add after existing content',	// TODO - Translation
-			'prepend' => 'Add before existing content',	// TODO - Translation
-			'replace' => 'Replace existing content',	// TODO - Translation
+			'_' => 'Content action when fetching the article content',	// TODO
+			'append' => 'Add after existing content',	// TODO
+			'prepend' => 'Add before existing content',	// TODO
+			'replace' => 'Replace existing content',	// TODO
 		),
-		'css_cookie' => 'Use Cookies when fetching the article content',	// TODO - Translation
-		'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',	// TODO - Translation
+		'css_cookie' => 'Use Cookies when fetching the article content',	// TODO
+		'css_cookie_help' => 'Example: <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',	// TODO
 		'css_help' => 'In caso di RSS feeds troncati (attenzione, richiede molto tempo!)',
 		'css_path' => 'Percorso del foglio di stile CSS del sito di origine',
 		'description' => 'Descrizione',
 		'empty' => 'Questo feed non contiene articoli. Per favore verifica il sito direttamente.',
 		'error' => 'Questo feed ha generato un errore. Per favore verifica se ancora disponibile.',
 		'filteractions' => array(
-			'_' => 'Filter actions',	// TODO - Translation
-			'help' => 'Write one search filter per line.',	// TODO - Translation
+			'_' => 'Filter actions',	// TODO
+			'help' => 'Write one search filter per line.',	// TODO
 		),
 		'information' => 'Informazioni',
 		'keep_min' => 'Numero minimo di articoli da mantenere',
 		'maintenance' => array(
-			'clear_cache' => 'Clear cache',	// TODO - Translation
-			'clear_cache_help' => 'Clear the cache for this feed.',	// TODO - Translation
-			'reload_articles' => 'Reload articles',	// TODO - Translation
-			'reload_articles_help' => 'Reload articles and fetch complete content if a selector is defined.',	// TODO - Translation
-			'title' => 'Maintenance',	// TODO - Translation
+			'clear_cache' => 'Clear cache',	// TODO
+			'clear_cache_help' => 'Clear the cache for this feed.',	// TODO
+			'reload_articles' => 'Reload articles',	// TODO
+			'reload_articles_help' => 'Reload articles and fetch complete content if a selector is defined.',	// TODO
+			'title' => 'Maintenance',	// TODO
 		),
 		'moved_category_deleted' => 'Cancellando una categoria i feed al suo interno verranno classificati automaticamente come <em>%s</em>.',
-		'mute' => 'mute',	// TODO - Translation
+		'mute' => 'mute',	// TODO
 		'no_selected' => 'Nessun feed selezionato.',
 		'number_entries' => '%d articoli',
 		'priority' => array(
-			'_' => 'Visibility',	// TODO - Translation
-			'archived' => 'Do not show (archived)',	// TODO - Translation
+			'_' => 'Visibility',	// TODO
+			'archived' => 'Do not show (archived)',	// TODO
 			'main_stream' => 'Mostra in homepage',
-			'normal' => 'Show in its category',	// TODO - Translation
+			'normal' => 'Show in its category',	// TODO
 		),
-		'proxy' => 'Set a proxy for fetching this feed',	// TODO - Translation
-		'proxy_help' => 'Select a protocol (e.g: SOCKS5) and enter the proxy address (e.g: <kbd>127.0.0.1:1080</kbd>)',	// TODO - Translation
+		'proxy' => 'Set a proxy for fetching this feed',	// TODO
+		'proxy_help' => 'Select a protocol (e.g: SOCKS5) and enter the proxy address (e.g: <kbd>127.0.0.1:1080</kbd>)',	// TODO
 		'selector_preview' => array(
-			'show_raw' => 'Show source code',	// TODO - Translation
-			'show_rendered' => 'Show content',	// TODO - Translation
+			'show_raw' => 'Show source code',	// TODO
+			'show_rendered' => 'Show content',	// TODO
 		),
 		'show' => array(
-			'all' => 'Show all feeds',	// TODO - Translation
-			'error' => 'Show only feeds with errors',	// TODO - Translation
+			'all' => 'Show all feeds',	// TODO
+			'error' => 'Show only feeds with errors',	// TODO
 		),
 		'showing' => array(
-			'error' => 'Showing only feeds with errors',	// TODO - Translation
+			'error' => 'Showing only feeds with errors',	// TODO
 		),
-		'ssl_verify' => 'Verify SSL security',	// TODO - Translation
+		'ssl_verify' => 'Verify SSL security',	// TODO
 		'stats' => 'Statistiche',
 		'think_to_add' => 'Aggiungi feed.',
-		'timeout' => 'Timeout in seconds',	// TODO - Translation
+		'timeout' => 'Timeout in seconds',	// TODO
 		'title' => 'Titolo',
 		'title_add' => 'Aggiungi RSS feed',
 		'ttl' => 'Non aggiornare automaticamente piu di',
-		'url' => 'Feed URL',	// TODO - Translation
-		'useragent' => 'Set the user agent for fetching this feed',	// TODO - Translation
-		'useragent_help' => 'Example: <kbd>Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0)</kbd>',	// TODO - Translation
+		'url' => 'Feed URL',	// TODO
+		'useragent' => 'Set the user agent for fetching this feed',	// TODO
+		'useragent_help' => 'Example: <kbd>Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0)</kbd>',	// TODO
 		'validator' => 'Controlla la validita del feed ',
 		'website' => 'URL del sito',
 		'websub' => 'Notifica istantanea con WebSub',
 	),
 	'import_export' => array(
 		'export' => 'Esporta',
-		'export_labelled' => 'Export your labelled articles',	// TODO - Translation
+		'export_labelled' => 'Export your labelled articles',	// TODO
 		'export_opml' => 'Esporta tutta la lista dei feed (OPML)',
 		'export_starred' => 'Esporta i tuoi preferiti',
 		'feed_list' => 'Elenco di %s articoli',
@@ -108,31 +118,31 @@ return array(
 		'title' => 'Importa / esporta',
 	),
 	'menu' => array(
-		'add' => 'Add a feed or category',	// TODO - Translation
+		'add' => 'Add a feed or category',	// TODO
 		'import_export' => 'Importa / esporta',
-		'label_management' => 'Label management',	// TODO - Translation
+		'label_management' => 'Label management',	// TODO
 		'stats' => array(
 			'idle' => 'Feeds non aggiornati',
 			'main' => 'Statistiche principali',
 			'repartition' => 'Ripartizione articoli',
 		),
 		'subscription_management' => 'Gestione sottoscrizioni',
-		'subscription_tools' => 'Subscription tools',	// TODO - Translation
+		'subscription_tools' => 'Subscription tools',	// TODO
 	),
 	'tag' => array(
-		'name' => 'Name',	// TODO - Translation
-		'new_name' => 'New name',	// TODO - Translation
-		'old_name' => 'Old name',	// TODO - Translation
+		'name' => 'Name',	// TODO
+		'new_name' => 'New name',	// TODO
+		'old_name' => 'Old name',	// TODO
 	),
 	'title' => array(
 		'_' => 'Gestione sottoscrizioni',
-		'add' => 'Add a feed or category',	// TODO - Translation
-		'add_category' => 'Add a category',	// TODO - Translation
-		'add_feed' => 'Add a feed',	// TODO - Translation
-		'add_label' => 'Add a label',	// TODO - Translation
-		'delete_label' => 'Delete a label',	// TODO - Translation
+		'add' => 'Add a feed or category',	// TODO
+		'add_category' => 'Add a category',	// TODO
+		'add_feed' => 'Add a feed',	// TODO
+		'add_label' => 'Add a label',	// TODO
+		'delete_label' => 'Delete a label',	// TODO
 		'feed_management' => 'Gestione RSS feeds',
-		'rename_label' => 'Rename a label',	// TODO - Translation
-		'subscription_tools' => 'Subscription tools',	// TODO - Translation
+		'rename_label' => 'Rename a label',	// TODO
+		'subscription_tools' => 'Subscription tools',	// TODO
 	),
 );

+ 30 - 20
app/i18n/it/user.php

@@ -1,44 +1,54 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(
-			'invalid' => 'This email address is invalid.',	// TODO - Translation
-			'required' => 'An email address is required.',	// TODO - Translation
+			'invalid' => 'This email address is invalid.',	// TODO
+			'required' => 'An email address is required.',	// TODO
 		),
 		'validation' => array(
-			'change_email' => 'You can change your email address <a href="%s">on the profile page</a>.',	// TODO - Translation
-			'email_sent_to' => 'We sent you an email at <strong>%s</strong>. Please follow its instructions to validate your address.',	// TODO - Translation
+			'change_email' => 'You can change your email address <a href="%s">on the profile page</a>.',	// TODO
+			'email_sent_to' => 'We sent you an email at <strong>%s</strong>. Please follow its instructions to validate your address.',	// TODO
 			'feedback' => array(
-				'email_failed' => 'We couldn’t send you an email because of a server configuration error.',	// TODO - Translation
-				'email_sent' => 'An email has been sent to your address.',	// TODO - Translation
-				'error' => 'Email address validation failed.',	// TODO - Translation
-				'ok' => 'This email address has been validated.',	// TODO - Translation
-				'unnecessary' => 'This email address was already validated.',	// TODO - Translation
-				'wrong_token' => 'This email address failed to be validated due to a wrong token.',	// TODO - Translation
+				'email_failed' => 'We couldn’t send you an email because of a server configuration error.',	// TODO
+				'email_sent' => 'An email has been sent to your address.',	// TODO
+				'error' => 'Email address validation failed.',	// TODO
+				'ok' => 'This email address has been validated.',	// TODO
+				'unnecessary' => 'This email address was already validated.',	// TODO
+				'wrong_token' => 'This email address failed to be validated due to a wrong token.',	// TODO
 			),
-			'need_to' => 'You need to validate your email address before being able to use %s.',	// TODO - Translation
-			'resend_email' => 'Resend the email',	// TODO - Translation
-			'title' => 'Email address validation',	// TODO - Translation
+			'need_to' => 'You need to validate your email address before being able to use %s.',	// TODO
+			'resend_email' => 'Resend the email',	// TODO
+			'title' => 'Email address validation',	// TODO
 		),
 	),
 	'mailer' => array(
 		'email_need_validation' => array(
-			'body' => 'You’ve just registered on %s, but you still need to validate your email address. For that, just follow the link:',	// TODO - Translation
-			'title' => 'You need to validate your account',	// TODO - Translation
-			'welcome' => 'Welcome %s,',	// TODO - Translation
+			'body' => 'You’ve just registered on %s, but you still need to validate your email address. For that, just follow the link:',	// TODO
+			'title' => 'You need to validate your account',	// TODO
+			'welcome' => 'Welcome %s,',	// TODO
 		),
 	),
 	'password' => array(
-		'invalid' => 'The password is invalid.',	// TODO - Translation
+		'invalid' => 'The password is invalid.',	// TODO
 	),
 	'tos' => array(
 		'feedback' => array(
-			'invalid' => 'You must accept the Terms of Service to be able to register.',	// TODO - Translation
+			'invalid' => 'You must accept the Terms of Service to be able to register.',	// TODO
 		),
 	),
 	'username' => array(
-		'invalid' => 'This username is invalid.',	// TODO - Translation
-		'taken' => 'This username, %s, is taken.',	// TODO - Translation
+		'invalid' => 'This username is invalid.',	// TODO
+		'taken' => 'This username, %s, is taken.',	// TODO
 	),
 );

+ 10 - 0
app/i18n/ja/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => '標準のユーザーの記事が匿名のユーザーでも読めるようにします。 (%s)',

+ 18 - 8
app/i18n/ja/conf.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'アーカイブ',
@@ -163,20 +173,20 @@ return array(
 	'sharing' => array(
 		'_' => '共有',
 		'add' => '共有方法を追加する',
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'Eメール',
-		'facebook' => 'Facebook',
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => 'もっと多くの情報',
-		'print' => '印刷',
-		'raindrop' => 'Raindrop.io',
+		'print' => '印刷',	// IGNORE
+		'raindrop' => 'Raindrop.io',	// IGNORE
 		'remove' => '共有方法を削除する',
-		'shaarli' => 'Shaarli',
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => '表示する共有方法の名前',
 		'share_url' => '使用するURLを共有する',
 		'title' => '共有',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => 'ショートカット',

+ 10 - 0
app/i18n/ja/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'このページにアクセスする権限がありません。',

+ 46 - 36
app/i18n/ja/gen.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'フィードを更新する',
@@ -106,9 +116,9 @@ return array(
 		'wed' => '水',
 		'yesterday' => '昨日',
 	),
-	'dir' => 'ltr',
+	'dir' => 'ltr',	// IGNORE
 	'freshrss' => array(
-		'_' => 'FreshRSS',
+		'_' => 'FreshRSS',	// IGNORE
 		'about' => 'FreshRSSについて',
 	),
 	'js' => array(
@@ -124,24 +134,24 @@ return array(
 		'should_be_activated' => 'JavaScriptは有効になっている必要があります。',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'FreshRSSについて',
@@ -183,25 +193,25 @@ return array(
 	),
 	'share' => array(
 		'Known' => 'よく使われるサイト',
-		'blogotext' => 'Blogotext',
+		'blogotext' => 'Blogotext',	// IGNORE
 		'clipboard' => 'クリップボード',
-		'diaspora' => 'Diaspora*',
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'Eメール',
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
 		'print' => '印刷',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => '警告!',

+ 11 - 1
app/i18n/ja/index.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => 'FreshRSSについて',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
 		'bugs_reports' => 'バグレポート',
 		'credits' => 'クレジット',
 		'credits_content' => 'いくつかのデザイン要素は <a href="http://twitter.github.io/bootstrap/">Bootstrap</a>から来ています。しかしFreshRSSはこのフレームワークを使用していません。 <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">アイコン</a> は <a href="https://www.gnome.org/">GNOME プロジェクトから作られています</a>。 <em>Open Sans</em> フォントは <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson によって作成されました</a>。 FreshRSS は<a href="https://github.com/marienfressinaud/MINZ">Minz</a>,PHP フレームワークをもとにしています。',

+ 10 - 0
app/i18n/ja/install.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => 'インストール作業を終わりにする',

+ 11 - 1
app/i18n/ja/sub.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
 		'documentation' => '外部ツール内で使うURLをコピーします。',
-		'title' => 'API',
+		'title' => 'API',	// IGNORE
 	),
 	'bookmarklet' => array(
 		'documentation' => 'このボタンをブックマークツールバーへドラッグするか、右クリックして、「このリンクをブックマークする」を選択します。そうすることでどのページでも購読できるようになります。',

+ 10 - 0
app/i18n/ja/user.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(

+ 10 - 0
app/i18n/ko/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => '누구나 기본 사용자의 글을 읽을 수 있도록 합니다(%s)',

+ 17 - 7
app/i18n/ko/conf.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => '보관',
@@ -163,20 +173,20 @@ return array(
 	'sharing' => array(
 		'_' => '공유',
 		'add' => '공유 방법 추가',
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => '메일',
-		'facebook' => 'Facebook',
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => '자세한 정보',
 		'print' => '인쇄',
-		'raindrop' => 'Raindrop.io',
+		'raindrop' => 'Raindrop.io',	// IGNORE
 		'remove' => '공유 방법 삭제',
-		'shaarli' => 'Shaarli',
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => '표시할 이름',
 		'share_url' => '사용할 공유 URL',
 		'title' => '공유',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => '단축키',

+ 10 - 0
app/i18n/ko/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => '이 페이지에 접근할 수 있는 권한이 없습니다',

+ 59 - 49
app/i18n/ko/gen.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => '새 글 가져오기',
@@ -48,18 +58,18 @@ return array(
 		),
 	),
 	'date' => array(
-		'Apr' => '\\4\\월',
-		'Aug' => '\\8\\월',
-		'Dec' => '\\1\\2\\월',
-		'Feb' => '\\2\\월',
-		'Jan' => '\\1\\월',
-		'Jul' => '\\7\\월',
-		'Jun' => '\\6\\월',
-		'Mar' => '\\3\\월',
-		'May' => '\\5\\월',
-		'Nov' => '\\1\\1\\월',
-		'Oct' => '\\1\\0\\월',
-		'Sep' => '\\9\\월',
+		'Apr' => '\\4\\월',	// IGNORE
+		'Aug' => '\\8\\월',	// IGNORE
+		'Dec' => '\\1\\2\\월',	// IGNORE
+		'Feb' => '\\2\\월',	// IGNORE
+		'Jan' => '\\1\\월',	// IGNORE
+		'Jul' => '\\7\\월',	// IGNORE
+		'Jun' => '\\6\\월',	// IGNORE
+		'Mar' => '\\3\\월',	// IGNORE
+		'May' => '\\5\\월',	// IGNORE
+		'Nov' => '\\1\\1\\월',	// IGNORE
+		'Oct' => '\\1\\0\\월',	// IGNORE
+		'Sep' => '\\9\\월',	// IGNORE
 		'apr' => '4월',
 		'april' => '4월',
 		'aug' => '8월',
@@ -106,9 +116,9 @@ return array(
 		'wed' => '수',
 		'yesterday' => '어제',
 	),
-	'dir' => 'ltr',
+	'dir' => 'ltr',	// IGNORE
 	'freshrss' => array(
-		'_' => 'FreshRSS',
+		'_' => 'FreshRSS',	// IGNORE
 		'about' => '정보',
 	),
 	'js' => array(
@@ -124,24 +134,24 @@ return array(
 		'should_be_activated' => '자바스크립트를 사용하도록 설정해야합니다',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => '정보',
@@ -182,26 +192,26 @@ return array(
 		'years' => '년',
 	),
 	'share' => array(
-		'Known' => 'Known based sites',
-		'blogotext' => 'Blogotext',
+		'Known' => 'Known based sites',	// IGNORE
+		'blogotext' => 'Blogotext',	// IGNORE
 		'clipboard' => '클립보드',
-		'diaspora' => 'Diaspora*',
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => '메일',
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
 		'print' => '인쇄',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => '경고!',

+ 11 - 1
app/i18n/ko/index.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => '정보',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
 		'bugs_reports' => '버그 제보하기',
 		'credits' => '크레딧',
 		'credits_content' => 'FreshRSS는 <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> 프레임워크를 사용하진 않지만, 일부 디자인 요소를 가져왔습니다. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">아이콘들</a>은 <a href="https://www.gnome.org/">GNOME 프로젝트</a>에서 가져왔습니다. <em>Open Sans</em> 글꼴은 <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>가 제작하였습니다. FreshRSS는 PHP 프레임워크인 <a href="https://github.com/marienfressinaud/MINZ">Minz</a>에 기반하고 있습니다.',

+ 10 - 0
app/i18n/ko/install.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => '설치 완료',

+ 11 - 1
app/i18n/ko/sub.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
 		'documentation' => '외부 도구에서 API를 사용하기 위해서 아래 URL을 사용하세요.',
-		'title' => 'API',
+		'title' => 'API',	// IGNORE
 	),
 	'bookmarklet' => array(
 		'documentation' => '이 버튼을 즐겨찾기 막대로 끌어다 놓거나 마우스 오른쪽 클릭으로 나타나는 메뉴에서 "이 링크를 즐겨찾기에 추가"를 선택하세요. 그리고 피드를 구독하길 원하는 페이지에서 "구독하기" 버튼을 클릭하세요.',

+ 10 - 0
app/i18n/ko/user.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(

+ 12 - 2
app/i18n/nl/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => 'Sta bezoekers toe om artikelen te lezen van de standaard gebruiker (%s)',
@@ -130,7 +140,7 @@ return array(
 		'entry_per_hour' => 'Per uur (gemiddeld: %.2f berichten)',
 		'entry_per_month' => 'Per maand (gemiddeld: %.2f berichten)',
 		'entry_repartition' => 'Invoer verdeling',
-		'feed' => 'Feed',
+		'feed' => 'Feed',	// IGNORE
 		'feed_per_category' => 'Feeds per categorie',
 		'idle' => 'Gepauzeerde feeds',
 		'main' => 'Hoofd statistieken',
@@ -179,7 +189,7 @@ return array(
 		'database_size' => 'Databasegrootte',
 		'email' => 'Emailadres',
 		'enabled' => 'Ingeschakeld',
-		'feed_count' => 'Feeds',
+		'feed_count' => 'Feeds',	// IGNORE
 		'is_admin' => 'Is beheerder',
 		'language' => 'Taal',
 		'last_user_activity' => 'Laatste gebruikersactiviteit',

+ 21 - 11
app/i18n/nl/conf.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'Archivering',
@@ -80,7 +90,7 @@ return array(
 			'search' => 'Expressie',
 			'state' => 'Status',
 			'tags' => 'Weergeven op tag',
-			'type' => 'Type',
+			'type' => 'Type',	// IGNORE
 		),
 		'get_all' => 'Toon alle artikelen',
 		'get_category' => 'Toon "%s" categorie',
@@ -88,7 +98,7 @@ return array(
 		'get_feed' => 'Toon "%s" feed',
 		'name' => 'Naam',
 		'no_filter' => 'Geen filter',
-		'number' => 'Query n°%d',
+		'number' => 'Query n°%d',	// IGNORE
 		'order_asc' => 'Toon oudste artikelen eerst',
 		'order_desc' => 'Toon nieuwste artikelen eerst',
 		'search' => 'Zoek naar "%s"',
@@ -163,20 +173,20 @@ return array(
 	'sharing' => array(
 		'_' => 'Delen',
 		'add' => 'Deelmethode toevoegen',
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
-		'email' => 'Email',
-		'facebook' => 'Facebook',
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
+		'email' => 'Email',	// IGNORE
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => 'Meer informatie',
-		'print' => 'Afdrukken',
-		'raindrop' => 'Raindrop.io',
+		'print' => 'Afdrukken',	// IGNORE
+		'raindrop' => 'Raindrop.io',	// IGNORE
 		'remove' => 'Deelmethode verwijderen',
-		'shaarli' => 'Shaarli',
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => 'Gedeelde naam om weer te geven',
 		'share_url' => 'Deel URL voor gebruik',
 		'title' => 'Delen',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => 'Snelkoppelingen',

+ 10 - 0
app/i18n/nl/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'U hebt geen rechten om deze pagina te bekijken.',

+ 56 - 46
app/i18n/nl/gen.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'Feeds actualiseren',
@@ -48,18 +58,18 @@ return array(
 		),
 	),
 	'date' => array(
-		'Apr' => '\\A\\p\\r\\i\\l',
+		'Apr' => '\\A\\p\\r\\i\\l',	// IGNORE
 		'Aug' => '\\A\\u\\g\\u\\s\\t\\u\\s',
-		'Dec' => '\\D\\e\\c\\e\\m\\b\\e\\r',
+		'Dec' => '\\D\\e\\c\\e\\m\\b\\e\\r',	// IGNORE
 		'Feb' => '\\F\\e\\b\\r\\u\\a\\r\\i',
 		'Jan' => '\\J\\a\\n\\u\\a\\r\\i',
 		'Jul' => '\\J\\u\\l\\i',
 		'Jun' => '\\J\\u\\n\\i',
 		'Mar' => '\\M\\a\\a\\r\\t',
 		'May' => '\\M\\e\\i',
-		'Nov' => '\\N\\o\\v\\e\\m\\b\\e\\r',
+		'Nov' => '\\N\\o\\v\\e\\m\\b\\e\\r',	// IGNORE
 		'Oct' => '\\O\\k\\t\\o\\b\\e\\r',
-		'Sep' => '\\S\\e\\p\\t\\e\\m\\b\\e\\r',
+		'Sep' => '\\S\\e\\p\\t\\e\\m\\b\\e\\r',	// IGNORE
 		'apr' => 'apr',
 		'april' => 'Apr',
 		'aug' => 'aug',
@@ -69,8 +79,8 @@ return array(
 		'december' => 'Dec',
 		'feb' => 'feb',
 		'february' => 'Feb',
-		'format_date' => 'j %s Y',
-		'format_date_hour' => 'j %s Y \\o\\m H\\:i',
+		'format_date' => 'j %s Y',	// IGNORE
+		'format_date_hour' => 'j %s Y \\o\\m H\\:i',	// IGNORE
 		'fri' => 'Vr',
 		'jan' => 'jan',
 		'january' => 'Jan',
@@ -106,9 +116,9 @@ return array(
 		'wed' => 'Wo',
 		'yesterday' => 'Gisteren',
 	),
-	'dir' => 'ltr',
+	'dir' => 'ltr',	// IGNORE
 	'freshrss' => array(
-		'_' => 'FreshRSS',
+		'_' => 'FreshRSS',	// IGNORE
 		'about' => 'Over FreshRSS',
 	),
 	'js' => array(
@@ -124,28 +134,28 @@ return array(
 		'should_be_activated' => 'JavaScript moet aanstaan',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'Over',
-		'account' => 'Account',
+		'account' => 'Account',	// IGNORE
 		'admin' => 'Administratie',
 		'archiving' => 'Archiveren',
 		'authentication' => 'Authenticatie',
@@ -183,25 +193,25 @@ return array(
 	),
 	'share' => array(
 		'Known' => 'Known-gebaseerde sites',
-		'blogotext' => 'Blogotext',
+		'blogotext' => 'Blogotext',	// IGNORE
 		'clipboard' => 'Klembord',
-		'diaspora' => 'Diaspora*',
-		'email' => 'Email',
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
-		'print' => 'Print',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'diaspora' => 'Diaspora*',	// IGNORE
+		'email' => 'Email',	// IGNORE
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
+		'print' => 'Print',	// IGNORE
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => 'Attentie!',
@@ -212,7 +222,7 @@ return array(
 		'default_category' => 'Niet ingedeeld',
 		'no' => 'Nee',
 		'not_applicable' => 'Niet aanwezig',
-		'ok' => 'Ok!',
+		'ok' => 'Ok!',	// IGNORE
 		'or' => 'of',
 		'yes' => 'Ja',
 	),

+ 12 - 2
app/i18n/nl/index.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => 'Over',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
 		'bugs_reports' => 'Rapporteer fouten',
 		'credits' => 'Waarderingen',
 		'credits_content' => 'Sommige ontwerp elementen komen van <a href="http://twitter.github.io/bootstrap/">Bootstrap</a> alhoewel FreshRSS dit raamwerk niet gebruikt. <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">Pictogrammen</a> komen van het <a href="https://www.gnome.org/">GNOME project</a>. <em>De Open Sans</em> font police is gemaakt door <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS is gebaseerd op <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, een PHP raamwerk. Nederlandse vertaling door Wanabo, <a href="http://www.nieuwskop.be" title="NieuwsKop">NieuwsKop.be</a>. Link naar de Nederlandse vertaling, <a href="https://github.com/Wanabo/FreshRSS-Dutch-translation/tree/master">FreshRSS-Dutch-translation</a>.',
@@ -12,7 +22,7 @@ return array(
 		'license' => 'Licentie',
 		'project_website' => 'Projectwebsite',
 		'title' => 'Over',
-		'version' => 'Versie',
+		'version' => 'Versie',	// IGNORE
 	),
 	'feed' => array(
 		'add' => 'U kunt wat feeds toevoegen.',

+ 12 - 2
app/i18n/nl/install.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => 'Completeer installatie',
@@ -17,13 +27,13 @@ return array(
 		'type' => 'Authenticatiemethode',
 	),
 	'bdd' => array(
-		'_' => 'Database',
+		'_' => 'Database',	// IGNORE
 		'conf' => array(
 			'_' => 'Database configuratie',
 			'ko' => 'Controleer uw database informatie.',
 			'ok' => 'Database configuratie is opgeslagen.',
 		),
-		'host' => 'Host',
+		'host' => 'Host',	// IGNORE
 		'password' => 'Database wachtwoord',
 		'prefix' => 'Tabel voorvoegsel',
 		'type' => 'Type database',

+ 12 - 2
app/i18n/nl/sub.php

@@ -1,14 +1,24 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
 		'documentation' => 'Kopieer de volgende URL om deze in een externe toepassing te gebruiken.',
-		'title' => 'API',
+		'title' => 'API',	// IGNORE
 	),
 	'bookmarklet' => array(
 		'documentation' => 'Sleep deze knop naar je bladwijzerwerkbalk of klik erop met de rechtermuisknop en kies "Deze link aan bladwijzers toevoegen."',
 		'label' => 'Abonneren',
-		'title' => 'Bookmarklet',
+		'title' => 'Bookmarklet',	// IGNORE
 	),
 	'category' => array(
 		'_' => 'Categorie',

+ 10 - 0
app/i18n/nl/user.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(

+ 16 - 6
app/i18n/oc/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => 'Autorizar la lectura anonima dels articles de l’utilizaire per defaut (%s)',
@@ -114,10 +124,10 @@ return array(
 			'_' => 'Extensions sistèma',
 			'no_rights' => 'Extensions sistèma (contrarotlat per l’administrator)',
 		),
-		'title' => 'Extensions',
+		'title' => 'Extensions',	// IGNORE
 		'update' => 'Mesa a jorn disponibla',
 		'user' => 'Extensions utilizaire',
-		'version' => 'Version',
+		'version' => 'Version',	// IGNORE
 	),
 	'stats' => array(
 		'_' => 'Estatisticas',
@@ -136,12 +146,12 @@ return array(
 		'main' => 'Estatisticas principalas',
 		'main_stream' => 'Flux màger',
 		'no_idle' => 'I a pas cap d’article inactiu !',
-		'number_entries' => '%d articles',
+		'number_entries' => '%d articles',	// IGNORE
 		'percent_of_total' => '%% del total',
 		'repartition' => 'Reparticion dels articles',
 		'status_favorites' => 'Favorits',
 		'status_read' => 'Legit',
-		'status_total' => 'Total',
+		'status_total' => 'Total',	// IGNORE
 		'status_unread' => 'Pas legits',
 		'title' => 'Estatisticas',
 		'top_feed' => 'Los dètz fluxes mai gròsses',
@@ -172,8 +182,8 @@ return array(
 		'title' => 'Sistèma de mesa a jorn',
 	),
 	'user' => array(
-		'admin' => 'Administrator',
-		'article_count' => 'Articles',
+		'admin' => 'Administrator',	// IGNORE
+		'article_count' => 'Articles',	// IGNORE
 		'back_to_manage' => '← Tornar a la lista dels utilizaires',
 		'create' => 'Crear un nòu utilizaire',
 		'database_size' => 'Talha basa de donadas',

+ 21 - 11
app/i18n/oc/conf.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'Archius',
@@ -77,7 +87,7 @@ return array(
 			'categories' => 'Afichatge per categoria',
 			'feeds' => 'Afichatge per flux',
 			'order' => 'Triar per data',
-			'search' => 'Expression',
+			'search' => 'Expression',	// IGNORE
 			'state' => 'Estat',
 			'tags' => 'Afichatge per etiqueta',
 			'type' => 'Tipe',
@@ -163,20 +173,20 @@ return array(
 	'sharing' => array(
 		'_' => 'Partatge',
 		'add' => 'Ajustar un metòde de partatge',
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'Corrièl',
-		'facebook' => 'Facebook',
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => 'Mai d’informacions',
-		'print' => 'Imprimir',
-		'raindrop' => 'Raindrop.io',
+		'print' => 'Imprimir',	// IGNORE
+		'raindrop' => 'Raindrop.io',	// IGNORE
 		'remove' => 'Suprimir lo metòde de partatge',
-		'shaarli' => 'Shaarli',
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => 'Nom del partatge de mostrar',
 		'share_url' => 'URL del partatge d’utilizar',
 		'title' => 'Partatge',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => 'Acorchis',
@@ -194,7 +204,7 @@ return array(
 		'load_more' => 'Cargar mai d’articles',
 		'mark_favorite' => 'Ajustar als favorits',
 		'mark_read' => 'Marcar coma legit',
-		'navigation' => 'Navigacion',
+		'navigation' => 'Navigacion',	// IGNORE
 		'navigation_help' => 'Amb lo modificador <kbd>⇧ Shift</kbd>, los acorchis de navigacion s’aplican als fluxes.<br/>Amb lo modificador <kbd>Alt ⎇</kbd>, los acorchis de navigacion s’aplican a las categorias.',
 		'navigation_no_mod_help' => 'Los acorchis clavièrs de navigacion son pas compatibles amb los modificadors.',
 		'next_article' => 'Passar a l’article seguent',
@@ -216,7 +226,7 @@ return array(
 		'views' => 'Vistas',
 	),
 	'user' => array(
-		'articles_and_size' => '%s articles (%s)',
+		'articles_and_size' => '%s articles (%s)',	// IGNORE
 		'current' => 'Utilizaire actual',
 		'is_admin' => 'es administrator',
 		'users' => 'Utilizaires',

+ 10 - 0
app/i18n/oc/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'Avètz pas l’autorizacion d’accedir a aquesta pagina',

+ 50 - 40
app/i18n/oc/gen.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'Actualizar flux',
@@ -106,9 +116,9 @@ return array(
 		'wed' => 'Dc',
 		'yesterday' => 'Ièr',
 	),
-	'dir' => 'ltr',
+	'dir' => 'ltr',	// IGNORE
 	'freshrss' => array(
-		'_' => 'FreshRSS',
+		'_' => 'FreshRSS',	// IGNORE
 		'about' => 'A prepaus de FreshRSS',
 	),
 	'js' => array(
@@ -124,36 +134,36 @@ return array(
 		'should_be_activated' => 'JavaScript deu èsser activat',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'A prepaus',
 		'account' => 'Compte',
-		'admin' => 'Administracion',
+		'admin' => 'Administracion',	// IGNORE
 		'archiving' => 'Archivar',
 		'authentication' => 'Autentificacion',
 		'check_install' => 'Verificacion de l’installacion',
-		'configuration' => 'Configuracion',
+		'configuration' => 'Configuracion',	// IGNORE
 		'display' => 'Afichatge',
-		'extensions' => 'Extensions',
-		'logs' => 'Jornals d’audit',
+		'extensions' => 'Extensions',	// IGNORE
+		'logs' => 'Jornals d’audit',	// IGNORE
 		'queries' => 'Filtres utilizaire',
 		'reading' => 'Lectura',
 		'search' => 'Recercar de mots o d’#etiquetas',
@@ -183,25 +193,25 @@ return array(
 	),
 	'share' => array(
 		'Known' => 'Sites basats sus Known',
-		'blogotext' => 'Blogotext',
+		'blogotext' => 'Blogotext',	// IGNORE
 		'clipboard' => 'Quicha-papiers.',
-		'diaspora' => 'Diaspora*',
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'Corrièl',
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
 		'print' => 'Imprimir',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => 'Atencion !',

+ 14 - 4
app/i18n/oc/index.php

@@ -1,9 +1,19 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'about' => array(
 		'_' => 'A prepaus',
-		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',
+		'agpl3' => '<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL 3</a>',	// IGNORE
 		'bugs_reports' => 'Senhalament de problèmas',
 		'credits' => 'Crèdits',
 		'credits_content' => 'Unes elements de l’estil venon del <a href="http://twitter.github.io/bootstrap/">projècte Bootstrap</a> encara que FreshRSS utilize pas aqueste framework. Las <a href="https://git.gnome.org/browse/gnome-icon-theme-symbolic">icònas</a> venon del <a href="https://www.gnome.org/">projècte GNOME</a>. La polissa <em>Open Sans</em> utilizada foguèt creada per en <a href="https://fonts.google.com/specimen/Open+Sans">Steve Matteson</a>. FreshRSS es basat sus <a href="https://github.com/marienfressinaud/MINZ">Minz</a>, un framework PHP.',
@@ -12,7 +22,7 @@ return array(
 		'license' => 'Licéncia',
 		'project_website' => 'Site del projècte',
 		'title' => 'A prepaus',
-		'version' => 'Version',
+		'version' => 'Version',	// IGNORE
 	),
 	'feed' => array(
 		'add' => 'Podètz ajustar de fluxes.',
@@ -23,10 +33,10 @@ return array(
 		'title_global' => 'Vista generala',
 	),
 	'log' => array(
-		'_' => 'Jornals d’audit',
+		'_' => 'Jornals d’audit',	// IGNORE
 		'clear' => 'Escafar los jornals',
 		'empty' => 'Los jornals son voids',
-		'title' => 'Jornals d’audit',
+		'title' => 'Jornals d’audit',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'A prepaus de FreshRSS',

+ 10 - 0
app/i18n/oc/install.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'finish' => 'Acabar l’installacion',

+ 14 - 4
app/i18n/oc/sub.php

@@ -1,14 +1,24 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'api' => array(
 		'documentation' => 'Copiatz l’URL seguenta per l’utilizaire dins d’una aisina extèrna.',
-		'title' => 'API',
+		'title' => 'API',	// IGNORE
 	),
 	'bookmarklet' => array(
 		'documentation' => 'Depausatz aqueste boton per la barra de marcapaginas o clicatz-lo a drecha e causissètz « Enregistrar aqueste ligam». Puèi clicatz «S’abonar» sus las paginas que volètz seguir.',
 		'label' => 'S’abonar',
-		'title' => 'Bookmarklet',
+		'title' => 'Bookmarklet',	// IGNORE
 	),
 	'category' => array(
 		'_' => 'Categoria',
@@ -42,7 +52,7 @@ return array(
 		'css_cookie_help' => 'Exemple : <kbd>foo=bar; gdpr_consent=true; cookie=value</kbd>',
 		'css_help' => 'Permet de recuperar los fluxes troncats (atencion, demanda mai de temps !)',
 		'css_path' => 'Selector CSS dels articles sul site d’origina',
-		'description' => 'Descripcion',
+		'description' => 'Descripcion',	// IGNORE
 		'empty' => 'Aqueste flux es void. Assegurats-vos qu’es totjorn mantengut.',
 		'error' => 'Aqueste flux a rescontrat un problèma. Volgatz verificar que siá totjorn accessible puèi actualizatz-lo.',
 		'filteractions' => array(
@@ -61,7 +71,7 @@ return array(
 		'moved_category_deleted' => 'Quand escafatz una categoria, sos fluxes son automaticament classats dins <em>%s</em>.',
 		'mute' => 'mut',
 		'no_selected' => 'Cap de flux pas seleccionat.',
-		'number_entries' => '%d articles',
+		'number_entries' => '%d articles',	// IGNORE
 		'priority' => array(
 			'_' => 'Visibilitat',
 			'archived' => 'Mostrar pas (archivat)',

+ 10 - 0
app/i18n/oc/user.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'email' => array(
 		'feedback' => array(

+ 55 - 45
app/i18n/pl/admin.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'auth' => array(
 		'allow_anonymous' => 'Pozwól na anonimowy odczyt wiadomości domyślnego użytkownika (%s)',
@@ -16,88 +26,88 @@ return array(
 	),
 	'check_install' => array(
 		'cache' => array(
-			'nok' => 'Check permissions on <em>./data/cache</em> directory. HTTP server must have write permission.',	// TODO - Translation
-			'ok' => 'Permissions on the cache directory are good.',	// TODO - Translation
+			'nok' => 'Check permissions on <em>./data/cache</em> directory. HTTP server must have write permission.',	// TODO
+			'ok' => 'Permissions on the cache directory are good.',	// TODO
 		),
 		'categories' => array(
-			'nok' => 'Category table is improperly configured.',	// TODO - Translation
-			'ok' => 'Category table is okay.',	// TODO - Translation
+			'nok' => 'Category table is improperly configured.',	// TODO
+			'ok' => 'Category table is okay.',	// TODO
 		),
 		'connection' => array(
-			'nok' => 'Connection to the database cannot be established.',	// TODO - Translation
-			'ok' => 'Connection to the database is okay.',	// TODO - Translation
+			'nok' => 'Connection to the database cannot be established.',	// TODO
+			'ok' => 'Connection to the database is okay.',	// TODO
 		),
 		'ctype' => array(
-			'nok' => 'Cannot find a required library for character type checking (php-ctype).',	// TODO - Translation
-			'ok' => 'You have the required library for character type checking (ctype).',	// TODO - Translation
+			'nok' => 'Cannot find a required library for character type checking (php-ctype).',	// TODO
+			'ok' => 'You have the required library for character type checking (ctype).',	// TODO
 		),
 		'curl' => array(
-			'nok' => 'Cannot find the cURL library (php-curl package).',	// TODO - Translation
-			'ok' => 'You have the cURL library.',	// TODO - Translation
+			'nok' => 'Cannot find the cURL library (php-curl package).',	// TODO
+			'ok' => 'You have the cURL library.',	// TODO
 		),
 		'data' => array(
-			'nok' => 'Check permissions on <em>./data</em> directory. HTTP server must have write permission.',	// TODO - Translation
-			'ok' => 'Permissions on the data directory are good.',	// TODO - Translation
+			'nok' => 'Check permissions on <em>./data</em> directory. HTTP server must have write permission.',	// TODO
+			'ok' => 'Permissions on the data directory are good.',	// TODO
 		),
-		'database' => 'Database installation',	// TODO - Translation
+		'database' => 'Database installation',	// TODO
 		'dom' => array(
-			'nok' => 'Cannot find a required library to browse the DOM (php-xml package).',	// TODO - Translation
-			'ok' => 'You have the required library to browse the DOM.',	// TODO - Translation
+			'nok' => 'Cannot find a required library to browse the DOM (php-xml package).',	// TODO
+			'ok' => 'You have the required library to browse the DOM.',	// TODO
 		),
 		'entries' => array(
-			'nok' => 'Entry table is improperly configured.',	// TODO - Translation
-			'ok' => 'Entry table is okay.',	// TODO - Translation
+			'nok' => 'Entry table is improperly configured.',	// TODO
+			'ok' => 'Entry table is okay.',	// TODO
 		),
 		'favicons' => array(
-			'nok' => 'Check permissions on <em>./data/favicons</em> directory. HTTP server must have write permission.',	// TODO - Translation
-			'ok' => 'Permissions on the favicons directory are good.',	// TODO - Translation
+			'nok' => 'Check permissions on <em>./data/favicons</em> directory. HTTP server must have write permission.',	// TODO
+			'ok' => 'Permissions on the favicons directory are good.',	// TODO
 		),
 		'feeds' => array(
-			'nok' => 'Feed table is improperly configured.',	// TODO - Translation
-			'ok' => 'Feed table is okay.',	// TODO - Translation
+			'nok' => 'Feed table is improperly configured.',	// TODO
+			'ok' => 'Feed table is okay.',	// TODO
 		),
 		'fileinfo' => array(
-			'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',	// TODO - Translation
-			'ok' => 'You have the fileinfo library.',	// TODO - Translation
+			'nok' => 'Cannot find the PHP fileinfo library (fileinfo package).',	// TODO
+			'ok' => 'You have the fileinfo library.',	// TODO
 		),
-		'files' => 'File installation',	// TODO - Translation
+		'files' => 'File installation',	// TODO
 		'json' => array(
-			'nok' => 'Cannot find JSON (php-json package).',	// TODO - Translation
-			'ok' => 'You have the JSON extension.',	// TODO - Translation
+			'nok' => 'Cannot find JSON (php-json package).',	// TODO
+			'ok' => 'You have the JSON extension.',	// TODO
 		),
 		'mbstring' => array(
-			'nok' => 'Cannot find the recommended mbstring library for Unicode.',	// TODO - Translation
-			'ok' => 'You have the recommended mbstring library for Unicode.',	// TODO - Translation
+			'nok' => 'Cannot find the recommended mbstring library for Unicode.',	// TODO
+			'ok' => 'You have the recommended mbstring library for Unicode.',	// TODO
 		),
 		'pcre' => array(
-			'nok' => 'Cannot find a required library for regular expressions (php-pcre).',	// TODO - Translation
-			'ok' => 'You have the required library for regular expressions (PCRE).',	// TODO - Translation
+			'nok' => 'Cannot find a required library for regular expressions (php-pcre).',	// TODO
+			'ok' => 'You have the required library for regular expressions (PCRE).',	// TODO
 		),
 		'pdo' => array(
-			'nok' => 'Cannot find PDO or one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',	// TODO - Translation
-			'ok' => 'You have PDO and at least one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',	// TODO - Translation
+			'nok' => 'Cannot find PDO or one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',	// TODO
+			'ok' => 'You have PDO and at least one of the supported drivers (pdo_mysql, pdo_sqlite, pdo_pgsql).',	// TODO
 		),
 		'php' => array(
-			'_' => 'PHP installation',	// TODO - Translation
-			'nok' => 'Your PHP version is %s but FreshRSS requires at least version %s.',	// TODO - Translation
-			'ok' => 'Your PHP version (%s) is compatible with FreshRSS.',	// TODO - Translation
+			'_' => 'PHP installation',	// TODO
+			'nok' => 'Your PHP version is %s but FreshRSS requires at least version %s.',	// TODO
+			'ok' => 'Your PHP version (%s) is compatible with FreshRSS.',	// TODO
 		),
 		'tables' => array(
-			'nok' => 'There are one or more missing tables in the database.',	// TODO - Translation
-			'ok' => 'The appropriate tables exist in the database.',	// TODO - Translation
+			'nok' => 'There are one or more missing tables in the database.',	// TODO
+			'ok' => 'The appropriate tables exist in the database.',	// TODO
 		),
-		'title' => 'Installation check',	// TODO - Translation
+		'title' => 'Installation check',	// TODO
 		'tokens' => array(
-			'nok' => 'Check permissions on <em>./data/tokens</em> directory. HTTP server must have write permission',	// TODO - Translation
-			'ok' => 'Permissions on the tokens directory are good.',	// TODO - Translation
+			'nok' => 'Check permissions on <em>./data/tokens</em> directory. HTTP server must have write permission',	// TODO
+			'ok' => 'Permissions on the tokens directory are good.',	// TODO
 		),
 		'users' => array(
-			'nok' => 'Check permissions on <em>./data/users</em> directory. HTTP server must have write permission',	// TODO - Translation
-			'ok' => 'Permissions on the users directory are good.',	// TODO - Translation
+			'nok' => 'Check permissions on <em>./data/users</em> directory. HTTP server must have write permission',	// TODO
+			'ok' => 'Permissions on the users directory are good.',	// TODO
 		),
 		'zip' => array(
-			'nok' => 'Cannot find the ZIP extension (php-zip package).',	// TODO - Translation
-			'ok' => 'You have the ZIP extension.',	// TODO - Translation
+			'nok' => 'Cannot find the ZIP extension (php-zip package).',	// TODO
+			'ok' => 'You have the ZIP extension.',	// TODO
 		),
 	),
 	'extensions' => array(
@@ -172,7 +182,7 @@ return array(
 		'title' => 'Aktualizacja',
 	),
 	'user' => array(
-		'admin' => 'Administrator',
+		'admin' => 'Administrator',	// IGNORE
 		'article_count' => 'Liczba wiadomości',
 		'back_to_manage' => '← Powrót do listy użytkowników',
 		'create' => 'Dodaj nowego użytkownika',

+ 17 - 7
app/i18n/pl/conf.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'archiving' => array(
 		'_' => 'Archiwizacja',
@@ -163,20 +173,20 @@ return array(
 	'sharing' => array(
 		'_' => 'Podawanie dalej',
 		'add' => 'Dodaj sposób na podanie dalej wiadomości',
-		'blogotext' => 'Blogotext',
-		'diaspora' => 'Diaspora*',
+		'blogotext' => 'Blogotext',	// IGNORE
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'E-mail',
-		'facebook' => 'Facebook',
+		'facebook' => 'Facebook',	// IGNORE
 		'more_information' => 'Więcej informacji',
 		'print' => 'Wydruk',
-		'raindrop' => 'Raindrop.io',
+		'raindrop' => 'Raindrop.io',	// IGNORE
 		'remove' => 'Usuń sposób na podanie dalej wiadomości',
-		'shaarli' => 'Shaarli',
+		'shaarli' => 'Shaarli',	// IGNORE
 		'share_name' => 'Wyświetlana nazwa serwisu',
 		'share_url' => 'Adres API serwisu',
 		'title' => 'Podawanie dalej',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag',
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag',	// IGNORE
 	),
 	'shortcut' => array(
 		'_' => 'Skróty klawiszowe',

+ 10 - 0
app/i18n/pl/feedback.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'access' => array(
 		'denied' => 'Nie masz uprawnień dostępu do tej strony',

+ 49 - 39
app/i18n/pl/gen.php

@@ -1,5 +1,15 @@
 <?php
 
+/******************************************************************************/
+/* Each entry of that file can be associated with a comment to indicate its   */
+/* state. When there is no comment, it means the entry is fully translated.   */
+/* The recognized comments are (comment matching is case-insensitive):        */
+/*   + TODO: the entry has never been translated.                             */
+/*   + DIRTY: the entry has been translated but needs to be updated.          */
+/*   + IGNORE: the entry does not need to be translated.                      */
+/* When a comment is not recognized, it is discarded.                         */
+/******************************************************************************/
+
 return array(
 	'action' => array(
 		'actualize' => 'Aktualizuj kanałów',
@@ -69,8 +79,8 @@ return array(
 		'december' => 'Grudzień',
 		'feb' => 'Lut',
 		'february' => 'Luty',
-		'format_date' => 'j %s Y',
-		'format_date_hour' => 'j %s Y\\, H\\:i',
+		'format_date' => 'j %s Y',	// IGNORE
+		'format_date_hour' => 'j %s Y\\, H\\:i',	// IGNORE
 		'fri' => 'Pt.',
 		'jan' => 'Sty.',
 		'january' => 'Styczeń',
@@ -106,9 +116,9 @@ return array(
 		'wed' => 'Śr.',
 		'yesterday' => 'Wczorajsze',
 	),
-	'dir' => 'ltr',	// TODO - Translation
+	'dir' => 'ltr',	// TODO
 	'freshrss' => array(
-		'_' => 'FreshRSS',
+		'_' => 'FreshRSS',	// IGNORE
 		'about' => 'O serwisie FreshRSS',
 	),
 	'js' => array(
@@ -124,24 +134,24 @@ return array(
 		'should_be_activated' => 'JavaScript musi być włączony',
 	),
 	'lang' => array(
-		'cz' => 'Čeština',
-		'de' => 'Deutsch',
-		'en' => 'English',
-		'en-us' => 'English (United States)',
-		'es' => 'Español',
-		'fr' => 'Français',
-		'he' => 'עברית',
-		'it' => 'Italiano',
-		'ja' => '日本語',
-		'ko' => '한국어',
-		'nl' => 'Nederlands',
-		'oc' => 'Occitan',
-		'pl' => 'Polski',
-		'pt-br' => 'Português (Brasil)',
-		'ru' => 'Русский',
-		'sk' => 'Slovenčina',
-		'tr' => 'Türkçe',
-		'zh-cn' => '简体中文',
+		'cz' => 'Čeština',	// IGNORE
+		'de' => 'Deutsch',	// IGNORE
+		'en' => 'English',	// IGNORE
+		'en-us' => 'English (United States)',	// IGNORE
+		'es' => 'Español',	// IGNORE
+		'fr' => 'Français',	// IGNORE
+		'he' => 'עברית',	// IGNORE
+		'it' => 'Italiano',	// IGNORE
+		'ja' => '日本語',	// IGNORE
+		'ko' => '한국어',	// IGNORE
+		'nl' => 'Nederlands',	// IGNORE
+		'oc' => 'Occitan',	// IGNORE
+		'pl' => 'Polski',	// IGNORE
+		'pt-br' => 'Português (Brasil)',	// IGNORE
+		'ru' => 'Русский',	// IGNORE
+		'sk' => 'Slovenčina',	// IGNORE
+		'tr' => 'Türkçe',	// IGNORE
+		'zh-cn' => '简体中文',	// IGNORE
 	),
 	'menu' => array(
 		'about' => 'O serwisie',
@@ -183,25 +193,25 @@ return array(
 	),
 	'share' => array(
 		'Known' => 'Strony bazujące na usłudze Known',
-		'blogotext' => 'Blogotext',
+		'blogotext' => 'Blogotext',	// IGNORE
 		'clipboard' => 'Schowek',
-		'diaspora' => 'Diaspora*',
+		'diaspora' => 'Diaspora*',	// IGNORE
 		'email' => 'E-mail',
-		'facebook' => 'Facebook',
-		'gnusocial' => 'GNU social',
-		'jdh' => 'Journal du hacker',
-		'lemmy' => 'Lemmy',
-		'linkedin' => 'LinkedIn',
-		'mastodon' => 'Mastodon',
-		'movim' => 'Movim',
-		'pinboard' => 'Pinboard',
-		'pocket' => 'Pocket',
+		'facebook' => 'Facebook',	// IGNORE
+		'gnusocial' => 'GNU social',	// IGNORE
+		'jdh' => 'Journal du hacker',	// IGNORE
+		'lemmy' => 'Lemmy',	// IGNORE
+		'linkedin' => 'LinkedIn',	// IGNORE
+		'mastodon' => 'Mastodon',	// IGNORE
+		'movim' => 'Movim',	// IGNORE
+		'pinboard' => 'Pinboard',	// IGNORE
+		'pocket' => 'Pocket',	// IGNORE
 		'print' => 'Wydruk',
-		'raindrop' => 'Raindrop.io',
-		'shaarli' => 'Shaarli',
-		'twitter' => 'Twitter',
-		'wallabag' => 'wallabag v1',
-		'wallabagv2' => 'wallabag v2',
+		'raindrop' => 'Raindrop.io',	// IGNORE
+		'shaarli' => 'Shaarli',	// IGNORE
+		'twitter' => 'Twitter',	// IGNORE
+		'wallabag' => 'wallabag v1',	// IGNORE
+		'wallabagv2' => 'wallabag v2',	// IGNORE
 	),
 	'short' => array(
 		'attention' => 'Uwaga!',
@@ -212,7 +222,7 @@ return array(
 		'default_category' => 'Brak kategorii',
 		'no' => 'Nie',
 		'not_applicable' => 'Niedostępne',
-		'ok' => 'Okay!',
+		'ok' => 'Okay!',	// IGNORE
 		'or' => 'lub',
 		'yes' => 'Tak',
 	),

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů