
diff --git a/db/migrate/20110630035132_add_lang_to_user.rb b/db/migrate/20110630035132_add_lang_to_user.rb
new file mode 100644
index 0000000..b267b0f
--- /dev/null
+++ b/db/migrate/20110630035132_add_lang_to_user.rb
@@ -0,0 +1,9 @@
+class AddLangToUser < ActiveRecord::Migration
+ def self.up
+ add_column :users, :lang, :string
+ end
+
+ def self.down
+ remove_column :users, :lang
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 63032cd..d51a67c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20110624073136) do
+ActiveRecord::Schema.define(:version => 20110630035132) do
create_table "albums", :force => true do |t|
t.string "name"
@@ -101,6 +101,7 @@ ActiveRecord::Schema.define(:version => 20110624073136) do
t.datetime "updated_at"
t.string "lastfm_key"
t.string "lastfm_username"
+ t.string "lang"
end
end
diff --git a/public/javascripts/coffee/ajax.js b/public/javascripts/coffee/ajax.js
index fbfb0de..c6f7ea1 100644
--- a/public/javascripts/coffee/ajax.js
+++ b/public/javascripts/coffee/ajax.js
@@ -32,14 +32,14 @@ Ajax = (function() {
Ajax.prototype.loadSearchPage = function() {
$.get('/templates/search.html', function(data) {
_ajax.setArchor('/search/');
- return _pages.renderSearch(data);
+ return _pages.renderSearch(_beathaven.localizeHTML($(data)));
});
return false;
};
Ajax.prototype.loadSettingsPage = function() {
$.get('/templates/settings.html', function(data) {
_ajax.setArchor('/settings/');
- return _pages.renderSettings(data);
+ return _pages.renderSettings(_beathaven.localizeHTML($(data)));
});
return false;
};
diff --git a/public/javascripts/coffee/beathaven.js b/public/javascripts/coffee/beathaven.js
index 0a004e4..c59a650 100644
--- a/public/javascripts/coffee/beathaven.js
+++ b/public/javascripts/coffee/beathaven.js
@@ -16,15 +16,18 @@ $(function() {
_beathaven = new BeatHaven();
_beathaven.init();
$(window).resize(function() {
- return _beathaven.adjustSizes();
+ _beathaven.adjustSizes();
+ return false;
});
return window.setTimeout(function() {
- return _beathaven.checkRedrawScrollbar();
+ _beathaven.checkRedrawScrollbar();
+ return false;
}, 500);
});
BeatHaven = (function() {
function BeatHaven() {}
BeatHaven.prototype.last_height = false;
+ BeatHaven.prototype.lang = 'ru';
BeatHaven.prototype.init = function() {
this.adjustSizes();
this.checkRedrawScrollbar();
@@ -35,7 +38,8 @@ BeatHaven = (function() {
_player.initJplayer();
_search = new Search();
_pages = new Pages();
- return _settings = new Settings();
+ _settings = new Settings();
+ return false;
};
BeatHaven.prototype.adjustSizes = function() {
$('.data-container').height($(window).height() - $('.header-container').height());
@@ -43,7 +47,8 @@ BeatHaven = (function() {
$('.player-container').height($(window).height());
$('.playlist').height($(window).height() - $('.player').height() - $('.player-container .additional-controls').height());
$('.data-container').scrollbar();
- return $('.playlist').scrollbar();
+ $('.playlist').scrollbar();
+ return false;
};
BeatHaven.prototype.checkRedrawScrollbar = function() {
var focused_id, outer_height;
@@ -60,13 +65,41 @@ BeatHaven = (function() {
document.getElementById(focused_id).focus();
focused_id = false;
}
- return window.setTimeout(function() {
- return _beathaven.checkRedrawScrollbar();
+ window.setTimeout(function() {
+ _beathaven.checkRedrawScrollbar();
+ return false;
}, 500);
+ return false;
};
BeatHaven.prototype.redrawScrollbar = function() {
$('.data-container').html($('.data-container').find('.inner').first());
- return $('.data-container').scrollbar();
+ $('.data-container').scrollbar();
+ return false;
+ };
+ BeatHaven.prototype.localizeHTML = function(obj) {
+ if (obj == null) {
+ obj = $('body');
+ }
+ $(obj).find('[data-ls]').each(function() {
+ if ((_locale[$(this).attr('data-ls')] != null) && (_locale[$(this).attr('data-ls')][_beathaven.lang] != null)) {
+ if (this.nodeName === 'INPUT') {
+ return $(this).val(_locale[$(this).attr('data-ls')][_beathaven.lang]);
+ } else {
+ return $(this).text(_locale[$(this).attr('data-ls')][_beathaven.lang]);
+ }
+ }
+ });
+ return obj;
+ };
+ BeatHaven.prototype.ls = function(id, lang) {
+ if (lang == null) {
+ lang = _beathaven.lang;
+ }
+ if ((_locale[id] != null) && (_locale[id][lang] != null)) {
+ return _locale[id][lang];
+ } else {
+ return id;
+ }
};
return BeatHaven;
})();
diff --git a/public/javascripts/coffee/locale.js b/public/javascripts/coffee/locale.js
new file mode 100644
index 0000000..d5bb28e
--- /dev/null
+++ b/public/javascripts/coffee/locale.js
@@ -0,0 +1,99 @@
+var _locale;
+_locale = {
+ SEARCH: {
+ en: "Search",
+ ru: "Поиск"
+ },
+ NEWS: {
+ en: "News",
+ ru: "Новости"
+ },
+ ABOUT: {
+ en: "About",
+ ru: "О проекте"
+ },
+ LOGIN: {
+ en: "Log in",
+ ru: "Войти"
+ },
+ LOGOUT: {
+ en: "Log out",
+ ru: "Выйти"
+ },
+ ADD_SOME_MUSIC: {
+ en: "Add some music to playlist",
+ ru: "Добавьте музыку в плей-лист"
+ },
+ LOGIN_PLEASE: {
+ en: "Don't forget to log in, please. It's simple.",
+ ru: "Авторизуйтесь, пожалуйста. Это действительно просто."
+ },
+ REPEAT: {
+ en: "Repeat",
+ ru: "Повторять"
+ },
+ SHUFFLE: {
+ en: "Shuffle",
+ ru: "Перемешать"
+ },
+ EMPTY_PLAYLIST: {
+ en: "Empty playlist",
+ ru: "Очистить"
+ },
+ HELLO: {
+ en: "Hi there",
+ ru: "Привет"
+ },
+ ARTIST_LOADING_FAILED: {
+ en: "Something very bad happened while we tried out to load some info about this artist. How about some other one?",
+ ru: "Что-то ужасное произошло пока мы собирали информацию об этом исполнителе. Может пока поищем другого?"
+ },
+ ARTIST_LOADING_IN_PROCESS: {
+ en: "Artist info is loading for the first time now. Usually it takes less than a minute, please wait a bit.",
+ ru: "Прямо сейчас мы собираем всю возможною информацию об этом исполнителе в первый раз. Обычно это занимает меньше минуты."
+ },
+ MISSPELLED: {
+ en: "Misspelled?",
+ ru: "Опечатались?"
+ },
+ SETTINGS_ACCOUNT: {
+ en: "Account",
+ ru: "Аккаунт"
+ },
+ SETTINGS_LASTFM: {
+ en: "Last.fm",
+ ru: "Last.fm"
+ },
+ USERNAME: {
+ en: "Username",
+ ru: "Имя"
+ },
+ EMAIL: {
+ en: "Email",
+ ru: "Почта"
+ },
+ LANG: {
+ en: "Language",
+ ru: "Язык"
+ },
+ USELESS_BUTTON: {
+ en: "Hello, my name is Useless Button",
+ ru: "Привет, меня зовут Бесполезная Кнопка"
+ },
+ NOT_CONNECTED: {
+ en: "Not connected",
+ ru: "Не подключен"
+ },
+ CONNECT: {
+ en: "Connect",
+ ru: "Подключить"
+ },
+ WINDOW_LANG_RELOAD: {
+ en: "To change application language it is needed to reload page. Your current playlist will be emptied and music will stop. Do you really wish to continue?",
+ ru: "Чтобы изменить язык приложения, необходимо перезагрузить страницу. Ваш текущий плей-лист будет очищен и музыка остановится. Вы действительно хотите продолжить?"
+ },
+ ADD_TO_NOW_PLAYING: {
+ en: "Add to Now Playing",
+ ru: "Добавить в плей-лист"
+ }
+};
\ No newline at end of file
diff --git a/public/javascripts/coffee/pages.js b/public/javascripts/coffee/pages.js
index cb9acad..ebe5187 100644
--- a/public/javascripts/coffee/pages.js
+++ b/public/javascripts/coffee/pages.js
@@ -23,7 +23,7 @@ Pages = (function() {
\
 + ')
\
\
\
\
diff --git a/public/javascripts/coffee/session.js b/public/javascripts/coffee/session.js
index 8c423ad..a385b7f 100644
--- a/public/javascripts/coffee/session.js
+++ b/public/javascripts/coffee/session.js
@@ -16,6 +16,8 @@ Session = (function() {
}
Session.prototype.setUser = function(user) {
this.user = user;
+ _beathaven.lang = this.user.lang;
+ _beathaven.localizeHTML();
return false;
};
Session.prototype.getUser = function() {
diff --git a/public/javascripts/coffee/settings.js b/public/javascripts/coffee/settings.js
index a061d38..d971521 100644
--- a/public/javascripts/coffee/settings.js
+++ b/public/javascripts/coffee/settings.js
@@ -13,6 +13,7 @@ Settings = (function() {
if (form === 'account') {
$('.settings-container .form input[name$="username"]').val(_session.getUser().name);
$('.settings-container .form input[name$="email"]').val(_session.getUser().email);
+ $('.settings-container .form select').val(_session.getUser().lang);
} else if (form === 'lastfm') {
if (_session.getUser().lastfm_username) {
$('.form-container input[name$="username"]').first().val(_session.getUser().lastfm_username);
@@ -51,15 +52,25 @@ $('.lastfm-connect').live('click', function() {
setTimeout(_settings.updateLastfmLogin, 100);
return false;
});
-$('.settings-container .form input').live('blur', function() {
- var active_tab, params;
+$('.settings-container .form input, .settings-container .form select').live('blur', function() {
+ var active_tab, lang_changed, params;
active_tab = $('.settings-container .tabs .tab.active').attr('data-fieldset');
if (active_tab === 'account') {
params = {
username: $('.settings-container .form input[name$="username"]').first().val(),
- email: $('.settings-container .form input[name$="email"]').first().val()
+ email: $('.settings-container .form input[name$="email"]').first().val(),
+ lang: $('.settings-container .form select').first().val()
};
+ lang_changed = params.lang !== _session.getUser().lang;
+ if (lang_changed) {
+ if (!confirm(_beathaven.ls('WINDOW_LANG_RELOAD', params.lang))) {
+ $('.settings-container .form select').val(_session.getUser().lang);
+ }
+ }
_settings.saveAccountInfo(params, function() {
+ if (lang_changed) {
+ window.location.reload();
+ }
$('.header-container .hello .greating span').text((params.username.length > 0 ? params.username : '%username%'));
return false;
});
diff --git a/public/javascripts/coffee/vkontakte.js b/public/javascripts/coffee/vkontakte.js
index d74a7a1..7418330 100644
--- a/public/javascripts/coffee/vkontakte.js
+++ b/public/javascripts/coffee/vkontakte.js
@@ -19,14 +19,14 @@ Vkontakte = (function() {
});
};
return setTimeout(function() {
- return $('#vk_api_transport').append('');
+ return $('#vk_api_transport').append('');
}, 0);
};
Vkontakte.prototype.authInfo = function(response) {
var _session;
if (typeof response !== 'undefined' && response.session) {
_session = new Session(response.session);
- $('#vk_login, .auth_notice').hide();
+ $('#vk_login, .auth-notice').hide();
$('#vk_logout').css({
display: 'block'
});
@@ -42,7 +42,7 @@ Vkontakte = (function() {
name: r.response
}, function(ar2) {
_session.setUser(ar2.user);
- $('.header-container .hello .greating').html('Tēnā koe,
' + (_session.getUser().name ? _session.getUser().name : '%username%') + '!');
+ $('.header-container .hello .greating').html(_beathaven.ls('HELLO') + ',
' + (_session.getUser().name ? _session.getUser().name : '%username%') + '!');
window._session = _session;
_ajax.detectPage();
return $('.fullscreen').hide();
@@ -52,7 +52,7 @@ Vkontakte = (function() {
_session.setUser(ar.user);
}
$('.header-container .hello').show();
- $('.header-container .hello .greating').html('Tēnā koe,
' + (_session.getUser().name ? _session.getUser().name : '%username%') + '!');
+ $('.header-container .hello .greating').html(_beathaven.ls('HELLO') + ',
' + (_session.getUser().name ? _session.getUser().name : '%username%') + '!');
window._session = _session;
_ajax.detectPage();
return $('.fullscreen').hide();
@@ -66,9 +66,10 @@ Vkontakte = (function() {
} else {
_session = new Session({});
_session.setUser({});
- $('#vk_login, .auth_notice').css({
+ $('#vk_login').css({
display: 'block'
});
+ $('.auth-notice').css('left', $('#vk_login').offset().left).show();
$('.header-container .hello').hide();
window._session = _session;
_ajax.detectPage();
@@ -152,7 +153,7 @@ Vkontakte = (function() {
};
return Vkontakte;
})();
-$('#vk_login').live('click', function() {
+$('#vk_login, .auth-notice').live('click', function() {
VK.Auth.login(function(response) {
_vkontakte.authInfo(response);
return false;
diff --git a/public/stylesheets/_sass/misc.scss b/public/stylesheets/_sass/misc.scss
index 99b61c2..5fdda5a 100644
--- a/public/stylesheets/_sass/misc.scss
+++ b/public/stylesheets/_sass/misc.scss
@@ -45,6 +45,10 @@
border-color: #eaa0a0;
box-shadow: #da9090 1px 1px 0px;
}
+
+ &.big {
+ font-size: 22px;
+ }
}
/* Scrollbars */
@@ -129,20 +133,22 @@
clear: both;
}
-.auth_notice {
+.auth-notice {
display: none;
position: absolute;
- background-color: #07F;
- color: #FFF;
+ background-color: #60a0ff;
+ color: #ffffff;
top: 32px;
- left: 280px;
- padding: 8px;
- border: #05D 1px solid;
+ left: 290px;
+ line-height: 35px;
+ padding-right: 10px;
+ border: #4080dd 1px solid;
@include rounded(3);
+ cursor: pointer;
.arrow {
float: left;
- margin: -8px 15px 0 8px;
+ margin: -5px 10px 0 10px;
font-size: 25px;
font-weight: bold;
}
diff --git a/public/stylesheets/_sass/search.scss b/public/stylesheets/_sass/search.scss
index 801f143..bf848f6 100644
--- a/public/stylesheets/_sass/search.scss
+++ b/public/stylesheets/_sass/search.scss
@@ -12,15 +12,6 @@
border: #CCC 1px solid;
@include rounded(3);
}
-
- #search_button {
- width: 100px;
- font-size: 24px;
- padding: 4px;
- background-color: #DDD;
- border: #CCC 1px solid;
- @include rounded(3);
- }
}
.spinner {
diff --git a/public/stylesheets/_sass/settings.scss b/public/stylesheets/_sass/settings.scss
index 377c7f6..372dc23 100644
--- a/public/stylesheets/_sass/settings.scss
+++ b/public/stylesheets/_sass/settings.scss
@@ -80,22 +80,26 @@
input[type="text"]{
font-size: 24px;
padding: 4px;
+ background-color: #ffffff;
+ color: #202020;
border: #CCC 1px solid;
@include rounded(3);
width: 300px;
}
+
+ select {
+ font-size: 24px;
+ background-color: #ffffff;
+ color: #202020;
+ border: #CCC 1px solid;
+ width: 310px;
+ height: 38px;
+ }
}
.action-button {
- input[type="button"]{
- width: 120px;
- font-size: 24px;
- padding: 4px;
- background-color: #DDD;
- border: #CCC 1px solid;
- @include rounded(3);
- margin-left: 5px;
- }
+ float: left;
+ margin: 6px 0 0 5px;
}
.saved {
diff --git a/public/stylesheets/misc.css b/public/stylesheets/misc.css
index 8f52cc9..3ffa48e 100644
--- a/public/stylesheets/misc.css
+++ b/public/stylesheets/misc.css
@@ -37,6 +37,8 @@
text-shadow: #c08080 0px 1px 1px;
border-color: #eaa0a0;
box-shadow: #da9090 1px 1px 0px; }
+ .button.big {
+ font-size: 22px; }
/* Scrollbars */
.data-container .scrollbar-pane {
@@ -86,20 +88,22 @@
height: 30px;
clear: both; }
-.auth_notice {
+.auth-notice {
display: none;
position: absolute;
- background-color: #07F;
- color: #FFF;
+ background-color: #60a0ff;
+ color: #ffffff;
top: 32px;
- left: 280px;
- padding: 8px;
- border: #05D 1px solid;
+ left: 290px;
+ line-height: 35px;
+ padding-right: 10px;
+ border: #4080dd 1px solid;
border-radius: 3px;
-moz-border-radius: 3px;
- -webkit-border-radius: 3px; }
- .auth_notice .arrow {
+ -webkit-border-radius: 3px;
+ cursor: pointer; }
+ .auth-notice .arrow {
float: left;
- margin: -8px 15px 0 8px;
+ margin: -5px 10px 0 10px;
font-size: 25px;
font-weight: bold; }
diff --git a/public/stylesheets/search.css b/public/stylesheets/search.css
index dd0ebce..4bc732c 100644
--- a/public/stylesheets/search.css
+++ b/public/stylesheets/search.css
@@ -9,15 +9,6 @@
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px; }
- .search-container #search_form #search_button {
- width: 100px;
- font-size: 24px;
- padding: 4px;
- background-color: #DDD;
- border: #CCC 1px solid;
- border-radius: 3px;
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px; }
.search-container .spinner {
display: none;
margin: 20px 0 0 175px; }
diff --git a/public/stylesheets/settings.css b/public/stylesheets/settings.css
index 7635bfe..23f280e 100644
--- a/public/stylesheets/settings.css
+++ b/public/stylesheets/settings.css
@@ -63,21 +63,23 @@
.settings-container .form-container .form .field .value input[type="text"] {
font-size: 24px;
padding: 4px;
+ background-color: #ffffff;
+ color: #202020;
border: #CCC 1px solid;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
width: 300px; }
- .settings-container .form-container .form .field .action-button input[type="button"] {
- width: 120px;
- font-size: 24px;
- padding: 4px;
- background-color: #DDD;
- border: #CCC 1px solid;
- border-radius: 3px;
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
- margin-left: 5px; }
+ .settings-container .form-container .form .field .value select {
+ font-size: 24px;
+ background-color: #ffffff;
+ color: #202020;
+ border: #CCC 1px solid;
+ width: 310px;
+ height: 38px; }
+ .settings-container .form-container .form .field .action-button {
+ float: left;
+ margin: 6px 0 0 5px; }
.settings-container .form-container .form .field .saved {
float: left; }
.settings-container .form-container .logout {
diff --git a/public/templates/search.html b/public/templates/search.html
index cf236c4..819f0cd 100644
--- a/public/templates/search.html
+++ b/public/templates/search.html
@@ -1,14 +1,14 @@

-
Something very bad happened while we tried out to load some info about this artist. How about some other one?
-
Artist info is loading for the first time now. Usually it takes less than a minute, please wait a bit.
+
+
\ No newline at end of file
diff --git a/public/templates/settings.html b/public/templates/settings.html
index 0510dea..3f4fca6 100644
--- a/public/templates/settings.html
+++ b/public/templates/settings.html
@@ -1,37 +1,46 @@