lyrics 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +17 -0
  5. data/Rakefile +45 -0
  6. data/VERSION +1 -0
  7. data/bin/lyrics +66 -0
  8. data/lib/lyrics.rb +4 -0
  9. data/lib/lyrics/cli/application.rb +99 -0
  10. data/lib/lyrics/cli/optionsparser.rb +228 -0
  11. data/lib/lyrics/cli/pluginadapter.rb +56 -0
  12. data/lib/lyrics/cli/plugins.rb +79 -0
  13. data/lib/lyrics/cli/wikipluginadapter.rb +139 -0
  14. data/lib/lyrics/i18n/README +1 -0
  15. data/lib/lyrics/i18n/en.rb +181 -0
  16. data/lib/lyrics/i18n/es.rb +181 -0
  17. data/lib/lyrics/i18n/i18n.rb +126 -0
  18. data/lib/lyrics/i18n/sk.rb +174 -0
  19. data/lib/lyrics/itrans/COPYRIGHT +31 -0
  20. data/lib/lyrics/itrans/itrans +0 -0
  21. data/lib/lyrics/itrans/itrans.txt +8 -0
  22. data/lib/lyrics/itrans/lyric.txt +23 -0
  23. data/lib/lyrics/itrans/udvng.ifm +206 -0
  24. data/lib/lyrics/lyrics.rb +567 -0
  25. data/lib/lyrics/lyrics_AZLyrics.rb +113 -0
  26. data/lib/lyrics/lyrics_DarkLyrics.rb +124 -0
  27. data/lib/lyrics/lyrics_Giitaayan.rb +124 -0
  28. data/lib/lyrics/lyrics_Jamendo.rb +166 -0
  29. data/lib/lyrics/lyrics_LeosLyrics.rb +142 -0
  30. data/lib/lyrics/lyrics_LoudSongs.rb +135 -0
  31. data/lib/lyrics/lyrics_LyricWiki.rb +328 -0
  32. data/lib/lyrics/lyrics_LyricsDownload.rb +118 -0
  33. data/lib/lyrics/lyrics_LyricsMania.rb +141 -0
  34. data/lib/lyrics/lyrics_Lyriki.rb +286 -0
  35. data/lib/lyrics/lyrics_SeekLyrics.rb +108 -0
  36. data/lib/lyrics/lyrics_Sing365.rb +103 -0
  37. data/lib/lyrics/lyrics_TerraLetras.rb +126 -0
  38. data/lib/lyrics/mediawikilyrics.rb +1417 -0
  39. data/lib/lyrics/utils/formdata.rb +56 -0
  40. data/lib/lyrics/utils/htmlentities.rb +291 -0
  41. data/lib/lyrics/utils/http.rb +198 -0
  42. data/lib/lyrics/utils/itrans.rb +160 -0
  43. data/lib/lyrics/utils/logger.rb +123 -0
  44. data/lib/lyrics/utils/strings.rb +378 -0
  45. data/lib/lyrics/utils/xmlhash.rb +111 -0
  46. data/lyrics.gemspec +98 -0
  47. data/spec/lyrics_spec.rb +7 -0
  48. data/spec/spec.opts +1 -0
  49. data/spec/spec_helper.rb +9 -0
  50. metadata +137 -0
@@ -0,0 +1,56 @@
1
+ # Copyright (C) 2006-2008 by Sergio Pistone
2
+ # sergio_pistone@yahoo.com.ar
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the
16
+ # Free Software Foundation, Inc.,
17
+ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
+
19
+ require "cgi"
20
+
21
+ module PluginAdapter
22
+
23
+ # Hack to make module methods become class methods when the module gets included
24
+ def PluginAdapter.included( including )
25
+ if including.is_a?( Class )
26
+ including.extend( ClassMethods ) # adds class methods
27
+ else # if including.is_a?( Module )
28
+ including::ClassMethods.append_class_methods( self )
29
+ end
30
+ end
31
+
32
+ # Methods under this module will became class methods when the module gets included
33
+ # Note: don't use def self.<method name> but just <method name>
34
+ module ClassMethods
35
+ def ClassMethods.append_class_methods( mod )
36
+ include mod::ClassMethods
37
+ end
38
+
39
+ def plugin_name()
40
+ return site_name()
41
+ end
42
+
43
+ def notify( message )
44
+ puts plugin_name() + ": " + message.gsub( /\/?<[^>]+>/, "" )
45
+ end
46
+ end
47
+
48
+ def plugin_name()
49
+ return self.class.plugin_name()
50
+ end
51
+
52
+ def notify( message )
53
+ self.class.notify( message )
54
+ end
55
+
56
+ end
@@ -0,0 +1,79 @@
1
+ # Copyright (C) 2007 by Sergio Pistone
2
+ # sergio_pistone@yahoo.com.ar
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the
16
+ # Free Software Foundation, Inc.,
17
+ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
+
19
+ require File.expand_path( File.dirname( __FILE__ ) + "/../mediawikilyrics" )
20
+ require File.expand_path( File.dirname( __FILE__ ) + "/pluginadapter" )
21
+ require File.expand_path( File.dirname( __FILE__ ) + "/wikipluginadapter" )
22
+
23
+ module Plugins
24
+
25
+ @@ALL = []
26
+ @@WIKI = []
27
+
28
+ def Plugins.find_plugins()
29
+ plugins = {}
30
+ Dir.new( File.expand_path( File.dirname( __FILE__ ) + "/.." ) ).each() do |filename|
31
+ filename = File.expand_path( File.dirname( __FILE__ ) + "/../" + filename )
32
+ if File.file?( filename ) && (md = /\/lyrics_([A-Za-z_0-9]*)\.rb$/.match( filename ))
33
+ plugins[md[1]] = filename
34
+ end
35
+ end
36
+ return plugins
37
+ end
38
+
39
+ def Plugins.load_plugins( plugins )
40
+ plugins.each() do |classname, filename|
41
+ require( filename ? filename : File.expand_path( File.dirname( __FILE__ ) + "/../lyrics_#{classname}.rb" ) )
42
+ classobj = eval( classname )
43
+ if classobj.ancestors().include?( MediaWikiLyrics )
44
+ eval( "class CLI#{classname} < #{classname}\ninclude WikiPluginAdapter\nend" ) # FIXME: refactor
45
+ plugin = eval( "CLI#{classname}.new()" )
46
+ @@WIKI << plugin
47
+ else
48
+ eval( "class CLI#{classname} < #{classname}\ninclude PluginAdapter\nend" ) # FIXME: refactor
49
+ plugin = eval( "CLI#{classname}.new()" )
50
+ end
51
+ @@ALL << plugin
52
+ end
53
+ end
54
+
55
+
56
+ def Plugins.all_plugins()
57
+ return @@ALL
58
+ end
59
+
60
+ def Plugins.all_names()
61
+ return @@ALL.collect(){ |plugin| plugin.plugin_name() }
62
+ end
63
+
64
+ def Plugins.wiki_plugins()
65
+ return @@WIKI
66
+ end
67
+
68
+ def Plugins.wiki_names()
69
+ return @@WIKI.collect(){ |plugin| plugin.plugin_name() }
70
+ end
71
+
72
+ def Plugins.plugin_by_name( name )
73
+ @@ALL.each() do |plugin|
74
+ return plugin if plugin.plugin_name() == name
75
+ end
76
+ return nil
77
+ end
78
+
79
+ end
@@ -0,0 +1,139 @@
1
+ # Copyright (C) 2006-2008 by Sergio Pistone
2
+ # sergio_pistone@yahoo.com.ar
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the
16
+ # Free Software Foundation, Inc.,
17
+ # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
+
19
+ require File.expand_path( File.dirname( __FILE__ ) + "/../utils/strings" )
20
+ require File.expand_path( File.dirname( __FILE__ ) + "/../i18n/i18n" )
21
+ require File.expand_path( File.dirname( __FILE__ ) + "/pluginadapter" )
22
+ require File.expand_path( File.dirname( __FILE__ ) + "/plugins" )
23
+
24
+ require "md5"
25
+ require "uri"
26
+
27
+ module WikiPluginAdapter
28
+
29
+ # Hack to make module methods become class methods when the module gets included
30
+ def WikiPluginAdapter.included( including )
31
+ if including.is_a?( Class )
32
+ including.extend( ClassMethods ) # adds class methods
33
+ else # including.is_a?( Module )
34
+ including::ClassMethods.append_class_methods( self )
35
+ end
36
+ end
37
+
38
+ # Methods under this module will became class methods when the module gets included
39
+ # Note: don't use def self.<method name> but just <method name>
40
+ module ClassMethods
41
+ def ClassMethods.append_class_methods( mod )
42
+ include mod::ClassMethods
43
+ end
44
+ end
45
+
46
+ include PluginAdapter
47
+
48
+ def submit?()
49
+ return @wpa_submit
50
+ end
51
+
52
+ def check_submit_conditions()
53
+ if @wpa_submit
54
+ login( @wpa_username, @wpa_password, false )
55
+ else
56
+ logout()
57
+ end
58
+
59
+ if ! logged_in?
60
+ @wpa_submit = false
61
+ end
62
+
63
+ if ! @wpa_submit || ! @wpa_review
64
+ @wpa_prompt_no_lyrics = false
65
+ @wpa_prompt_autogen = false
66
+ end
67
+ end
68
+
69
+ def set_submit_settings( username, password, review, prompt_autogen, prompt_no_lyrics )
70
+ @wpa_submit = true
71
+ @wpa_review = review
72
+ @wpa_prompt_autogen = prompt_autogen
73
+ @wpa_prompt_no_lyrics = prompt_no_lyrics
74
+ @wpa_username = username
75
+ @wpa_password = password
76
+ if ! @wpa_submit || ! @wpa_review
77
+ @wpa_prompt_no_lyrics = false
78
+ @wpa_prompt_autogen = false
79
+ end
80
+ end
81
+
82
+ # returns true if the review contents page is shown to the user (which can only happen when there was something to submit)
83
+ def wiki_process_response( response, response_plugin, wiki_searched )
84
+
85
+ return false if ! submit?() || ! authorized?
86
+
87
+ lyrics_found_on_site = response.lyrics && response_plugin == self
88
+ lyrics_autogenerated = lyrics_found_on_site && ! response.custom_data["reviewed"]
89
+
90
+ return false if lyrics_found_on_site && ! lyrics_autogenerated # we have nothing to do
91
+ return false if (! @wpa_prompt_autogen && lyrics_autogenerated) || (! @wpa_prompt_no_lyrics && ! response.lyrics)
92
+
93
+ begin
94
+
95
+ check_submit_conditions()
96
+
97
+ song_data = MediaWikiLyrics::SongData.new(
98
+ response.artist ? response.artist : response.request.artist,
99
+ response.title ? response.title : response.request.title,
100
+ response.lyrics,
101
+ response.album ? response.album : response.request.album,
102
+ response.year ? response.year : response.request.year,
103
+ response.custom_data["credits"],
104
+ response.custom_data["lyricist"]
105
+ )
106
+
107
+ submitted_url, submitted_data = submit_song_page(
108
+ song_data,
109
+ lyrics_autogenerated ? response.url : nil, # are we editing an existing page or creating a new one?
110
+ song_data.artist == response.request.artist && song_data.title == response.request.title &&
111
+ wiki_searched && ! lyrics_found_on_site, # do we KNOW FOR SURE the page doesn't exists?
112
+ @wpa_review || lyrics_autogenerated, # should we show the review contents dialog?
113
+ lyrics_autogenerated # should user be forced to review contents? (true causes the operation to abort otherwise)
114
+ )
115
+
116
+ # transfer summited data to response
117
+ if submitted_data
118
+ response.artist = submitted_data["artist"] if ! Strings.empty?( submitted_data["artist"] )
119
+ response.title = submitted_data["title"] if ! Strings.empty?( submitted_data["title"] )
120
+ response.album = submitted_data["album"] if ! Strings.empty?( submitted_data["album"] )
121
+ response.year = submitted_data["year"] if ! Strings.empty?( submitted_data["year"] )
122
+ response.lyrics = submitted_data["lyrics"] if ! Strings.empty?( submitted_data["lyrics"] )
123
+ custom_data = {}
124
+ custom_data.merge( response.custom_data )
125
+ custom_data["credits"] = submitted_data["credits"] if ! Strings.empty?( submitted_data["credits"] )
126
+ custom_data["lyricst"] = submitted_data["lyricst"] if ! Strings.empty?( submitted_data["lyricst"] )
127
+ response.custom_data = custom_data
128
+ end
129
+
130
+ return (@wpa_review || lyrics_autogenerated) && submitted_data
131
+
132
+ rescue TimeoutError
133
+ notify( I18n.get( "cli.application.plugintimeout", plugin_name(), site_host() ) )
134
+ return false
135
+ end
136
+
137
+ end
138
+
139
+ end
@@ -0,0 +1 @@
1
+ IMPORTANT: save all language files with UTF-8 encoding
@@ -0,0 +1,181 @@
1
+ cli.usage = Usage: %1 [OPTIONS]
2
+ cli.description = Fetch lyrics from various sites and/or submit lyrics to Lyriki and LyricWiki.
3
+ cli.values.true = true
4
+ cli.values.false = false
5
+ cli.options = Options:
6
+ cli.options.artist = Song artist (mandatory unless %1 specified).
7
+ cli.options.title = Song title (mandatory unless %1 specified).
8
+ cli.options.album = Song album.
9
+ cli.options.year = Song album year.
10
+ cli.options.featfix = Fix artist/title when the later has "feat. ARTIST" (%1 by default).
11
+ cli.options.batchfile = Batch process file (expects artist;title;album;year entries in each line).
12
+ cli.options.cleanup = Cleanup fetched lyrics (%1 by default).
13
+ cli.options.sites = Sites to search lyrics for, order included (%1 by default; see %2).
14
+ cli.options.sites.list = List available sites.
15
+ cli.options.sites.list.available = Available sites:
16
+ cli.options.submit = Wiki site to submit content to (needs %1 and %2).
17
+ cli.options.username = Username to login with (mandatory when %1 specified).
18
+ cli.options.password = Password to login with (mandatory when %1 specified).
19
+ cli.options.persist = Restore/save session from/to file (needs %1 and %2).
20
+ cli.options.prompt.review = Prompt for review before submitting content (%1 by default, needs %2).
21
+ cli.options.prompt.autogen = Prompt for review of autogenerated pages (%1 by default, needs %2).
22
+ cli.options.prompt.nolyrics = Prompt for submission even when no lyrics to submit where found (%1 by default, needs %2).
23
+ cli.options.proxy = Proxy server URL.
24
+ cli.options.toolkits = GUI toolkits priority. Loading falls back to the next toolkit when one fails; an empty list will cause no dialog to be shown and lyrics to be dumped to stdout (defaults to %1).
25
+ cli.options.help = Show this message and exit.
26
+ cli.options.version = Show version and exit.
27
+ cli.error.missingoption = missing %1
28
+ cli.error.missingdependency = %1 requires %1
29
+ cli.error.incompatibleoptions = %1 is incompatible with %2
30
+ cli.error.invalidoptionvalue = invalid %1 value: %2
31
+ cli.error.nosite = must provide at least one site
32
+ cli.error.notoolkit = must provide at least one toolkit to use review mode
33
+
34
+ cli.application.searchinglyrics = searching lyrics for %1 by %2...
35
+ cli.application.lyricsfound = lyrics for %1 by %2 found at %3
36
+ cli.application.nolyricsfound = no lyrics found for %1 by %2
37
+ cli.application.plugintimeout = %1 request has timed out, site %2 is probably down
38
+ cli.application.batchmode = operating in batch mode
39
+ cli.application.processedcount = %1 files processed
40
+
41
+ amarok.application.error.connectionrefused = Can't connect to the Internet (check your proxy settings)
42
+ amarok.application.error.connectiondown = The connection is down, exiting
43
+ amarok.application.error.notoolkit = Sorry...\nYou need one of QtRuby, RubyGTK or TkRuby to run this program
44
+ amarok.application.error.nopluginsselected = No sites to search lyrics for specified
45
+ amarok.application.search.current = Search current song lyrics
46
+ amarok.application.search.current.nosongplaying = no song currently playing
47
+ amarok.application.search.selected = Search selected song lyrics
48
+ amarok.application.search.noinfofound = no song info found in Amarok database
49
+ amarok.application.search.nolyricsfound = no lyrics found for <b>%1</b> by <b>%2</b>
50
+ amarok.application.search.plugintimeout = %1 request has timed out! Site %2 is probably down
51
+ amarok.application.clearlyricscache = Clear lyrics cache
52
+ amarok.application.clearlyricscache.confirm = Are you sure you want to clear the lyrics cache?
53
+ amarok.application.clearlyricscache.done = lyrics cache cleared
54
+
55
+ amarok.wikiplugin.checksong = Check/Submit song page
56
+ amarok.wikiplugin.checksong.noinfofound = no song info found in Amarok database
57
+ amarok.wikiplugin.checkalbum = Check/Submit album page
58
+ amarok.wikiplugin.checkalbum.noinfofound = no album info found in Amarok database
59
+ amarok.wikiplugin.uploadcover = Upload album cover
60
+ amarok.wikiplugin.uploadcover.invalidalbumparams = invalid album params received
61
+ amarok.wikiplugin.uploadcover.noimagepath = no cover image received
62
+ amarok.wikiplugin.uploadcover.searching = searching album cover for <b>%1</b> by <b>%2</b>...
63
+ amarok.wikiplugin.uploadcover.found = album cover found (no need to upload)
64
+ amarok.wikiplugin.submitcontent = Submit contents
65
+
66
+ gui.common.cut = Cut
67
+ gui.common.copy = Copy
68
+ gui.common.paste = Paste
69
+ gui.common.delete = Delete
70
+ gui.common.selectall = Select All
71
+ gui.common.undo = Undo
72
+ gui.common.redo = Redo
73
+
74
+ gui.common.accept = Accept
75
+ gui.common.cancel = Cancel
76
+ gui.common.submit = Submit
77
+ gui.common.load = Load
78
+ gui.common.fix = Fix
79
+ gui.common.url = URL
80
+ gui.common.artist = Artist
81
+ gui.common.song = Song
82
+ gui.common.album = Album
83
+ gui.common.year = Year
84
+ gui.common.month = Month
85
+ gui.common.day = Day
86
+ gui.common.released = Released
87
+ gui.common.credits = Credits
88
+ gui.common.lyricist = Lyricist
89
+ gui.common.image = Image
90
+ gui.common.reviewed = I have reviewed the contents of this form
91
+
92
+ gui.searchlyrics.title = Search lyrics
93
+ gui.searchlyrics.search = Search Settings
94
+
95
+ gui.lyrics.title = Lyrics to %1 by %2
96
+
97
+ gui.pluginsmanager.title = %1 script configuration
98
+ gui.pluginsmanager.sites = Sites
99
+ gui.pluginsmanager.sites.inuse = Currently used
100
+ gui.pluginsmanager.sites.available = Available
101
+ gui.pluginsmanager.sites.moveup = Move Up
102
+ gui.pluginsmanager.sites.movedown = Move Down
103
+ gui.pluginsmanager.sites.add = << Add
104
+ gui.pluginsmanager.sites.remove = >> Remove
105
+ gui.pluginsmanager.misc = Miscellaneous
106
+ gui.pluginsmanager.misc.cleanup = Clean up retrieved lyrics
107
+ gui.pluginsmanager.misc.singlethreaded = Avoid using multiple threads to save battery (needs restart)
108
+ gui.pluginsmanager.misc.writelog = Write log to %1
109
+
110
+ gui.wikiplugin.title = Configure %1 settings
111
+ gui.wikiplugin.general = General Settings
112
+ gui.wikiplugin.general.submit = Submit contents to %1
113
+ gui.wikiplugin.general.review = Prompt for review before submitting contents
114
+ gui.wikiplugin.general.autogen = Review song pages marked as auto-generated
115
+ gui.wikiplugin.general.nolyrics = Show submit dialog even if no lyrics were found
116
+ gui.wikiplugin.login = Login Settings
117
+ gui.wikiplugin.login.username = Username
118
+ gui.wikiplugin.login.password = Password
119
+
120
+ gui.submitsong.title.submit = %1 - Submit song page
121
+ gui.submitsong.title.edit = %1 - Review song page
122
+ gui.submitsong.instrumental = Song is instrumental
123
+
124
+ gui.submitalbum.title = %1 - Submit album page
125
+ gui.submitalbum.coverfound = (cover found, no need to upload)
126
+
127
+ gui.uploadcover.title = %1 - Upload album cover
128
+ gui.uploadcover.imagepath = Path
129
+ gui.uploadcover.browseimage.title = Select album cover image path
130
+ gui.uploadcover.browseimage.images = Images
131
+ gui.uploadcover.browseimage.allfiles = All Files
132
+
133
+ gui.fixpages.success = Submitted page %1
134
+ gui.fixpages.error = Error submitting page %1
135
+
136
+ wiki.control.versionblocked = <b>Version %1 has been blocked</b> from submitting content. Please, update to the last version.
137
+ wiki.control.userblocked = <b>User %1 has been blocked</b> from submitting content. Please, check your user page.
138
+ wiki.control.updated = A new version of the script has been released. <b>Please, update to version %1</b>.
139
+
140
+ wiki.login.attempt = starting session for user <b>%1</b>...
141
+ wiki.login.success = session started successfully for user <b>%1</b>
142
+ wiki.login.error = error starting session for user <b>%1</b>
143
+ wiki.logout = session finished for user <b>%1</b>
144
+
145
+ wiki.session.save.success = session saved for user <b>%1</b>
146
+ wiki.session.save.error.notloggedin = can't save session before logging in
147
+ wiki.session.save.error = there was an error saving the session for user <b>%1</b>
148
+ wiki.session.restore.success = session restored for user <b>%1</b>
149
+ wiki.session.restore.error = there was an error restoring the session for user <b>%1</b>
150
+ wiki.session.restore.notfound = no saved session found
151
+
152
+ wiki.submitsong.searchingpage = searching song page for <b>%1</b> by <b>%2</b>...
153
+ wiki.submitsong.pagefound = song page found for <b>%1</b> by <b>%2</b>
154
+ wiki.submitsong.pagefound.autogenerated = auto-generated song page found for <b>%1</b> by <b>%2</b>
155
+ wiki.submitsong.nopagefound = no song page found for <b>%1</b> by <b>%2</b>
156
+ wiki.submitsong.cancelled = song page submission cancelled by user
157
+ wiki.submitsong.mustreviewcontent = contents were not reviewed, submission cancelled
158
+ wiki.submitsong.success = successfully submitted song page for <b>%1</b> by <b>%2</b>
159
+ wiki.submitsong.error.invalidsong = invalid song title received
160
+ wiki.submitsong.error.invalidartist = invalid album artist received
161
+ wiki.submitsong.error.nolyrics = no lyrics to submit received
162
+ wiki.submitsong.error = there was an error submitting the song page for <b>%1</b> by <b>%2</b>
163
+
164
+ wiki.submitalbum.searchingpage = searching album page for <b>%1</b> by <b>%2</b>...
165
+ wiki.submitalbum.pagefound = found album page for <b>%1</b> by <b>%2</b>
166
+ wiki.submitalbum.nopagefound = no album page found for <b>%1</b> by <b>%2</b>
167
+ wiki.submitalbum.cancelled = album page submission cancelled by user
168
+ wiki.submitalbum.mustreviewcontent = contents were not reviewed, submission cancelled
169
+ wiki.submitalbum.success = successfully submitted album page for <b>%1</b> by <b>%2</b>
170
+ wiki.submitalbum.error.invalidyear = invalid album year received
171
+ wiki.submitalbum.error.invalidalbum = invalid album name received
172
+ wiki.submitalbum.error.invalidartist = invalid album artist received
173
+ wiki.submitalbum.error = there was an error submitting the album page for <b>%1</b> by <b>%2</b>
174
+
175
+ wiki.submitredirect.success = submitted redirect page to %1
176
+ wiki.submitredirect.error = there was an error submitting the redirect page to %1
177
+
178
+ wiki.uploadcover.uploading = uploading album cover for <b>%1</b> by <b>%2</b>
179
+ wiki.uploadcover.success = successfully uploaded album cover for <b>%1</b> by <b>%2</b>
180
+ wiki.uploadcover.error.convert = there was an error converting the album cover to JPEG format
181
+ wiki.uploadcover.error = there was an error uploading the album cover for <b>%1</b> by <b>%2</b>