diff --git a/.gitignore b/.gitignore
index 88a64dc8..54c77670 100644
--- a/.gitignore
+++ b/.gitignore
@@ -110,6 +110,10 @@ local.properties
# Eclipse Core
.project
+# Intellij
+*.iml
+.idea
+
# External tool builders
.externalToolBuilders/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..64fdcf2a
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,15 @@
+language: java
+sudo: required
+jdk:
+ - oraclejdk8
+cache:
+ directories:
+ - $HOME/.m2
+install:
+ - sudo apt-get -qq update
+ - sudo apt-get -y install lintian fakeroot rpm python-rpm
+ - git clone https://github.com/rpm-software-management/rpmlint -o rpmlint-1.9
+ - sudo make -C rpmlint install
+script:
+ - mvn -Pfull,rpm package install
+ - mvn -Pfull -pl libresonic-assembly assembly:single
diff --git a/BUILD.md b/BUILD.md
index 9254e560..d4f639f9 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -8,6 +8,7 @@ Requirements
* Recent version of [Maven](http://maven.apache.org/).
* A JDK installation. 1.8.x series of OpenJDK or Oracle JDK 8+ should work.
* Optional: lintian and fakeroot, for .deb package
+ * Optional: rpm and rpmlint, for .rpm package
* Test as follows:
```
@@ -53,14 +54,39 @@ $
Packaged .deb
-------------
-You can furthermore go ahead to create a .deb suitable for installation on Debian or Ubuntu. These instructions should similarly work with rpm(for RedHat/CentOS or Fedora), but it is has not been tested.
+You can furthermore go ahead to create a .deb suitable for installation on
+Debian or Ubuntu.
```
$ mvn -P full -pl libresonic-booter -am install
-$ mvn -P full -pl libresonic-installer-debian/ -am install
+$ mvn -P full -pl libresonic-installer-debian -am install
$ sudo dpkg -i ./libresonic-installer-debian/target/libresonic-*.deb
-$
```
-Good luck!
+Packaged RPM
+------------
+
+Building a RPM package is very similar :
+
+```
+$ mvn -P full -pl libresonic-booter -am install
+$ mvn -P full,rpm -pl libresonic-installer-rpm -am install
+$ sudo rpm -ivh libresonic-installer-rpm/target/libresonic-*.rpm
+```
+Additional release archives
+---------------------------
+
+Additional release archives can be built using the following commands :
+
+```
+$ mvn -Pfull -pl libresonic-assembly assembly:single
+```
+
+These archives are built in `libresonic-assembly/targets` and include :
+
+* The source distribution
+* The standalone archive (for use without a WAR container)
+* The WAR archive (for WAR containers)
+
+Good luck!
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7e2f876c..1a7e0f4a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,20 @@
# Libresonic/libresonic
# -->
+v6.1.beta2
+--------
+
+ * Metaproject: Jenkins builds!
+ * More documentation
+ * Translation updates
+ * Improve shuffling behaviour
+ * Lots of small fixes, many more to come
+
+v6.1.beta1
+----------
+
+ * Meant as a release candidate; failed to make it past the Primary election.
+
v6.1-alpha1
-----------
diff --git a/INSTALL.md b/INSTALL.md
index c20a948b..40f97083 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -23,7 +23,7 @@ Daily WAR files are built by Jenkins and available [here](https://jenkins.zifnab
1. Download the latest war file:
- wget https://jenkins.zifnab.net/job/libresonic/lastSuccessfulBuild/artifact/.repository/org/libresonic/player/libresonic-main/6.1.beta1/libresonic-main-6.1.beta1.war -O /var/lib/tomcat8/webapps/libresonic.war
+ wget https://jenkins.zifnab.net/job/libresonic/lastSuccessfulBuild/artifact/.repository/org/libresonic/player/libresonic-main/6.1.beta2/libresonic-main-6.1.beta2.war -O /var/lib/tomcat8/webapps/libresonic.war
Note that this command copies the war file directly to the Tomcat webapps directory, and renames it to `libresonic.war`.
diff --git a/MIGRATE.md b/MIGRATE.md
new file mode 100644
index 00000000..3f1e2990
--- /dev/null
+++ b/MIGRATE.md
@@ -0,0 +1,36 @@
+Upgrade to Libresonic from Subsonic
+================
+
+This guide helps you to migrate your data from Subsonic to Libresonic. It has been tested with Subsonic 5 to Libresonic 6.
+
+Install Libresonic as described in INSTALL.md. The author of this guide used the standalone solution without Java Tomcat.
+
+After installation of Libresonic, the database needs to be migrated. In preperation for that, stop the Libresonic service
+
+ sudo service libresonic stop
+
+If you ran Subsonic before, your data will be (by default) stored in `/var/subsonic`. Assuming you did not use Libresonic before, we will delete all data from Libresonic
+
+ sudo rm -r /var/libresonic # WARNING: DELETES all Libresonic data (Subsonic data will be kept)
+
+We then copy Subsonic data to Libresonic location. Be aware that a couple of files need to be renamed:
+
+ sudo cp -a /var/subsonic /var/libresonic
+ sudo mv /var/libresonic/subsonic_sh.log libresonic_sh.log
+ sudo mv /var/libresonic/subsonic.log libresonic.log
+ sudo mv /var/libresonic/subsonic.properties libresonic.properties
+ sudo mv /var/libresonic/db/subsonic.backup /var/libresonic/db/libresonic.backup
+ sudo mv /var/libresonic/db/subsonic.data /var/libresonic/db/libresonic.data
+ sudo mv /var/libresonic/db/subsonic.lck /var/libresonic/db/libresonic.lck
+ sudo mv /var/libresonic/db/subsonic.log /var/libresonic/db/libresonic.log
+ sudo mv /var/libresonic/db/subsonic.properties /var/libresonic/db/libresonic.properties
+ sudo mv /var/libresonic/db/subsonic.script /var/libresonic/db/libresonic.script
+
+Then start Libresonic service again.
+
+ sudo service libresonic start
+
+Your old settings will be there. If you wish, you can delete subsonic data
+
+ sudo rm -r /var/subsonic # Optional, THIS WILL DELETE SUBSONIC DATA
+
diff --git a/documentation/FreeBSD-FreeNAS-Install.md b/documentation/FreeBSD-FreeNAS-Install.md
index d03bf5c4..d2960a73 100644
--- a/documentation/FreeBSD-FreeNAS-Install.md
+++ b/documentation/FreeBSD-FreeNAS-Install.md
@@ -66,15 +66,15 @@ Open a web browser and enter your servers IP address in the url bar followed by
You should be greeted by the Apache Tomcat page. Click on the Manager App button on the right of the page and enter the username and password used in step 3. Default was username: admin and password: admin
-Scroll down to Deploy and the subheading "WAR file to deploy" hit choose file and select the libresonic.war downloaded in the preamble. After selecting press the deploy button. Scroll up and press start. When the page refreshes a message "OK - Started application at context path /libresonic-v6.1.beta1" should be visible.
+Scroll down to Deploy and the subheading "WAR file to deploy" hit choose file and select the libresonic.war downloaded in the preamble. After selecting press the deploy button. Scroll up and press start. When the page refreshes a message "OK - Started application at context path /libresonic-v6.1.beta2" should be visible.
### 6. Navigate to Libresonic
In a browser. Take your server IP address and port and append the the context path from above
-ie if the War deployed was called libresonic-v6.1.beta1.war navigate to:
+ie if the War deployed was called libresonic-v6.1.beta2.war navigate to:
- 10.0.0.10:8080/libresonic-v6.1.beta1/
+ 10.0.0.10:8080/libresonic-v6.1.beta2/
### 7. Log into Libresonic
diff --git a/documentation/INSTALL.md b/documentation/INSTALL.md
index c20a948b..40f97083 100644
--- a/documentation/INSTALL.md
+++ b/documentation/INSTALL.md
@@ -23,7 +23,7 @@ Daily WAR files are built by Jenkins and available [here](https://jenkins.zifnab
1. Download the latest war file:
- wget https://jenkins.zifnab.net/job/libresonic/lastSuccessfulBuild/artifact/.repository/org/libresonic/player/libresonic-main/6.1.beta1/libresonic-main-6.1.beta1.war -O /var/lib/tomcat8/webapps/libresonic.war
+ wget https://jenkins.zifnab.net/job/libresonic/lastSuccessfulBuild/artifact/.repository/org/libresonic/player/libresonic-main/6.1.beta2/libresonic-main-6.1.beta2.war -O /var/lib/tomcat8/webapps/libresonic.war
Note that this command copies the war file directly to the Tomcat webapps directory, and renames it to `libresonic.war`.
diff --git a/libresonic-assembly/pom.xml b/libresonic-assembly/pom.xml
index 90e020bb..7f2b49bc 100644
--- a/libresonic-assembly/pom.xml
+++ b/libresonic-assembly/pom.xml
@@ -9,7 +9,7 @@
org.libresonic.player
libresonic
- 6.1.beta1
+ 6.1.beta2
diff --git a/libresonic-booter/pom.xml b/libresonic-booter/pom.xml
index b8bf1a68..fe778dfe 100644
--- a/libresonic-booter/pom.xml
+++ b/libresonic-booter/pom.xml
@@ -8,7 +8,7 @@
org.libresonic.player
libresonic
- 6.1.beta1
+ 6.1.beta2
diff --git a/libresonic-booter/src/main/resources/applicationContext-agent.xml b/libresonic-booter/src/main/resources/applicationContext-agent.xml
index 2b2e4856..f4221270 100644
--- a/libresonic-booter/src/main/resources/applicationContext-agent.xml
+++ b/libresonic-booter/src/main/resources/applicationContext-agent.xml
@@ -2,7 +2,7 @@
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
diff --git a/libresonic-booter/src/main/resources/applicationContext-deployer.xml b/libresonic-booter/src/main/resources/applicationContext-deployer.xml
index 07932bb8..86791e3d 100644
--- a/libresonic-booter/src/main/resources/applicationContext-deployer.xml
+++ b/libresonic-booter/src/main/resources/applicationContext-deployer.xml
@@ -2,7 +2,7 @@
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
diff --git a/libresonic-booter/src/main/resources/applicationContext-mac.xml b/libresonic-booter/src/main/resources/applicationContext-mac.xml
index 629d9632..fd908955 100644
--- a/libresonic-booter/src/main/resources/applicationContext-mac.xml
+++ b/libresonic-booter/src/main/resources/applicationContext-mac.xml
@@ -2,7 +2,7 @@
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
diff --git a/libresonic-installer-debian/pom.xml b/libresonic-installer-debian/pom.xml
index eb27e599..ac53d340 100644
--- a/libresonic-installer-debian/pom.xml
+++ b/libresonic-installer-debian/pom.xml
@@ -9,7 +9,7 @@
org.libresonic.player
libresonic
- 6.1.beta1
+ 6.1.beta2
diff --git a/libresonic-installer-debian/src/DEBIAN/control b/libresonic-installer-debian/src/DEBIAN/control
index 5f6fbf42..08e6f05d 100644
--- a/libresonic-installer-debian/src/DEBIAN/control
+++ b/libresonic-installer-debian/src/DEBIAN/control
@@ -4,7 +4,7 @@ Section: Multimedia
Priority: optional
Recommends: ffmpeg
Architecture: all
-Maintainer: Sindre Mehus
+Maintainer: Eugene E. Kashpureff Jr
Description: A web-based music streamer, jukebox and Podcast receiver
Libresonic is a web-based music streamer, jukebox and Podcast receiver,
providing access to your music collection wherever you are. Use it
diff --git a/libresonic-installer-mac/pom.xml b/libresonic-installer-mac/pom.xml
index 05204b09..432d5085 100644
--- a/libresonic-installer-mac/pom.xml
+++ b/libresonic-installer-mac/pom.xml
@@ -9,7 +9,7 @@
org.libresonic.player
libresonic
- 6.1.beta1
+ 6.1.beta2
diff --git a/libresonic-installer-rpm/pom.xml b/libresonic-installer-rpm/pom.xml
index c81254c9..74e86211 100644
--- a/libresonic-installer-rpm/pom.xml
+++ b/libresonic-installer-rpm/pom.xml
@@ -9,7 +9,7 @@
org.libresonic.player
libresonic
- 6.1.beta1
+ 6.1.beta2
diff --git a/libresonic-installer-windows/pom.xml b/libresonic-installer-windows/pom.xml
index 72726ecb..e9567211 100644
--- a/libresonic-installer-windows/pom.xml
+++ b/libresonic-installer-windows/pom.xml
@@ -9,7 +9,7 @@
org.libresonic.player
libresonic
- 6.1.beta1
+ 6.1.beta2
diff --git a/libresonic-main/libresonic-main.iml b/libresonic-main/libresonic-main.iml
deleted file mode 100644
index 4ac8de09..00000000
--- a/libresonic-main/libresonic-main.iml
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libresonic-main/pom.xml b/libresonic-main/pom.xml
index 70abbc5c..0d0a6234 100644
--- a/libresonic-main/pom.xml
+++ b/libresonic-main/pom.xml
@@ -9,7 +9,7 @@
org.libresonic.player
libresonic
- 6.1.beta1
+ 6.1.beta2
@@ -246,12 +246,6 @@
1.5.5
-
- com.sun.mail
- javax.mail
- 1.5.5
-
-
taglibs
standard
@@ -291,12 +285,6 @@
2.0.1
-
- org.seamless
- seamless-http
- 1.1.0
-
-
org.seamless
seamless-util
diff --git a/libresonic-main/src/main/java/org/libresonic/player/command/PersonalSettingsCommand.java b/libresonic-main/src/main/java/org/libresonic/player/command/PersonalSettingsCommand.java
index 81f5d3ec..bea8cd23 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/command/PersonalSettingsCommand.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/command/PersonalSettingsCommand.java
@@ -57,6 +57,7 @@ public class PersonalSettingsCommand {
private boolean songNotificationEnabled;
private boolean queueFollowingSongs;
private boolean lastFmEnabled;
+ private int listReloadDelay;
private String lastFmUsername;
private String lastFmPassword;
private boolean isReloadNeeded;
@@ -237,6 +238,14 @@ public class PersonalSettingsCommand {
this.lastFmEnabled = lastFmEnabled;
}
+ public int getListReloadDelay() {
+ return listReloadDelay;
+ }
+
+ public void setListReloadDelay(int listReloadDelay) {
+ this.listReloadDelay = listReloadDelay;
+ }
+
public String getLastFmUsername() {
return lastFmUsername;
}
diff --git a/libresonic-main/src/main/java/org/libresonic/player/command/PlayerSettingsCommand.java b/libresonic-main/src/main/java/org/libresonic/player/command/PlayerSettingsCommand.java
index 6ee0a32d..89260232 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/command/PlayerSettingsCommand.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/command/PlayerSettingsCommand.java
@@ -41,6 +41,7 @@ public class PlayerSettingsCommand {
private Date lastSeen;
private boolean isDynamicIp;
private boolean isAutoControlEnabled;
+ private boolean isM3uBomEnabled;
private String technologyName;
private String transcodeSchemeName;
private boolean transcodingSupported;
@@ -109,6 +110,14 @@ public class PlayerSettingsCommand {
isAutoControlEnabled = autoControlEnabled;
}
+ public boolean isM3uBomEnabled() {
+ return isM3uBomEnabled;
+ }
+
+ public void setM3uBomEnabled(boolean m3uBomEnabled) {
+ isM3uBomEnabled = m3uBomEnabled;
+ }
+
public String getTranscodeSchemeName() {
return transcodeSchemeName;
}
diff --git a/libresonic-main/src/main/java/org/libresonic/player/controller/HomeController.java b/libresonic-main/src/main/java/org/libresonic/player/controller/HomeController.java
index 8f943a54..c6b0ef68 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/controller/HomeController.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/controller/HomeController.java
@@ -76,8 +76,8 @@ public class HomeController extends ParameterizableViewController {
}
int listOffset = getIntParameter(request, "listOffset", 0);
AlbumListType listType = AlbumListType.fromId(getStringParameter(request, "listType"));
+ UserSettings userSettings = settingsService.getUserSettings(user.getUsername());
if (listType == null) {
- UserSettings userSettings = settingsService.getUserSettings(user.getUsername());
listType = userSettings.getDefaultAlbumList();
}
@@ -140,6 +140,7 @@ public class HomeController extends ParameterizableViewController {
map.put("coverArtSize", CoverArtScheme.MEDIUM.getSize());
map.put("listOffset", listOffset);
map.put("musicFolder", selectedMusicFolder);
+ map.put("listReloadDelay", userSettings.getListReloadDelay());
ModelAndView result = super.handleRequestInternal(request, response);
result.addObject("model", map);
diff --git a/libresonic-main/src/main/java/org/libresonic/player/controller/M3UController.java b/libresonic-main/src/main/java/org/libresonic/player/controller/M3UController.java
index d41df2ec..e04cd4ad 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/controller/M3UController.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/controller/M3UController.java
@@ -74,6 +74,9 @@ public class M3UController implements Controller {
}
private void createClientSidePlaylist(PrintWriter out, Player player, String url) throws Exception {
+ if (player.isM3uBomEnabled()) {
+ out.print("\ufeff");
+ }
out.println("#EXTM3U");
List result;
synchronized (player.getPlayQueue()) {
@@ -99,6 +102,9 @@ public class M3UController implements Controller {
url += "&suffix=." + suffix;
}
+ if (player.isM3uBomEnabled()) {
+ out.print("\ufeff");
+ }
out.println("#EXTM3U");
out.println("#EXTINF:-1,Libresonic");
out.println(url);
diff --git a/libresonic-main/src/main/java/org/libresonic/player/controller/MultiController.java b/libresonic-main/src/main/java/org/libresonic/player/controller/MultiController.java
index 00e318aa..e37b736e 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/controller/MultiController.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/controller/MultiController.java
@@ -237,6 +237,7 @@ public class MultiController extends MultiActionController {
Map map = new HashMap();
map.put("showRight", userSettings.isShowNowPlayingEnabled() || userSettings.isShowChatEnabled());
map.put("autoHidePlayQueue", userSettings.isAutoHidePlayQueue());
+ map.put("listReloadDelay", userSettings.getListReloadDelay());
map.put("showSideBar", userSettings.isShowSideBar());
map.put("brand", settingsService.getBrand());
return new ModelAndView("index", "model", map);
diff --git a/libresonic-main/src/main/java/org/libresonic/player/controller/PersonalSettingsController.java b/libresonic-main/src/main/java/org/libresonic/player/controller/PersonalSettingsController.java
index 64808a2c..e772c224 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/controller/PersonalSettingsController.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/controller/PersonalSettingsController.java
@@ -73,6 +73,7 @@ public class PersonalSettingsController extends SimpleFormController {
command.setBetaVersionNotificationEnabled(userSettings.isBetaVersionNotificationEnabled());
command.setSongNotificationEnabled(userSettings.isSongNotificationEnabled());
command.setAutoHidePlayQueue(userSettings.isAutoHidePlayQueue());
+ command.setListReloadDelay(userSettings.getListReloadDelay());
command.setLastFmEnabled(userSettings.isLastFmEnabled());
command.setLastFmUsername(userSettings.getLastFmUsername());
command.setLastFmPassword(userSettings.getLastFmPassword());
@@ -135,6 +136,7 @@ public class PersonalSettingsController extends SimpleFormController {
settings.setBetaVersionNotificationEnabled(command.isBetaVersionNotificationEnabled());
settings.setSongNotificationEnabled(command.isSongNotificationEnabled());
settings.setAutoHidePlayQueue(command.isAutoHidePlayQueue());
+ settings.setListReloadDelay(command.getListReloadDelay());
settings.setLastFmEnabled(command.isLastFmEnabled());
settings.setLastFmUsername(command.getLastFmUsername());
settings.setSystemAvatarId(getSystemAvatarId(command));
diff --git a/libresonic-main/src/main/java/org/libresonic/player/controller/PlayerSettingsController.java b/libresonic-main/src/main/java/org/libresonic/player/controller/PlayerSettingsController.java
index 712aa6f0..2a6d5d28 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/controller/PlayerSettingsController.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/controller/PlayerSettingsController.java
@@ -72,6 +72,7 @@ public class PlayerSettingsController extends SimpleFormController {
command.setLastSeen(player.getLastSeen());
command.setDynamicIp(player.isDynamicIp());
command.setAutoControlEnabled(player.isAutoControlEnabled());
+ command.setM3uBomEnabled(player.isM3uBomEnabled());
command.setTranscodeSchemeName(player.getTranscodeScheme().name());
command.setTechnologyName(player.getTechnology().name());
command.setAllTranscodings(transcodingService.getAllTranscodings());
@@ -99,6 +100,7 @@ public class PlayerSettingsController extends SimpleFormController {
Player player = playerService.getPlayerById(command.getPlayerId());
player.setAutoControlEnabled(command.isAutoControlEnabled());
+ player.setM3uBomEnabled(command.isM3uBomEnabled());
player.setDynamicIp(command.isDynamicIp());
player.setName(StringUtils.trimToNull(command.getName()));
player.setTranscodeScheme(TranscodeScheme.valueOf(command.getTranscodeSchemeName()));
diff --git a/libresonic-main/src/main/java/org/libresonic/player/dao/HsqlDaoHelper.java b/libresonic-main/src/main/java/org/libresonic/player/dao/HsqlDaoHelper.java
index 98137858..43880551 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/dao/HsqlDaoHelper.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/dao/HsqlDaoHelper.java
@@ -52,6 +52,8 @@ import org.libresonic.player.dao.schema.hsql.Schema50;
import org.libresonic.player.dao.schema.hsql.Schema51;
import org.libresonic.player.dao.schema.hsql.Schema52;
import org.libresonic.player.dao.schema.hsql.Schema53;
+import org.libresonic.player.dao.schema.hsql.Schema61;
+import org.libresonic.player.dao.schema.hsql.Schema62;
import org.libresonic.player.service.SettingsService;
/**
@@ -67,7 +69,8 @@ public class HsqlDaoHelper implements DaoHelper {
new Schema30(), new Schema31(), new Schema32(), new Schema33(), new Schema34(),
new Schema35(), new Schema36(), new Schema37(), new Schema38(), new Schema40(),
new Schema43(), new Schema45(), new Schema46(), new Schema47(), new Schema49(),
- new Schema50(), new Schema51(), new Schema52(), new Schema53()};
+ new Schema50(), new Schema51(), new Schema52(), new Schema53(), new Schema61(),
+ new Schema62()};
private DataSource dataSource;
private static boolean shutdownHookAdded;
diff --git a/libresonic-main/src/main/java/org/libresonic/player/dao/PlayerDao.java b/libresonic-main/src/main/java/org/libresonic/player/dao/PlayerDao.java
index d470452d..37d9f6a4 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/dao/PlayerDao.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/dao/PlayerDao.java
@@ -35,7 +35,7 @@ import java.util.*;
public class PlayerDao extends AbstractDao {
private static final Logger LOG = Logger.getLogger(PlayerDao.class);
- private static final String COLUMNS = "id, name, type, username, ip_address, auto_control_enabled, " +
+ private static final String COLUMNS = "id, name, type, username, ip_address, auto_control_enabled, m3u_bom_enabled, " +
"last_seen, cover_art_scheme, transcode_scheme, dynamic_ip, technology, client_id";
private PlayerRowMapper rowMapper = new PlayerRowMapper();
@@ -94,7 +94,7 @@ public class PlayerDao extends AbstractDao {
player.setId(String.valueOf(id));
String sql = "insert into player (" + COLUMNS + ") values (" + questionMarks(COLUMNS) + ")";
update(sql, player.getId(), player.getName(), player.getType(), player.getUsername(),
- player.getIpAddress(), player.isAutoControlEnabled(),
+ player.getIpAddress(), player.isAutoControlEnabled(), player.isM3uBomEnabled(),
player.getLastSeen(), CoverArtScheme.MEDIUM.name(),
player.getTranscodeScheme().name(), player.isDynamicIp(),
player.getTechnology().name(), player.getClientId());
@@ -143,6 +143,7 @@ public class PlayerDao extends AbstractDao {
"username = ?," +
"ip_address = ?," +
"auto_control_enabled = ?," +
+ "m3u_bom_enabled = ?," +
"last_seen = ?," +
"transcode_scheme = ?, " +
"dynamic_ip = ?, " +
@@ -150,7 +151,7 @@ public class PlayerDao extends AbstractDao {
"client_id = ? " +
"where id = ?";
update(sql, player.getName(), player.getType(), player.getUsername(),
- player.getIpAddress(), player.isAutoControlEnabled(),
+ player.getIpAddress(), player.isAutoControlEnabled(), player.isM3uBomEnabled(),
player.getLastSeen(), player.getTranscodeScheme().name(), player.isDynamicIp(),
player.getTechnology(), player.getClientId(), player.getId());
}
@@ -174,6 +175,7 @@ public class PlayerDao extends AbstractDao {
player.setUsername(rs.getString(col++));
player.setIpAddress(rs.getString(col++));
player.setAutoControlEnabled(rs.getBoolean(col++));
+ player.setM3uBomEnabled(rs.getBoolean(col++));
player.setLastSeen(rs.getTimestamp(col++));
col++; // Ignore cover art scheme.
player.setTranscodeScheme(TranscodeScheme.valueOf(rs.getString(col++)));
diff --git a/libresonic-main/src/main/java/org/libresonic/player/dao/UserDao.java b/libresonic-main/src/main/java/org/libresonic/player/dao/UserDao.java
index abd1ac2e..87c3d81a 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/dao/UserDao.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/dao/UserDao.java
@@ -44,7 +44,7 @@ public class UserDao extends AbstractDao {
"playlist_year, playlist_bit_rate, playlist_duration, playlist_format, playlist_file_size, " +
"last_fm_enabled, last_fm_username, last_fm_password, transcode_scheme, show_now_playing, selected_music_folder_id, " +
"party_mode_enabled, now_playing_allowed, avatar_scheme, system_avatar_id, changed, show_chat, show_artist_info, auto_hide_play_queue, " +
- "view_as_list, default_album_list, queue_following_songs, show_side_bar";
+ "view_as_list, default_album_list, queue_following_songs, show_side_bar, list_reload_delay";
private static final Integer ROLE_ID_ADMIN = 1;
private static final Integer ROLE_ID_DOWNLOAD = 2;
@@ -188,7 +188,7 @@ public class UserDao extends AbstractDao {
settings.getAvatarScheme().name(), settings.getSystemAvatarId(), settings.getChanged(),
settings.isShowChatEnabled(), settings.isShowArtistInfoEnabled(), settings.isAutoHidePlayQueue(),
settings.isViewAsList(), settings.getDefaultAlbumList().getId(), settings.isQueueFollowingSongs(),
- settings.isShowSideBar()});
+ settings.isShowSideBar(), settings.getListReloadDelay()});
}
private static String encrypt(String s) {
@@ -349,6 +349,7 @@ public class UserDao extends AbstractDao {
settings.setDefaultAlbumList(AlbumListType.fromId(rs.getString(col++)));
settings.setQueueFollowingSongs(rs.getBoolean(col++));
settings.setShowSideBar(rs.getBoolean(col++));
+ settings.setListReloadDelay((Integer) rs.getObject(col++));
return settings;
}
diff --git a/libresonic-main/src/main/java/org/libresonic/player/dao/schema/hsql/Schema61.java b/libresonic-main/src/main/java/org/libresonic/player/dao/schema/hsql/Schema61.java
new file mode 100644
index 00000000..d2634efa
--- /dev/null
+++ b/libresonic-main/src/main/java/org/libresonic/player/dao/schema/hsql/Schema61.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of Libresonic.
+ *
+ * Libresonic is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Libresonic is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Libresonic. If not, see .
+ */
+package org.libresonic.player.dao.schema.hsql;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import org.libresonic.player.Logger;
+import org.libresonic.player.dao.schema.Schema;
+
+/**
+ * Used for creating and evolving the database schema.
+ * This class implements the database schema for Libresonic version 6.1.
+ *
+ * @author François-Xavier Thomas
+ */
+public class Schema61 extends Schema {
+
+ private static final Logger LOG = Logger.getLogger(Schema61.class);
+
+ @Override
+ public void execute(JdbcTemplate template) {
+
+ if (template.queryForInt("select count(*) from version where version = 26") == 0) {
+ LOG.info("Updating database schema to version 26.");
+ template.execute("insert into version values (26)");
+ }
+
+ if (!columnExists(template, "list_reload_delay", "user_settings")) {
+ LOG.info("Database column 'user_settings.list_reload_delay' not found. Creating it.");
+ template.execute("alter table user_settings add list_reload_delay int default 60 not null");
+ LOG.info("Database column 'user_settings.list_reload_delay' was added successfully.");
+ }
+ }
+}
diff --git a/libresonic-main/src/main/java/org/libresonic/player/dao/schema/hsql/Schema62.java b/libresonic-main/src/main/java/org/libresonic/player/dao/schema/hsql/Schema62.java
new file mode 100644
index 00000000..0e945944
--- /dev/null
+++ b/libresonic-main/src/main/java/org/libresonic/player/dao/schema/hsql/Schema62.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of Libresonic.
+ *
+ * Libresonic is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Libresonic is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Libresonic. If not, see .
+ */
+package org.libresonic.player.dao.schema.hsql;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import org.libresonic.player.Logger;
+import org.libresonic.player.dao.schema.Schema;
+
+/**
+ * Used for creating and evolving the database schema.
+ * This class implements the database schema for Libresonic version 6.1.
+ *
+ * @author Shen-Ta Hsieh
+ */
+public class Schema62 extends Schema {
+
+ private static final Logger LOG = Logger.getLogger(Schema62.class);
+
+ @Override
+ public void execute(JdbcTemplate template) {
+
+ if (template.queryForInt("select count(*) from version where version = 27") == 0) {
+ LOG.info("Updating database schema to version 27.");
+ template.execute("insert into version values (27)");
+ }
+
+ if (!columnExists(template, "player", "m3u_bom_enabled")) {
+ LOG.info("Database column 'player.m3u_bom_enabled' not found. Creating it.");
+ template.execute("alter table player add m3u_bom_enabled boolean default false not null");
+ LOG.info("Database column 'player.m3u_bom_enabled' was added successfully.");
+ }
+ }
+}
diff --git a/libresonic-main/src/main/java/org/libresonic/player/domain/PlayQueue.java b/libresonic-main/src/main/java/org/libresonic/player/domain/PlayQueue.java
index 16401e34..2cc2ae42 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/domain/PlayQueue.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/domain/PlayQueue.java
@@ -241,7 +241,8 @@ public class PlayQueue {
MediaFile currentFile = getCurrentFile();
Collections.shuffle(files);
if (currentFile != null) {
- index = files.indexOf(currentFile);
+ Collections.swap(files, files.indexOf(currentFile), 0);
+ index = 0;
}
}
diff --git a/libresonic-main/src/main/java/org/libresonic/player/domain/Player.java b/libresonic-main/src/main/java/org/libresonic/player/domain/Player.java
index 8a14ecdd..9ef3fa38 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/domain/Player.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/domain/Player.java
@@ -40,6 +40,7 @@ public class Player {
private String ipAddress;
private boolean isDynamicIp = true;
private boolean isAutoControlEnabled = true;
+ private boolean isM3uBomEnabled = true;
private Date lastSeen;
private TranscodeScheme transcodeScheme = TranscodeScheme.OFF;
private PlayQueue playQueue;
@@ -188,6 +189,24 @@ public class Player {
this.isAutoControlEnabled = isAutoControlEnabled;
}
+ /**
+ * Returns whether apply BOM mark when generating a M3U file.
+ *
+ * @return Whether apply BOM mark when generating a M3U file.
+ */
+ public boolean isM3uBomEnabled() {
+ return isM3uBomEnabled;
+ }
+
+ /**
+ * Sets whether apply BOM mark when generating a M3U file.
+ *
+ * @param isM3uBomEnabled Whether apply BOM mark when generating a M3U file.
+ */
+ public void setM3uBomEnabled(boolean isM3uBomEnabled) {
+ this.isM3uBomEnabled = isM3uBomEnabled;
+ }
+
/**
* Returns the time when the player was last seen.
*
diff --git a/libresonic-main/src/main/java/org/libresonic/player/domain/UserSettings.java b/libresonic-main/src/main/java/org/libresonic/player/domain/UserSettings.java
index 6b587fd1..05a9139c 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/domain/UserSettings.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/domain/UserSettings.java
@@ -46,6 +46,7 @@ public class UserSettings {
private Visibility mainVisibility = new Visibility();
private Visibility playlistVisibility = new Visibility();
private boolean lastFmEnabled;
+ private int listReloadDelay;
private String lastFmUsername;
private String lastFmPassword;
private TranscodeScheme transcodeScheme = TranscodeScheme.OFF;
@@ -156,6 +157,14 @@ public class UserSettings {
this.lastFmEnabled = lastFmEnabled;
}
+ public int getListReloadDelay() {
+ return listReloadDelay;
+ }
+
+ public void setListReloadDelay(int listReloadDelay) {
+ this.listReloadDelay = listReloadDelay;
+ }
+
public String getLastFmUsername() {
return lastFmUsername;
}
diff --git a/libresonic-main/src/main/java/org/libresonic/player/service/SettingsService.java b/libresonic-main/src/main/java/org/libresonic/player/service/SettingsService.java
index 63b454a0..2c579baf 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/service/SettingsService.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/service/SettingsService.java
@@ -1270,6 +1270,7 @@ public class SettingsService {
settings.setQueueFollowingSongs(true);
settings.setDefaultAlbumList(AlbumListType.RANDOM);
settings.setLastFmEnabled(false);
+ settings.setListReloadDelay(60);
settings.setLastFmUsername(null);
settings.setLastFmPassword(null);
settings.setChanged(new Date());
diff --git a/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties b/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties
index 8f240eb2..a71e11bb 100644
--- a/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties
+++ b/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties
@@ -378,6 +378,7 @@ personalsettings.autohideplayqueue = Auto-hide play queue
personalsettings.finalversionnotification = Notify me about new versions
personalsettings.betaversionnotification = Notify me about new beta versions
personalsettings.songnotification = Notify me when new songs are played (not supported by all browsers)
+personalsettings.listreloaddelay = Album list reload delay (in seconds, 0 disables)
personalsettings.lastfmenabled = Register what I'm playing at Last.fm
personalsettings.lastfmusername = Last.fm username
personalsettings.lastfmpassword = Last.fm password
@@ -511,6 +512,7 @@ playersettings.name = Player name
playersettings.maxbitrate = Max bitrate
playersettings.notranscoder = Notice: Transcoders does not appear to be installed.
Click Help button for more information.
playersettings.autocontrol = Control player automatically
+playersettings.m3ubom = Apply BOM signature in the generated M3U file
playersettings.dynamicip = Player has dynamic IP address
playersettings.transcodings = Active transcodings
playersettings.ok = Save
@@ -817,6 +819,8 @@ helppopup.playername.text = Allows you to specify an easy-to-remember name fo
helppopup.autocontrol.title = Control player automatically
helppopup.autocontrol.text =
With this option selected, {0} will automatically start the player when you click "Play" \
in the playlist. Otherwise, you must start and connect the player yourself.
+helppopup.m3ubom.title = Apply BOM in M3U file
+helppopup.m3ubom.text = Apply a BOM mark in generated M3U playlists for Unicode compatibility.
helppopup.dynamicip.title = Dynamic IP address
helppopup.dynamicip.text = Turn off this option if the player uses a static IP address.
helppopup.smtpServer.title = SMTP Server
diff --git a/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_zh_TW.properties b/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_zh_TW.properties
index 272cf257..e3ff6b3a 100644
--- a/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_zh_TW.properties
+++ b/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_zh_TW.properties
@@ -1,44 +1,71 @@
#
-# Taiwan localization.
+# Traditional Chinese (Taiwan) localization.
# Author: Cheng Jen Li
# chengjen.li@gmail.com
+# Author: Shen-Ta Hsieh
+# ibmibmibm.tw@gmail.com
#
common.home = \u9996\u9801
-common.back = \u56DE\u5FA9
-common.help = \u5354\u52A9
+common.back = \u4E0A\u4E00\u9801
+common.help = \u8AAA\u660E
common.play = \u64AD\u653E
common.add = \u65B0\u589E
common.download = \u4E0B\u8F09
common.close = \u95DC\u9589
-common.refresh = \u5237\u65B0
-common.next = \u4E0B\u9801
-common.previous = \u4E0A\u9801
+common.refresh = \u91CD\u65B0\u6574\u7406
+common.next = \u4E0B\u4E00\u9801
+common.previous = \u4E0A\u4E00\u9801
common.more = \u66F4\u591A
common.ok = \u78BA\u5B9A
common.cancel = \u53D6\u6D88
common.save = \u5132\u5B58
common.create = \u5EFA\u7ACB
common.delete = \u522A\u9664
+common.edit = \u7DE8\u8F2F
+common.confirm = \u8ACB\u78BA\u8A8D
common.unknown = (\u672A\u77E5)
common.default = (\u9810\u8A2D\u503C)
+common.settingssaved = \u8A2D\u5B9A\u5DF2\u5132\u5B58\u3002
+common.trialexpired = \u8A66\u7528\u7248\u5C07\u65BC {0} \u5230\u671F\u3002\u53D6\u5F97Subsonic Premium\u4F86\u4F7F\u7528\u9019\u500B\u529F\u80FD\u3002
+common.trialnotexpired = \u9019\u500B\u529F\u80FD\u5728 {0} \u4E4B\u524D\u90FD\u53EF\u4F7F\u7528\u3002\u4E4B\u5F8C\u60A8\u5FC5\u9808\u53D6\u5F97Subsonic Premium\u624D\u80FD\u4F7F\u7528\u3002
# login.jsp
login.username = \u5E33\u865F
login.password = \u5BC6\u78BC
login.login = \u767B\u5165
login.remember = \u8A18\u5F97\u6211
-login.logout = \u60A8\u5DF2\u7D93\u767B\u51FA.
-login.error = \u5E33\u865F\u6216\u662F\u5BC6\u78BC\u932F\u8AA4.
-login.insecure = {0} \u672A\u53D7\u4FDD\u8B77. \u8ACB\u5148\u4EE5\u4F7F\u7528\u8005\u53CA\u5BC6\u78BC "admin"\u767B\u5165, \u6216\u9EDE\u64CA \u9019\u88E1. \u4E26\u4E14\u7ACB\u523B\u8B8A\u66F4\u60A8\u7684\u5BC6\u78BC.
+login.logout = \u60A8\u5DF2\u7D93\u767B\u51FA\u3002
+login.error = \u5E33\u865F\u6216\u662F\u5BC6\u78BC\u932F\u8AA4\u3002
+login.insecure = {0} \u672A\u53D7\u4FDD\u8B77\u3002\u8ACB\u5148\u4EE5\u4F7F\u7528\u8005\u53CA\u5BC6\u78BC "admin"\u767B\u5165\uFF0C\u6216\u9EDE\u9078 \u9019\u88E1\uFF0C\u4E26\u4E14\u7ACB\u523B\u8B8A\u66F4\u60A8\u7684\u5BC6\u78BC\u3002
+login.recover = \u5FD8\u8A18\u5BC6\u78BC\uFF1F
+
+# recover.jsp
+recover.title = \u5FD8\u8A18\u5BC6\u78BC\uFF1F
+recover.text = \u8981\u91CD\u8A2D\u5BC6\u78BC\uFF0C\u8ACB\u5728\u4E0B\u65B9\u8F38\u5165\u60A8\u7684\u5E33\u865F\u6216\u662FEmail\u4F4D\u5740\u3002
+recover.username = \u5E33\u865F\u6216Email\u4F4D\u5740
+recover.send = \u91CD\u8A2D\u5BC6\u78BC\u4E26\u5BC4\u7D66\u6211
+recover.success = \u60A8\u7684\u5BC6\u78BC\u5DF2\u91CD\u8A2D\u4E26\u5BC4\u5230\u4E86 {0} \u3002
+recover.error.usernotfound = \u62B1\u6B49\uFF0C\u672A\u627E\u5230\u4F7F\u7528\u8005\u3002
+recover.error.noemail = \u62B1\u6B49\uFF0C\u8A72\u4F7F\u7528\u8005\u672A\u8A3B\u518A\u4FE1\u7BB1\u3002
+recover.error.sendfailed = Email\u5BC4\u9001\u5931\u6557\uFF0C\u8ACB\u7A0D\u5F8C\u518D\u8A66\u3002
+recover.error.invalidcaptcha = \u62B1\u6B49\uFF0C\u8F38\u5165\u7684CAPTCHA\u6587\u5B57\u6709\u8AA4\uFF0C\u8ACB\u518D\u8A66\u4E00\u6B21\u3002
# accessDenied.jsp
accessDenied.title = \u62D2\u7D55\u5B58\u53D6
-accessDenied.text = \u62B1\u6B49\uFF0C\u60A8\u7121\u6B0A\u57F7\u884C\u6240\u8ACB\u6C42\u7684\u64CD\u4F5C.
+accessDenied.text = \u62B1\u6B49\uFF0C\u60A8\u7121\u6B0A\u57F7\u884C\u6240\u8ACB\u6C42\u7684\u64CD\u4F5C\u3002
+
+# notFound.jsp
+notFound.title = \u627E\u4E0D\u5230
+notFound.text = Sorry, we could not find what you were looking for.
Try reloading the web page. If that doesn't help, \
+ try scanning the media folders again.
+notFound.reload = \u91CD\u65B0\u6574\u7406\u9801\u9762
+notFound.scan = Media folders settings
# top.jsp
top.home = \u9996\u9801
top.now_playing = \u64AD\u653E
+top.starred = Starred
top.settings = \u8A2D\u5B9A
top.status = \u72C0\u614B
top.podcast = \u64AD\u5BA2
@@ -46,32 +73,40 @@ top.more = \u5176\u4ED6
top.help = \u95DC\u65BC
top.search = \u641C\u5C0B
top.upgrade = \u6709\u65B0\u7248\u672C\u63D0\u4F9B. \u4E0B\u8F09 {0} {1} \
- \u9019\u88E1.
-top.missing = \u627E\u4E0D\u5230\u97F3\u6A02\u593E\uFF0C\u8ACB\u91CD\u65B0\u8A2D\u5B9A.
+ \u9019\u88E1\u3002
+top.missing = \u627E\u4E0D\u5230\u97F3\u6A02\u8CC7\u6599\u593E\uFF0C\u8ACB\u91CD\u65B0\u8A2D\u5B9A\u3002
top.logout =\u767B\u51FA{0}
+top.getpremium = \u53D6\u5F97 Subsonic Premium
+top.gotpremium = Subsonic Premium
+top.trialdaysleft = \u5269\u4E0B {0} \u5929\u9AD4\u9A57\u6642\u9593
# left.jsp
-left.statistics = \u97F3\u6A02\u76D2\u6709 \
- {0} \u4F4D\u6B4C\u624B
\
+left.scanning = \u6383\u63CF\u97F3\u6A02\u8CC7\u6599\u593E\u4E2D\u2026
+left.statistics = {0} \u4F4D\u6B4C\u624B
\
{1} \u5F35\u5C08\u8F2F
\
{2} \u9996\u6B4C\u66F2
\
- {3} (\u7D04 {4} \u5C0F\u6642)
+ {3}
\
+ {4} \u5C0F\u6642
left.shortcut = \u6377\u5F91
+left.playlists = \u64AD\u653E\u6E05\u55AE
left.radio = \u7DDA\u4E0A\u96FB\u8996/\u6536\u97F3\u6A5F
left.allfolders = \u5168\u90E8
+left.showallplaylists = \u986F\u793A\u5168\u90E8
+left.createplaylist = \u5EFA\u7ACB\u65B0\u7684\u64AD\u653E\u6E05\u55AE
+left.importplaylist = \u532F\u5165\u64AD\u653E\u6E05\u55AE
-# playlist.jsp
+# playQueue.jsp
playlist.stop = \u505C\u6B62
playlist.start = \u64AD\u653E
-playlist.confirmclear = \u78BA\u5B9A\u522A\u9664\u9EDE\u64AD\u6E05\u55AE?
+playlist.confirmclear = \u78BA\u5B9A\u522A\u9664\u64AD\u653E\u6E05\u55AE?
playlist.clear = \u6E05\u9664
playlist.shuffle = \u96A8\u8208\u64AD\u653E
playlist.repeat_on = \u91CD\u64AD
playlist.repeat_off = \u4E0D\u91CD\u64AD
playlist.undo = \u53D6\u6D88
playlist.settings = \u8A2D\u5B9A
-playlist.more = \u5176\u4ED6...
-playlist.more.playlist = \u9EDE\u64AD\u6E05\u55AE
+playlist.more = \u5176\u4ED6\u2026
+playlist.more.playlist = \u64AD\u653E\u6E05\u55AE
playlist.more.sortbytrack = \u97F3\u8ECC\u6392\u5E8F
playlist.more.sortbyartist = \u6B4C\u624B\u6392\u5E8F
playlist.more.sortbyalbum = \u5C08\u8F2F\u6392\u5E8F
@@ -79,12 +114,41 @@ playlist.more.selection = \u9078\u6B4C
playlist.more.selectall = \u5168\u9078
playlist.more.selectnone = \u5168\u4E0D\u9078
playlist.getflash = \u53D6\u5F97Flash\u64A5\u653E\u5668
+playlist.saveplayqueue = \u5132\u5B58\u64AD\u653E\u4F47\u5217
+playlist.loadplayqueue = \u8F09\u5165\u64AD\u653E\u4F47\u5217
playlist.save = \u5132\u5B58
playlist.append = \u52A0\u5165\u6E05\u55AE
playlist.remove = \u79FB\u9664
playlist.up = \u4E0A
playlist.down = \u4E0B
-playlist.empty = \u7A7A\u7684\u9EDE\u64AD\u6E05\u55AE
+playlist.empty = \u7A7A\u7684\u64AD\u653E\u6E05\u55AE
+playlist.toast.appendtoplaylist = \u64AD\u653E\u6E05\u55AE\u5DF2\u66F4\u65B0\u3002
+playlist.toast.saveasplaylist = \u64AD\u653E\u6E05\u55AE\u5DF2\u5132\u5B58\u3002
+playlist.toast.saveplayqueue = \u64AD\u653E\u4F47\u5217\u5DF2\u5132\u5B58\u3002
+playlist.missing = \u907A\u5931
+
+# playlist.jsp
+playlist2.noplaylists = \u60A8\u9084\u672A\u5EFA\u7ACB\u4EFB\u4F55\u6E05\u55AE\u3002
+playlist2.created = \u7531 {0} \u5EFA\u7ACB\u7684 {1}
+playlist2.songs = \u6B4C\u66F2
+playlist2.shared = \u5176\u4ED6\u4EBA\u4E5F\u53EF\u770B\u898B
+playlist2.notshared = \u5176\u4ED6\u4EBA\u7121\u6CD5\u770B\u898B
+playlist2.name = \u64AD\u653E\u6E05\u55AE\u540D\u7A31
+playlist2.comment = \u64AD\u653E\u6E05\u55AE\u8A3B\u89E3
+playlist2.public = \u4F7F\u6B64\u64AD\u653E\u6E05\u55AE\u53EF\u88AB\u5176\u4ED6\u4EBA\u4F7F\u7528\u3002
+playlist2.confirmdelete = \u60A8\u78BA\u5B9A\u8981\u522A\u9664\u6B64\u64AD\u653E\u6E05\u55AE\u55CE\uFF1F
+playlist2.empty = \u64AD\u653E\u6E05\u55AE\u70BA\u7A7A
+playlist2.export = \u532F\u51FA
+
+# importPlaylist.jsp
+importPlaylist.title = Import playlist
+importPlaylist.text = Select playlist to import (m3u, pls, xspf)
+importPlaylist.success = Successfully imported playlist "{0}".
+importPlaylist.error = Failed to import playlist. {0}
+
+# videoPlayer.jsp
+videoPlayer.getflash = Please install Flash Player
+videoPlayer.getpremium = Get Subsonic Premium to play on Chromecast.
# status.jsp
status.title = \u72C0\u614B
@@ -98,46 +162,67 @@ status.current = \u76EE\u524D\u64AD\u653E
status.transmitted = \u50B3\u8F38
status.bitrate = Bitrate (Kbps)
+# starred.jsp
+starred.title = My starred items
+starred.empty = Click the star icons to mark your favorite artist, albums and songs.
+
# search.jsp
search.title = \u641C\u5C0B
+search.query = \u6B4C\u624B\u3001\u5C08\u8F2F\u6216\u6B4C\u66F2\u6A19\u984C\u3002
search.search = \u641C\u5C0B
-search.index = \u6B63\u5728\u5EFA\u7ACB\u7D22\u5F15\uFF0C\u8ACB\u7A0D\u5F8C\u518D\u8A66!
-search.hits.none = \u627E\u4E0D\u5230.
+search.index = \u6B63\u5728\u5EFA\u7ACB\u7D22\u5F15\uFF0C\u8ACB\u7A0D\u5F8C\u518D\u8A66\uFF01
+search.hits.none = \u627E\u4E0D\u5230\u3002
+search.hits.more = \u66F4\u591A
+search.hits.artists = \u6B4C\u624B
+search.hits.albums = \u5C08\u8F2F
+search.hits.songs = \u6B4C\u66F2
+search.hits.videos = \u5F71\u50CF
# gettingStarted.jsp
gettingStarted.title = \u521D\u6B21\u4F7F\u7528
-gettingStarted.text = \u6B61\u8FCE\u4F7F\u7528Libresonic!
\u8ACB\u4F9D\u7167\u4E0B\u9762\u7684\u6B65\u9A5F\u8A2D\u5B9A.
\
- \u9EDE\u64CA\u5DE5\u5177\u5217\u4E0A\u7684"\u9996\u9801"\uFF0C\u5C31\u80FD\u96A8\u6642\u56DE\u4F86\u9019\u88E1\uFF01.
\
+gettingStarted.text = \u6B61\u8FCE\u4F7F\u7528Libresonic\uFF01
\u8ACB\u4F9D\u7167\u4E0B\u9762\u7684\u6B65\u9A5F\u8A2D\u5B9A\u3002
\
+ \u9EDE\u64CA\u5DE5\u5177\u5217\u4E0A\u7684"\u9996\u9801"\uFF0C\u5C31\u80FD\u96A8\u6642\u56DE\u4F86\u9019\u88E1\u3002
\
\u9700\u8981\u66F4\u591A\u8A0A\u606F\u8ACB\u53C3\u8003\u5165\u9580\u6307\u5357
-gettingStarted.step1.title = \u8B8A\u66F4\u7BA1\u7406\u54E1\u7684\u5BC6\u78BC.
+gettingStarted.root = \u8B66\u544A\uFF01Libresonic\u7A0B\u5F0F\u6B63\u4EE5 root \u4F7F\u7528\u8005\u57F7\u884C\u3002\u8ACB\u8003\u616E \
+ \u5225\u7684\u65B9\u5F0F\u3002
+gettingStarted.step1.title = \u8B8A\u66F4\u7BA1\u7406\u54E1\u7684\u5BC6\u78BC\u3002
gettingStarted.step1.text = \u8ACB\u4FEE\u6539\u9810\u8A2D\u7684\u7BA1\u7406\u54E1\u5BC6\u78BC\uFF0C\u4EE5\u78BA\u4FDD\u4F3A\u670D\u5668\u7684\u5B89\u5168\u3002\
- \u4E5F\u53EF\u4EE5\u5EFA\u7ACB\u65B0\u7684\u4F7F\u7528\u8005\u4E26\u7D66\u4E88\u4E0D\u540C\u7684\u6B0A\u9650
-gettingStarted.step2.title = \u8A2D\u5B9A\u97F3\u6A02\u593E.
+ \u4E5F\u53EF\u4EE5\u5EFA\u7ACB\u65B0\u7684\u4F7F\u7528\u8005\u4E26\u7D66\u4E88\u4E0D\u540C\u7684\u6B0A\u9650\u3002
+gettingStarted.step2.title = \u8A2D\u5B9A\u97F3\u6A02\u8CC7\u6599\u593E\u3002
gettingStarted.step2.text = \u8A2D\u5B9A\u60A8\u97F3\u6A02\u6240\u653E\u7F6E\u7684\u8CC7\u6599\u593E\u3002
-gettingStarted.step3.title = \u914D\u7F6E\u7DB2\u8DEF\u8A2D\u5B9A.
+gettingStarted.step3.title = \u914D\u7F6E\u7DB2\u8DEF\u8A2D\u5B9A\u3002
gettingStarted.step3.text = \u5982\u679C\u60A8\u8981\u900F\u904E\u7DB2\u969B\u7DB2\u8DEF\u6216\u662F\u8207\u60A8\u7684\u670B\u53CB\u3001\u5BB6\u4EBA\u5206\u4EAB\u3002\
- \u4E26\u53D6\u5F97\u60A8\u7684\u5C08\u5C6C\u7DB2\u5740\u50CF\u662Fyourname.libresonic.org.
+ \u4E26\u53D6\u5F97\u60A8\u7684\u5C08\u5C6C\u7DB2\u5740\u50CF\u662Fyourname.libresonic.org\u3002
gettingStarted.hide = \u4E0B\u6B21\u4E0D\u986F\u793A\u672C\u9801\uFF01
-gettingStarted.hidealert = \u5982\u679C\u4E0B\u6B21\u9084\u9700\u8981\u986F\u793A\u63D0\u793A,\u8ACB\u5F9E \u8A2D\u5B9A->\u4E00\u822C \u4E2D\u52FE\u9078.
+gettingStarted.hidealert = \u5982\u679C\u4E0B\u6B21\u9084\u9700\u8981\u986F\u793A\u63D0\u793A\uFF0C\u8ACB\u5F9E \u8A2D\u5B9A\u2192\u4E00\u822C \u4E2D\u52FE\u9078\u3002
# home.jsp
home.random.title = \u96A8\u8208\u64AD\u653E
+home.alphabetical.title = \u5168\u90E8
home.newest.title = \u6700\u65B0\u97F3\u6A02
+home.starred.title = \u661F\u865F\u6A19\u8A18
home.highest.title = \u559C\u597D\u7A0B\u5EA6
home.frequent.title = \u9EDE\u64AD\u7387
home.recent.title = \u6700\u8FD1\u64AD\u653E
+home.decade.title = \u7531\u5E74\u4EFD
+home.genre.title = \u7531\u66F2\u98A8
home.users.title = \u4F7F\u7528\u8005
home.random.text = \u96A8\u8208\u9078\u64AD\u5C08\u8F2F
+home.alphabetical.text = \u6240\u6709\u5C08\u8F2F
home.newest.text = \u6700\u65B0\u5C08\u8F2F
+home.starred.text = \u60A8\u6A19\u8A18\u661F\u865F\u7684\u5C08\u8F2F
home.highest.text = \u8A55\u50F9\u9AD8\u7684\u5C08\u8F2F
home.frequent.text = \u6700\u591A\u9EDE\u64AD\u5C08\u8F2F
home.recent.text =\u6700\u8FD1\u64AD\u653E\u5C08\u8F2F
+home.decade.text = \u5E74\u4EFD
+home.genre.text = \u66F2\u98A8
home.users.text = \u4F7F\u7528\u8005\u7D71\u8A08
-home.scan = \u97F3\u6A02\u593E\u5DF2\u7D93\u6383\u63CF. \u6240\u6709\u529F\u80FD\u5C1A\u672A\u958B\u653E.
+home.scan = \u6B63\u5728\u6383\u63CF\u97F3\u6A02\u8CC7\u6599\u593E\u3002\u90E8\u4EFD\u529F\u80FD\u5C07\u7121\u6CD5\u4F7F\u7528\u3002
home.albums = \u5C08\u8F2F {0} - {1}
home.playcount = \u64AD\u653E\u4E86 {0} \u9996\u6B4C
home.lastplayed = \u64AD\u653E {0}
home.created = \u5EFA\u7ACB {0}
+home.shuffle = \u96A8\u6A5F\u64AD\u653E
home.chart.total = \u7E3D\u8A08 (MB)
home.chart.stream = \u4E32\u6D41 (MB)
home.chart.download = \u5DF2\u4E0B\u8F09(MB)
@@ -148,70 +233,79 @@ more.title = \u5176\u4ED6
more.random.title = \u96A8\u8208\u64AD\u653E
more.random.text = \u5EFA\u7ACB\u96A8\u8208\u6E05\u55AE
more.random.songs = {0} \u9996
-more.random.auto = \u7576\u9EDE\u64AD\u6E05\u55AE\u64AD\u653E\u5B8C\u7562\u6642\u7E7C\u7E8C\u64AD\u653E\u66F4\u591A\u7684\u96A8\u8208\u6B4C\u66F2 .
+more.random.auto = \u7576\u64AD\u653E\u6E05\u55AE\u64AD\u653E\u5B8C\u7562\u6642\u7E7C\u7E8C\u96A8\u6A5F\u64AD\u653E\u6B4C\u66F2\u3002
more.random.ok = \u78BA\u5B9A
more.random.genre = \u66F2\u98A8
more.random.anygenre = \u4EFB\u610F
more.random.year = \u5E74\u4EFD
more.random.anyyear = \u4EFB\u610F
-more.random.folder = \u97F3\u6A02\u593E
+more.random.folder = \u97F3\u6A02\u8CC7\u6599\u593E
more.random.anyfolder = \u4EFB\u610F
more.apps.title = Libresonic Apps
more.apps.text = \u652F\u63F4 iPhone, \
- Android \u548C AIR\u7684Libresonic apps.
+ Android \u548C AIR\u7684Libresonic apps\u3002
+more.jamstash.title = JamStash
+more.jamstash.text = Jamstash \u662F Libresonic \u7684 HTML5 \u64AD\u653E\u5668\u3002\u9EDE\u9078\u9019\u88E1 \u4F86\u555F\u52D5\u3002 \
+ \u4E5F\u53EF\u4EE5\u5728 Chrome App \u5167\u53D6\u5F97\u3002
+more.status.title = \u7DB2\u8DEF\u72C0\u614B
+more.status.text = \u76E3\u63A7\u6240\u6709\u7DB2\u8DEF\u4E32\u6D41\u7684\u5373\u6642\u72C0\u614B\u3002
more.mobile.title = \u79FB\u52D5\u8A2D\u5099
-more.mobile.text = \u53EF\u4EE5\u7531WAP\u96FB\u8A71\u6216PDA\u4F7F\u7528 {0} .
\
+more.mobile.text =
\u53EF\u4EE5\u7531 WAP \u96FB\u8A71\u6216 PDA \u4F7F\u7528 {0} \u3002
\
\u7D93\u7531\u624B\u6A5F\u8F38\u5165\u9019\u6A23\u7684\u7DB2\u5740 http://yourhostname/wap
\
- \u7576\u7136\u60A8\u624B\u6A5F\u5FC5\u9808\u8981\u6709\u4E0A\u7DB2\u529F\u80FD!.
+ \u9019\u9700\u8981\u60A8\u7684\u4F3A\u670D\u5668\u53EF\u4EE5\u900F\u904E\u7DB2\u969B\u7DB2\u8DEF\u5B58\u53D6\u3002
more.podcast.title = \u64AD\u5BA2
-more.podcast.text = \u5132\u5B58\u9EDE\u64AD\u6E05\u55AE\u7576\u6210\u64AD\u5BA2.
\
- \u7D93\u7531\u9019\u500B\u7DB2\u5740\u53EF\u4EE5\u6536\u807D: http://yourhostname/podcast, \
- \u6216\u662F \u9EDE\u6211.
+more.podcast.text = \u5132\u5B58\u64AD\u653E\u6E05\u55AE\u7576\u6210\u64AD\u5BA2\u3002
\
+ \u7D93\u7531\u9019\u500B\u7DB2\u5740\u53EF\u4EE5\u6536\u807D\uFF1A http://yourhostname/podcast\uFF0C\
+ \u6216\u662F \u9EDE\u6211\u3002
more.upload.title = \u4E0A\u50B3\u6A94\u6848
more.upload.source = \u9078\u64C7\u6A94\u6848
more.upload.target = \u4E0A\u50B3\u5230
more.upload.browse = \u9078\u64C7
more.upload.ok = \u4E0A\u50B3
-more.upload.unzip = \u81EA\u52D5\u89E3\u58D3\u7E2Ezip\u6A94.
-more.upload.progress = % \u5B8C\u6210. \u8ACB\u7A0D\u5019...
+more.upload.unzip = \u81EA\u52D5\u89E3\u58D3\u7E2Ezip\u6A94\u3002
+more.upload.progress = % \u5B8C\u6210\u3002\u8ACB\u7A0D\u5019\u2026
# upload.jsp
-upload.title = \u6A94\u6848\u4E0A\u50B3\u4E2D......
+upload.title = \u6A94\u6848\u4E0A\u50B3\u4E2D
upload.success = \u4E0A\u50B3\u6210\u529F {0}
-upload.empty = \u6C92\u6709\u4E0A\u50B3\u7684\u6A94\u6848\u5594.
-upload.failed = \u6A94\u6848\u4E0A\u50B3\u5931\u6557\u56E0\u70BA:
"{0}"
+upload.empty = \u6C92\u6709\u53EF\u4E0A\u50B3\u7684\u6A94\u6848\u3002
+upload.failed = \u6A94\u6848\u4E0A\u50B3\u6642\u767C\u751F\u932F\u8AA4\uFF1A
"{0}"
upload.unzipped = \u89E3\u58D3\u7E2E {0}
# help.jsp
help.title = \u95DC\u65BC {0}
-help.upgrade = \u6CE8\u610F! \u5DF2\u7D93\u6709\u65B0\u7684\u7248\u672C\u4E86\uFF0C\u4E0B\u8F09\u65B0\u7248 {0} {1} \
- \u5728\u9019.
+help.upgrade = \u6CE8\u610F\uFF01 \u6709\u65B0\u7248\u672C\u53EF\u7528\u3002\u4E0B\u8F09 {0} {1} \
+ \u8ACB\u9EDE\u9078\u9019\u88E1\u3002
+help.premium.title = \u6388\u6B0A
+help.premium.expires = (\u904E\u671F {0})
+help.premium.upgrade = \u5347\u7D1A\u5230 Subsonic Premium \u4F86\u4F7F\u7528 \u66F4\u591A\u529F\u80FD\uFF01
+help.premium.expired = (\u6388\u6B0A\u904E\u671F\u65BC {0})
help.version.title = \u7248\u672C
help.builddate.title = \u65E5\u671F
help.server.title = \u4F3A\u670D\u5668
help.license.title = \u6388\u6B0A
-help.license.text = {0} \u662F\u4EE5 GPL \u578B\u5F0F\u767C\u4F48\u6388\u6B0A\u7684\u81EA\u7531\u8EDF\u9AD4.
\
- {0} \u4F7F\u7528 \u7B2C\u4E09\u65B9\u6388\u6B0A.
+help.license.text = {0} \u662F\u4EE5 GPL \u578B\u5F0F\u767C\u4F48\u6388\u6B0A\u7684\u81EA\u7531\u8EDF\u9AD4\u3002
{0} \u4F7F\u7528 \u7B2C\u4E09\u65B9\u6388\u6B0A\u3002
help.homepage.title = \u9996\u9801
help.forum.title = \u8AD6\u58C7
help.shop.title = \u5546\u54C1
help.contact.title = \u806F\u7E6B
-help.contact.text = {0} \u7531 Sindre Mehus \u958B\u767C\u53CA\u7DAD\u8B77 \
- (sindre@activeobjects.no). \
- \u5982\u679C\u60A8\u6709\u4EFB\u4F55\u7591\u554F\uFF0C\u610F\u898B\u6216\u5EFA\u8B70\u6539\u5584\uFF0C\u8ACB\u5230 \
- Libresonic\u8AD6\u58C7.
+help.contact.text = {0} \u7531 Sindre Mehus \u958B\u767C\u53CA\u7DAD\u8B77(sindre@activeobjects.no)\u3002\u5982\u679C\u60A8\u6709\u4EFB\u4F55\u7591\u554F\uFF0C\u610F\u898B\u6216\u5EFA\u8B70\u6539\u5584\uFF0C\u8ACB\u5230Libresonic\u8AD6\u58C7\u3002
help.log = \u8A18\u9304
-help.logfile = \u5B8C\u6574\u7684\u7D00\u9304\u5B58\u653E\u5728 {0}.
+help.logfile = \u5B8C\u6574\u7684\u7D00\u9304\u5B58\u653E\u5728 {0}\u3002
# settingsHeader.jsp
settingsheader.title = \u8A2D\u5B9A
settingsheader.general = \u4E00\u822C
settingsheader.advanced = \u9032\u968E
settingsheader.personal = \u500B\u4EBA\u5316
-settingsheader.musicFolder = \u97F3\u6A02\u593E
+settingsheader.musicFolder = \u97F3\u6A02\u8CC7\u6599\u593E
settingsheader.internetRadio = \u7DDA\u4E0A\u96FB\u8996/\u6536\u97F3\u6A5F
settingsheader.podcast = \u64AD\u5BA2
settingsheader.player = \u64AD\u653E\u5668
+settingsheader.dlna = DLNA/UPnP
+settingsheader.sonos = Sonos
+settingsheader.premium = Subsonic Premium
+settingsheader.share = \u5206\u4EAB\u5A92\u9AD4
settingsheader.network = \u7DB2\u8DEF
settingsheader.transcoding = \u8F49\u6A94
settingsheader.user = \u4F7F\u7528\u8005
@@ -220,57 +314,71 @@ settingsheader.coverArt = \u5C08\u8F2F\u5C01\u9762
settingsheader.password = \u5BC6\u78BC
# generalSettings.jsp
-generalsettings.playlistfolder = \u9EDE\u64AD\u6E05\u55AE\u8CC7\u6599\u593E
+generalsettings.playlistfolder = \u64AD\u653E\u6E05\u55AE\u8CC7\u6599\u593E
generalsettings.musicmask = \u97F3\u6A02\u7684\u9644\u5C6C\u6A94\u540D:
generalsettings.videomask = \u8996\u8A0A\u7684\u9644\u5C6C\u6A94\u540D:
generalsettings.coverartmask = \u5C08\u8F2F\u5C01\u9762\u9644\u5C6C\u6A94\u540D
generalsettings.index = \u7D22\u5F15
generalsettings.ignoredarticles = \u5FFD\u7565\u7684\u6B4C\u624B\u540D\u7A31
generalsettings.shortcuts = \u6377\u5F91
+generalsettings.sortalbumsbyyear = \u7531\u5E74\u4EFD\u6392\u5E8F\u5C08\u8F2F
generalsettings.showgettingstarted = \u5728\u9996\u9801\u986F\u793A "\u521D\u6B21\u4F7F\u7528"
generalsettings.welcometitle = \u6B61\u8FCE\u6A19\u984C
generalsettings.welcomesubtitle = \u6B61\u8FCE\u6B21\u6A19\u984C
generalsettings.welcomemessage = \u6B61\u8FCE\u8A0A\u606F
generalsettings.loginmessage = \u767B\u5165\u8A0A\u606F
-generalsettings.language = Default language
+generalsettings.language = \u9810\u8A2D\u8A9E\u8A00
generalsettings.theme = \u9810\u8A2D\u4F48\u666F\u4E3B\u984C
# advancedSettings.jsp
advancedsettings.downsamplecommand = \u964D\u983B\u6307\u4EE4
-advancedsettings.coverartlimit = \u5C01\u9762\u9650\u5236
(0 = \u4E0D\u9650)
+advancedsettings.hlscommand = HTTP \u7DDA\u4E0A\u4E32\u6D41\u6307\u4EE4
advancedsettings.downloadlimit = \u4E0B\u8F09\u9650\u5236 (Kbps)
(0 = \u4E0D\u9650)
advancedsettings.uploadlimit = \u4E0A\u50B3\u9650\u5236 (Kbps)
(0 = \u4E0D\u9650)
-advancedsettings.streamport = \u975ESSL \u4E32\u6D41Port
(0 = \u53D6\u6D88)
-advancedsettings.ldapenabled = \u555F\u52D5LDAP\u9A57\u8B49
-advancedsettings.ldapurl = LDAP\u7DB2\u5740
-advancedsettings.ldapsearchfilter = LDAP\u641C\u5C0B\u904E\u6FFE
-advancedsettings.ldapmanagerdn = LDAP \u7BA1\u7406\u8005DN
(\u53EF\u9078\u64C7)
+advancedsettings.streamport = \u975E SSL \u4E32\u6D41 Port
(0 = \u53D6\u6D88)
+advancedsettings.ldapenabled = \u555F\u52D5 LDAP \u9A57\u8B49
+advancedsettings.ldapurl = LDAP \u7DB2\u5740
+advancedsettings.ldapsearchfilter = LDAP \u641C\u5C0B\u904E\u6FFE
+advancedsettings.ldapmanagerdn = LDAP \u7BA1\u7406\u8005 DN
(\u53EF\u9078\u64C7)
advancedsettings.ldapmanagerpassword = \u5BC6\u78BC
advancedsettings.ldapautoshadowing = \u81EA\u52D5\u5728{0}\u5EFA\u7ACB\u4F7F\u7528\u8005
+advancedsettings.smtpPort = SMTP \u9023\u63A5\u57E0
+advancedsettings.smtpServer = SMTP \u4F3A\u670D\u5668
+advancedsettings.smtpEncryption = SMTP \u52A0\u5BC6
+advancedsettings.smtpUser = SMTP \u5E33\u865F
+advancedsettings.smtpPassword = \u5BC6\u78BC
+advancedsettings.smtpEncryption.none = \u7121
+advancedsettings.smtpEncryption.starttls = STARTTLS
+advancedsettings.smtpEncryption.ssl = SSL/TLS
+advancedsettings.smtpFrom = \u5BC4\u4EF6\u8005
# personalSettings.jsp
personalsettings.title = {0}\u7684\u500B\u4EBA\u5316\u8A2D\u5B9A
-personalsettings.language = Language
+personalsettings.language = \u8A9E\u8A00
personalsettings.theme = \u4F48\u666F\u4E3B\u984C
+personalsettings.albumlist = \u9810\u8A2D\u5C08\u8F2F\u6392\u5E8F\u65B9\u5F0F
personalsettings.display = \u986F\u793A
personalsettings.browse = \u700F\u89BD
-personalsettings.playlist = \u9EDE\u64AD\u6E05\u55AE
+personalsettings.playlist = \u64AD\u653E\u6E05\u55AE
personalsettings.tracknumber = \u97F3\u8ECC #
personalsettings.artist = \u6B4C\u624B
personalsettings.album = \u5C08\u8F2F
-personalsettings.genre = \u66F2\u98A8\u578B\u614B
+personalsettings.genre = \u66F2\u98A8
personalsettings.year = \u767C\u884C
personalsettings.bitrate = Bit rate
personalsettings.duration = \u6642\u6548
personalsettings.format = \u683C\u5F0F
personalsettings.filesize = \u6587\u4EF6\u5927\u5C0F
-personalsettings.captioncutoff = Caption cutoff
personalsettings.partymode = \u5BB4\u6703\u6A21\u5F0F
+personalsettings.queuefollowingsongs = Queue following songs on play
personalsettings.shownowplaying = \u5176\u4ED6\u4EBA\u5728\u807D\u4EC0\u9EBC
personalsettings.nowplayingallowed = \u8B93\u5225\u4EBA\u770B\u6211\u5728\u807D\u4EC0\u9EBC
personalsettings.showchat = \u986F\u793A\u4EA4\u8AC7\u8A0A\u606F
+personalsettings.showartistinfo = \u986F\u793A\u6B4C\u624B\u8CC7\u8A0A
+personalsettings.autohideplayqueue = \u81EA\u52D5\u96B1\u85CF\u64AD\u653E\u4F47\u5217
personalsettings.finalversionnotification = \u63D0\u793A\u65B0\u7248\u672C
personalsettings.betaversionnotification = \u63D0\u793A\u65B0\u7684\u6E2C\u8A66\u7248
+personalsettings.songnotification = \u958B\u59CB\u64AD\u653E\u65B0\u6B4C\u6642\u63D0\u9192\u6211 (\u4E0D\u662F\u6240\u6709\u700F\u89BD\u5668\u90FD\u652F\u63F4)
personalsettings.lastfmenabled = \u767B\u9304\u6211\u5728 Last.fm\u7684\u5E33\u865F
personalsettings.lastfmusername = Last.fm \u5E33\u865F
personalsettings.lastfmpassword = Last.fm \u5BC6\u78BC
@@ -286,28 +394,51 @@ personalsettings.avatar.courtesy = Icons courtesy of \u8A18\u9304.
+avataruploadresult.success = \u6210\u529F\u4E0A\u50B3\u500B\u4EBA\u5716\u793A "{0}"\u3002
+avataruploadresult.failure = \u7121\u6CD5\u4E0A\u50B3\u500B\u4EBA\u5716\u793A. \u8ACB\u53C3\u95B1 \u8A18\u9304\u3002
# passwordSettings.jsp
passwordsettings.title = \u8B8A\u66F4\u5BC6\u78BC {0}
# musicFolderSettings.jsp
-musicfoldersettings.path = \u97F3\u6A02\u593E
+musicfoldersettings.path = \u97F3\u6A02\u8CC7\u6599\u593E
musicfoldersettings.name = \u540D\u7A31
musicfoldersettings.enabled = \u4F7F\u7528
-musicfoldersettings.add = \u65B0\u589E\u97F3\u6A02\u593E
-musicfoldersettings.nopath = \u5E6B\u97F3\u6A02\u593E\u547D\u540D\u5427.
+musicfoldersettings.add = \u65B0\u589E\u97F3\u6A02\u8CC7\u6599\u593E
+musicfoldersettings.nopath = \u8ACB\u6307\u5B9A\u8CC7\u6599\u593E\u3002
+musicfoldersettings.notfound = \u627E\u4E0D\u5230\u8CC7\u6599\u593E
+musicfoldersettings.scan = \u6383\u63CF\u97F3\u6A02\u8CC7\u6599\u593E
+musicfoldersettings.interval.never = \u5F9E\u4E0D
+musicfoldersettings.interval.one = \u6BCF\u5929
+musicfoldersettings.interval.many = \u6BCF\u9694 {0} \u5929
+musicfoldersettings.hour = \u5728 {0}:00
+musicfoldersettings.nowscanning = \u6B63\u5728\u6383\u63CF\u97F3\u6A02\u8CC7\u6599\u593E\u3002 \
+ \u9019\u500B\u52D5\u4F5C\u5C07\u9700\u8981\u5E7E\u5206\u9418\uFF0C\u53D6\u6C7A\u65BC\u60A8\u7684\u5A92\u9AD4\u8CC7\u6599\u5EAB\u7684\u5927\u5C0F\u3002
+musicfoldersettings.scannow = \u7ACB\u5373\u6383\u63CF\u97F3\u6A02\u8CC7\u6599\u593E
+musicfoldersettings.access = \u7BA1\u7406\u4F7F\u7528\u8005\u5B58\u53D6\u6B0A\u9650
+musicfoldersettings.access.description = \u8A2D\u5B9A\u54EA\u4E9B\u8CC7\u6599\u593E\u53EF\u4EE5\u88AB\u54EA\u4E9B\u4F7F\u7528\u8005\u5B58\u53D6\u3002
+musicfoldersettings.fastcache = \u5FEB\u901F\u8B80\u53D6\u6A21\u5F0F
+musicfoldersettings.fastcache.description = \u5982\u679C\u4F60\u7684\u5A92\u9AD4\u6A94\u6848\u5728\u7DB2\u8DEF\u4E0A\u7684\u78C1\u789F\uFF0C\u4F7F\u7528\u9019\u500B\u9078\u9805\u4F86\u6E1B\u5C11\u78C1\u789F\u5B58\u53D6\u3002 \
+ \u6CE8\u610F\uFF1A\u65B0\u589E\u6216\u66F4\u6539\u5BE6\u969B\u6A94\u6848\u5C07\u6703\u53EA\u6709\u5728\u6383\u63CF\u97F3\u6A02\u8CC7\u6599\u593E\u5F8C\u624D\u6703\u751F\u6548\u3002
+musicfoldersettings.expunge = \u6E05\u7406\u8CC7\u6599\u5EAB
+musicfoldersettings.expunge.description = Libresonic \u5132\u5B58\u4E86\u6240\u6709\u5A92\u9AD4\u6A94\u6848\u7684\u8CC7\u8A0A\u3002 \
+ \u6E05\u7406\u8CC7\u6599\u5EAB\u5F8C\uFF0C\u4E0D\u5728\u60A8\u7684\u5A92\u9AD4\u8CC7\u6599\u5EAB\u5167\u7684\u6A94\u6848\uFF0C\u5176\u8CC7\u8A0A\u5C07\u6C38\u4E45\u522A\u9664\u3002
+musicfoldersettings.organizebyfolderstructure = \u4EE5\u8CC7\u6599\u593E\u7D50\u69CB\u6574\u7406
+musicfoldersettings.organizebyfolderstructure.description = \u958B\u555F\u9019\u500B\u9078\u9805\u4F7F\u60A8\u700F\u89BD\u5A92\u9AD4\u8CC7\u6599\u5EAB\u6642\u4F7F\u7528\u539F\u4F86\u7684\u8CC7\u6599\u593E\u7D50\u69CB\uFF0C\u800C\u4E0D\u662F\u4F9D\u7167 ID3 \u6A19\u7C64\u5167\u7684\u6B4C\u624B\u8207\u5C08\u8F2F\u8CC7\u8A0A\u3002
# networkSettings.jsp
-networksettings.text = \u4EE5\u4E0B\u8A2D\u5B9A\u8B93\u60A8\u900F\u904E\u7DB2\u969B\u7DB2\u8DEF\u5B58\u53D6Libresonic\u4F3A\u670D\u5668.
\
- \u6709\u4EFB\u4F55\u554F\u984C, \u8ACB\u53C3\u8003 \u521D\u6B21\u4F7F\u7528\u624B\u518A.
-networksettings.portforwardingenabled = \u81EA\u52D5\u914D\u7F6E\u8DEF\u7531\u5668\u5B58\u53D6Libresonic\u4F3A\u670D\u5668 (UPnP port \u8F49\u767C).
-networksettings.portforwardinghelp = \u5982\u679C\u8DEF\u7531\u7121\u6CD5\u81EA\u52D5\u914D\u7F6E\uFF0C\u8ACB\u4F7F\u7528\u624B\u52D5\u914D\u7F6E.
\
+networksettings.text = \u4EE5\u4E0B\u8A2D\u5B9A\u8B93\u60A8\u900F\u904E\u7DB2\u969B\u7DB2\u8DEF\u5B58\u53D6Libresonic\u4F3A\u670D\u5668\u3002
\
+ \u6709\u4EFB\u4F55\u554F\u984C\uFF0C\u8ACB\u53C3\u8003 \u521D\u6B21\u4F7F\u7528\u624B\u518A\u3002
+networksettings.portforwardingenabled = \u81EA\u52D5\u914D\u7F6E\u8DEF\u7531\u5668\u5B58\u53D6 Libresonic \u4F3A\u670D\u5668 (UPnP port \u8F49\u767C)\u3002
+networksettings.portforwardinghelp = \u5982\u679C\u8DEF\u7531\u7121\u6CD5\u81EA\u52D5\u914D\u7F6E\uFF0C\u8ACB\u4F7F\u7528\u624B\u52D5\u914D\u7F6E\u3002
\
\u4F9D\u7167 portforward.com \u7684\u8AAA\u660E
\
- \u4F60\u5FC5\u9808\u8F49\u767CPort:{0}\u5230\u96FB\u8166\u4E0A\u904B\u884C\u7684Libresonic\u4F3A\u670D\u5668.
-networksettings.urlredirectionenabled = \u7528\u7C21\u55AE\u597D\u8A18\u7684\u7DB2\u5740\u9023\u7DDA\u5230\u60A8\u7684\u4F3A\u670D\u5668.
-networksettings.status = \u72C0\u614B:
+ \u60A8\u5FC5\u9808\u8F49\u767CPort {0}\u5230\u96FB\u8166\u4E0A\u904B\u884C\u7684Libresonic\u4F3A\u670D\u5668\u3002
+networksettings.urlredirectionenabled = \u7528\u7C21\u55AE\u597D\u8A18\u7684\u7DB2\u5740\u9023\u7DDA\u5230\u60A8\u7684\u4F3A\u670D\u5668\u3002
+networksettings.status = \u72C0\u614B\uFF1A
+networksettings.normalurl = Use
+networksettings.customurl = Use custom URL (advanced)
+networksettings.urlRedirectDisabled = Feature not currently available
+
# transcodingSettings.jsp
transcodingsettings.name = \u8F49\u6A94\u540D\u7A31
@@ -316,22 +447,23 @@ transcodingsettings.targetformat = \u8F49\u63DB\u6210
transcodingsettings.step1 = \u6B65\u9A5F\u4E00
transcodingsettings.step2 = \u6B65\u9A5F\u4E8C
transcodingsettings.step3 = \u6B65\u9A5F\u4E09
-transcodingsettings.defaultactive = \u9810\u8A2D
transcodingsettings.add = \u65B0\u589E\u8F49\u78BC\u5668
-transcodingsettings.noname = \u8ACB\u6307\u5B9A\u4E00\u500B\u540D\u7A31.
-transcodingsettings.nosourceformat = \u8ACB\u6307\u5B9A\u8F49\u63DB\u683C\u5F0F.
-transcodingsettings.notargetformat = \u8ACB\u6307\u5B9A\u8F49\u63DB\u683C\u5F0F.
-transcodingsettings.nostep1 = \u8ACB\u81F3\u5C11\u6307\u5B9A\u4E00\u500B\u8F49\u63DB\u6B65\u9A5F.
-transcodingsettings.info = (%s = \u6A94\u6848\u5C07\u88AB\u8F49\u63DB, %b = \u64A5\u653E\u5668\u7684\u6700\u5927\u50B3\u8F38\u7387)
\
- \u8F49\u6A94\u904E\u7A0B\u662F\u7531\u4E00\u500B\u97F3\u6A02\u683C\u5F0F\u7BA1\u63DB\u6210\u53E6\u4E00\u7A2E\u683C\u5F0F. {1}\u7684\u8F49\u6A94 \
- \u5F15\u64CE\u5C07\u975E\u4E32\u6D41\u683C\u5F0F\u8F49\u63DB\u6210\u4E32\u6D41. \u76F4\u63A5\u8F49\u6A94\u4E26\u4E14\u4E0D\u9700\u8981\u78C1\u789F\u904B\u4F5C
\
- \u5BE6\u969B\u7684\u5C08\u63DB\u6771\u505A\u901A\u5E38\u662F\u900F\u904E\u7B2C\u4E09\u65B9\u8EDF\u9AD4\u4EE5\u547D\u4EE4\u5217\u65B9\u5F0F\u8F49\u63DB\uFF0C\u7A0B\u5F0F\u5B89\u88DD\u5728 {0}.
\
- \u800CWindows\u7CFB\u7D71\u7684\u8F49\u63DB\u7A0B\u5F0F\u53EF\u4EE5\u5728\u9019\u88E1\u627E\u5230. \
+transcodingsettings.defaultactive = \u9810\u8A2D
+transcodingsettings.recommended = Recommended configuration
+transcodingsettings.noname = \u8ACB\u6307\u5B9A\u4E00\u500B\u540D\u7A31\u3002
+transcodingsettings.nosourceformat = \u8ACB\u6307\u5B9A\u8F49\u63DB\u7684\u4F86\u6E90\u683C\u5F0F\u3002
+transcodingsettings.notargetformat = \u8ACB\u6307\u5B9A\u8F49\u63DB\u7684\u76EE\u7684\u683C\u5F0F\u3002
+transcodingsettings.nostep1 = \u8ACB\u81F3\u5C11\u6307\u5B9A\u4E00\u500B\u8F49\u63DB\u6B65\u9A5F\u3002
+transcodingsettings.info =
(%s = \u6A94\u6848\u5C07\u88AB\u8F49\u63DB\uFF0C%b = \u64A5\u653E\u5668\u7684\u6700\u5927\u50B3\u8F38\u7387\uFF0C%t = \u6A19\u984C\uFF0C%a = \u6B4C\u624B\uFF0C%l = \u5C08\u8F2F)
\
+ \u8F49\u6A94\u904E\u7A0B\u662F\u7531\u4E00\u500B\u97F3\u6A02\u683C\u5F0F\u8F49\u63DB\u6210\u53E6\u4E00\u7A2E\u683C\u5F0F\u3002{1}\u7684\u8F49\u6A94 \
+ \u5F15\u64CE\u5C07\u975E\u4E32\u6D41\u683C\u5F0F\u8F49\u63DB\u6210\u4E32\u6D41\u3002\u76F4\u63A5\u8F49\u6A94\u4E26\u4E14\u4E0D\u9700\u8981\u78C1\u789F\u904B\u4F5C
\
+ \u5BE6\u969B\u7684\u8F49\u63DB\u52D5\u4F5C\u901A\u5E38\u662F\u900F\u904E\u7B2C\u4E09\u65B9\u8EDF\u9AD4\u4EE5\u547D\u4EE4\u5217\u65B9\u5F0F\u8F49\u63DB\uFF0C\u7A0B\u5F0F\u5B89\u88DD\u5728 {0}\u3002
\
+ \u800CWindows\u7CFB\u7D71\u7684\u8F49\u63DB\u7A0B\u5F0F\u53EF\u4EE5\u5728\u9019\u88E1\u627E\u5230\u3002 \
\u60A8\u4E5F\u80FD\u4EE5\u81EA\u5B9A\u7684\u8F49\u63DB\uFF0C\u53EA\u8981\u6EFF\u8DB3\u4E0B\u9762\u8981\u6C42\uFF1A\
\
- - \u5FC5\u9808\u4EE5\u4E00\u500B\u547D\u4EE4\u884C\u6307\u4EE4\u754C\u9762.
\
- - \u5FC5\u9808\u80FD\u5920\u5C07\u8F38\u51FA\u767C\u9001\u5230\u6A19\u6E96\u8F38\u51FA(Stdout).
\
- - \u5982\u679C\u4F7F\u7528\u6B65\u9A5F2\u62163\uFF0C\u5B83\u5FC5\u9808\u80FD\u5920\u5F9E\u6A19\u6E96\u8F38\u5165(Stdin)\u8B80\u53D6.
\
+ - \u5FC5\u9808\u6709\u547D\u4EE4\u5217\u754C\u9762\u3002
\
+ - \u5FC5\u9808\u80FD\u5920\u5C07\u7D50\u679C\u9001\u5230\u6A19\u6E96\u8F38\u51FA(Stdout)\u3002
\
+ - \u5982\u679C\u5728\u6B65\u9A5F2\u4F7F\u7528\uFF0C\u5B83\u5FC5\u9808\u80FD\u5920\u5F9E\u6A19\u6E96\u8F38\u5165(Stdin)\u8B80\u53D6\u3002
\
\
\
\u8ACB\u6CE8\u610F\uFF0C\u8F49\u63DB\u7684\u7A0B\u5E8F\u7684\u7531\u64A5\u653E\u5668\u8A2D\u5B9A\u4E2D\u52FE\u9078\u3002\u5982\u679C"\u9810\u8A2D"\u662F\u5DF2\u52FE\u9078\u7684\uFF0C\u90A3\u9EBC\u8F49\u63DB\u6703\u81EA\u52D5\u5728\u65B0\u64AD\u653E\u5668\u4E2D\u4F7F\u7528\u3002
@@ -363,35 +495,60 @@ podcastsettings.interval.weekly = \u6BCF\u9031
podcastsettings.folder = \u5132\u5B58\u64AD\u5BA2\u5728
# playerSettings.jsp
-playersettings.noplayers = \u6C92\u6709\u64A5\u653E\u5668.
+playersettings.noplayers = \u6C92\u6709\u64A5\u653E\u5668\u3002
playersettings.type = \u5F62\u614B
playersettings.lastseen = \u4E0A\u6B21\u767B\u5165
playersettings.title = \u9078\u64C7\u64A5\u653E\u5668
-
playersettings.technology.web.title = \u7DB2\u9801\u64AD\u653E
playersettings.technology.external.title = \u76F4\u63A5\u7528\u5916\u90E8\u64AD\u653E\u5668\u64AD\u653E
-playersettings.technology.external_with_playlist.title = \u4EE5\u9EDE\u64AD\u6E05\u55AE\u5728\u5916\u90E8\u64A5\u653E\u5668\u64AD\u653E
+playersettings.technology.external_with_playlist.title = \u4EE5\u64AD\u653E\u6E05\u55AE\u5728\u5916\u90E8\u64A5\u653E\u5668\u64AD\u653E
playersettings.technology.jukebox.title = \u9EDE\u64AD\u6A5F\u6A21\u5F0F
playersettings.technology.web.text = \u76F4\u63A5\u5728\u7DB2\u9801\u4E2D\u7684Flash\u64AD\u653E\u5668\u64AD\u653E.
playersettings.technology.external.text = \u5728\u60A8\u5E38\u7528\u7684\u64A5\u653E\u5668\u4E2D\u64AD\u653E\uFF0C\u4F8B\u5982:WinAmp\u3001Windows Media Player\u3001iTunes.
-playersettings.technology.external_with_playlist.text = \u5982\u540C\u4E0A\u9762\u7684\u9078\u9805\uFF0C\u4F46\u662F\u9EDE\u64AD\u6E05\u55AE\u7531\u5BA2\u6236\u7AEF\u7BA1\u7406\uFF0C\u800C\u4E0D\u662F\u4F3A\u670D\u5668
\
- \u56E0\u6B64\u53EF\u80FD\u7684\u60C5\u6CC1\u4E0B\u53EF\u4EE5\u76F4\u63A5\u8DF3\u807D\u4E0B\u4E00\u9996\u6B4C\u66F2\u3002
-playersettings.technology.jukebox.text = \u76F4\u63A5\u5728Libresonic\u4F3A\u670D\u5668\u4E2D\u64AD\u653E. (\u9650\u5DF2\u6388\u6B0A\u7684\u7528\u6236).
+playersettings.technology.external_with_playlist.text = \u5982\u540C\u4E0A\u9762\u7684\u9078\u9805\uFF0C\u4F46\u662F\u64AD\u653E\u6E05\u55AE\u7531\u5BA2\u6236\u7AEF\u7BA1\u7406\uFF0C\u800C\u4E0D\u662F\u4F3A\u670D\u5668\u3002 \
+ \u5728\u9019\u500B\u6A21\u5F0F\u4E2D\u53EF\u4EE5\u8DF3\u8457\u64AD\u653E\u3002
+playersettings.technology.jukebox.text = \u76F4\u63A5\u5728Libresonic\u4F3A\u670D\u5668\u4E2D\u64AD\u653E\u3002(\u9650\u5DF2\u6388\u6B0A\u7684\u7528\u6236\u3002)
playersettings.name = \u64A5\u653E\u5668\u540D\u7A31
-playersettings.coverartsize = \u5C08\u8F2F\u5C01\u9762\u5927\u5C0F
playersettings.maxbitrate = \u6700\u5927\u50B3\u8F38\u7387
-playersettings.coverart.off = \u4E0D\u986F\u793A
-playersettings.coverart.small = \u5C0F
-playersettings.coverart.medium = \u4E2D
-playersettings.coverart.large = \u5927
-playersettings.notranscoder = \u6CE8\u610F: ffmpeg \u5C1A\u672A\u5B89\u88DD.
\u9EDE\u64CA\u3010\u5354\u52A9\u3011.
+playersettings.notranscoder = \u6CE8\u610F: \u8F49\u78BC\u5F15\u64CE\u5C1A\u672A\u5B89\u88DD\u3002
\u9EDE\u9078\u3010\u8AAA\u660E\u3011\u7372\u5F97\u66F4\u591A\u8CC7\u8A0A\u3002
playersettings.autocontrol = \u81EA\u52D5\u64AD\u653E
+playersettings.m3ubom = \u70ba\u7522\u751f\u7684M3U\u6a94\u6848\u589e\u52a0BOM\u6a19\u8a18
playersettings.dynamicip = \u64A5\u653E\u5668\u4F7F\u7528\u52D5\u614BIP\u4F4D\u5740
playersettings.transcodings = \u555F\u52D5\u7684\u8F49\u78BC\u7A0B\u5F0F
playersettings.ok = \u5132\u5B58
playersettings.forget = \u522A\u9664\u64A5\u653E\u5668
playersettings.clone = \u8907\u88FD\u64A5\u653E\u5668
+dlnasettings.enabled = Enable DLNA server
+dlnasettings.description = Use this option to turn on the DLNA/UPnP Media Server in Libresonic, \
+ and stream your media to compatible DLNA players.
+dlnasettings.servername = Media Server name
+dlnasettings.servername.description = The name of the Media Server as it will appear in DLNA players.
+
+sonossettings.enabled = Enable Sonos music service
+sonossettings.description = Use this option to turn on the Sonos music service in Libresonic, \
+ and stream your media to Sonos devices on your local network. Remember to add Libresonic \
+ as a music service from your Sonos controller. Visit \
+ sonos.libresonic.org for more info. \
+ For trouble-shooting, please see the log.
+sonossettings.servicename = Music service name
+sonossettings.servicename.description = The name of the music service as it will appear in the Sonos controller.
+
+# shareSettings.jsp
+sharesettings.name = Name
+sharesettings.owner = Shared by
+sharesettings.description = Description
+sharesettings.visits = Visits
+sharesettings.lastvisited = Last visited
+sharesettings.expires = Expires
+sharesettings.files = Shared files
+sharesettings.expirein = Expire in
+sharesettings.expirein.week = 1w
+sharesettings.expirein.month = 1m
+sharesettings.expirein.year = 1y
+sharesettings.expirein.never = never
+sharesettings.deleteexpired = Delete all expired
+
# userSettings.jsp
usersettings.title = \u9078\u64C7\u4F7F\u7528\u8005
usersettings.newuser = \u65B0\u4F7F\u7528\u8005
@@ -401,52 +558,67 @@ usersettings.stream = \u53EF\u4EE5\u64AD\u653E\u6A94\u6848
usersettings.jukebox = \u53EF\u4EE5\u7528\u9EDE\u64A5\u6A5F\u6A21\u5F0F
usersettings.download = \u53EF\u4EE5\u4E0B\u8F09\u6A94\u6848
usersettings.upload = \u53EF\u4EE5\u4E0A\u50B3\u6A94\u6848
+usersettings.share = \u53EF\u4EE5\u8207\u4EFB\u4F55\u4EBA\u5206\u4EAB\u6A94\u6848
usersettings.coverart = \u53EF\u4EE5\u66F4\u63DB\u5C08\u8F2F\u5C01\u9762\u53CA\u6A19\u7C64
usersettings.comment= \u53EF\u4EE5\u5EFA\u7ACB\u6216\u7DE8\u8F2F\u8A55\u8AD6\u53CA\u8A55\u5206
usersettings.podcast= \u53EF\u4EE5\u7BA1\u7406\u64AD\u5BA2
+usersettings.folderaccess = \u53EF\u4EE5\u5B58\u53D6\u9019\u4E9B\u5A92\u9AD4\u8CC7\u6599\u593E
usersettings.username = \u4F7F\u7528\u8005
+usersettings.email = Email
usersettings.changepassword = \u8B8A\u66F4\u5BC6\u78BC
usersettings.password = \u5BC6\u78BC
usersettings.newpassword = \u65B0\u5BC6\u78BC
usersettings.confirmpassword = \u518D\u6B21\u78BA\u8A8D\u5BC6\u78BC
usersettings.delete = \u522A\u9664\u4F7F\u7528\u8005
usersettings.ldap = \u5728LDAP\u9A57\u8B49\u7528\u6236
-usersettings.nousername = \u7F3A\u5C11\u4F7F\u7528\u8005\u540D\u7A31.
-usersettings.useralreadyexists = \u4F7F\u7528\u8005\u540D\u7A31\u5DF2\u7D93\u88AB\u4F7F\u7528\u4E86\uFF01.
-usersettings.nopassword = \u5FC5\u9808\u8A2D\u5B9A\u5BC6\u78BC.
-usersettings.wrongpassword = \u5169\u6B21\u8F38\u5165\u5BC6\u78BC\u4E0D\u540C.
-usersettings.ldapdisabled = LDAP\u9A57\u8B49\u6C92\u6709\u555F\u52D5. \u8ACB\u5148\u5230\u9032\u968E\u8A2D\u5B9A.
-usersettings.passwordnotsupportedforldap = \u7121\u6CD5\u8A2D\u5B9A\u6216\u8B8A\u66F4LDAP\u9A57\u8B49\u7528\u6236\u7684\u5BC6\u78BC.
-usersettings.ok = \u4F7F\u7528\u8005 {0}\u7684\u5BC6\u78BC\u5DF2\u7D93\u8B8A\u66F4.
-
-# musicFolderSettings.jsp
-musicfoldersettings.interval.never = \u5F9E\u4E0D
-musicfoldersettings.interval.one = \u6BCF\u5929
-musicfoldersettings.interval.many = \u6BCF\u9694 {0} \u5929
-musicfoldersettings.hour = \u5728 {0}:00
+usersettings.nousername = \u7F3A\u5C11\u4F7F\u7528\u8005\u540D\u7A31\u3002
+usersettings.noemail= \u4E0D\u5408\u6CD5\u7684 email \u4F4D\u5740\u3002
+usersettings.useralreadyexists = \u5E33\u865F\u540D\u7A31\u5DF2\u7D93\u88AB\u4F7F\u7528\u4E86\u3002
+usersettings.nopassword = \u5FC5\u9808\u8A2D\u5B9A\u5BC6\u78BC\u3002
+usersettings.wrongpassword = \u5169\u6B21\u8F38\u5165\u5BC6\u78BC\u4E0D\u540C\u3002
+usersettings.ldapdisabled = LDAP\u9A57\u8B49\u6C92\u6709\u555F\u52D5\u3002\u8ACB\u5230\u9032\u968E\u8A2D\u5B9A\u3002
+usersettings.passwordnotsupportedforldap = \u7121\u6CD5\u8A2D\u5B9A\u6216\u8B8A\u66F4 LDAP \u9A57\u8B49\u7528\u6236\u7684\u5BC6\u78BC\u3002
+usersettings.ok = \u4F7F\u7528\u8005 {0} \u7684\u5BC6\u78BC\u5DF2\u7D93\u8B8A\u66F4\u3002
# main.jsp
main.up = \u4E0A\u4E00\u9801
main.playall = \u5168\u90E8\u64AD\u653E
main.playrandom = \u96A8\u8208\u64AD\u653E
-main.addall = \u5168\u90E8\u52A0\u5230\u9EDE\u64AD\u6E05\u55AE\u4E2D
+main.addall = \u5168\u90E8\u52A0\u5230\u64AD\u653E\u6E05\u55AE\u4E2D
main.downloadall = \u5168\u90E8\u4E0B\u8F09
main.tags = \u7DE8\u8F2F\u6A19\u7C64
-main.playcount = \u9EDE\u64AD {0} \u6B21.
-main.lastplayed =\u4E0A\u6B21\u9EDE\u64AD\u5728 {0}.
+main.playcount = \u64AD\u653E {0} \u6B21\u3002
+main.lastplayed =\u4E0A\u6B21\u64AD\u653E\u5728 {0} \u3002
main.comment = \u8A55\u8AD6
main.wiki = \
- __text__ | Bold text | \\\\ | Line break |
\
- ~~text~~ | Italic text | (empty line) | New paragraph |
\
- * text | List item | http://foo.com/ | Link |
\
- 1. text | Enumerated list item | {link:Foo|http://foo.com} | Named link |
\
+ __text__ | \u7C97\u9AD4 | \\\\ | \u63DB\u884C |
\
+ ~~text~~ | \u659C\u9AD4 | (empty line) | \u65B0\u6BB5\u843D |
\
+ * text | \u6E05\u55AE | http://foo.com/ | \u934A\u7D50 |
\
+ 1. text | \u5217\u8209\u6E05\u55AE | {link:Foo|http://foo.com} | \u5DF2\u547D\u540D\u934A\u7D50 |
\
+main.sharealbum = \u5206\u4EAB
+main.more = \u66F4\u591A\u52D5\u4F5C\u2026
+main.more.selection = \u9078\u64C7\u6B4C\u66F2\u2026
+main.more.share = \u5206\u4EAB
+main.premium = \u53D6\u5F97 Subsonic Premium
(\u4E26\u522A\u9664\u6B64\u5EE3\u544A)
main.nowplaying =\u76EE\u524D\u64A5\u653E
main.lyrics = \u6B4C\u8A5E
main.minutesago = \u5206\u9418\u524D
main.chat = \u4EA4\u8AC7
+main.scanning = \u6383\u63CF\u6A94\u6848\uFF1A
main.message = \u5BEB\u5728\u9019\u88E1
main.clearchat = \u6E05\u9664
+main.addtoplaylist.title = \u589E\u52A0\u81F3\u64AD\u653E\u6E05\u55AE
+main.addtoplaylist.text = \u589E\u52A0\u5DF2\u9078\u64C7\u7684\u6B4C\u66F2\u81F3\u6B64\u64AD\u653E\u6E05\u55AE\uFF1A
+main.addnext = \u52A0\u5230\u4E0B\u4E00\u9996
+main.addlast = \u52A0\u5230\u6700\u5F8C\u4E00\u9996
+main.addnext.toast = \u6B64\u6B4C\u66F2\u5C07\u6703\u65BC\u4E0B\u4E00\u9996\u6642\u64AD\u653E
+main.addlast.toast = \u6B64\u6B4C\u66F2\u5C07\u6703\u65BC\u6700\u5F8C\u4E00\u9996\u6642\u64AD\u653E
+main.similarartists = \u76F8\u4F3C\u7684\u6B4C\u624B
+main.startradio = Start radio
+main.playtopsongs = \u64AD\u653E\u6392\u884C\u699C\u6B4C\u66F2
+main.showall = \u986F\u793A\u6240\u6709\u5C08\u8F2F
+main.topsongs = \u6392\u884C\u699C\u6B4C\u66F2
# rating.jsp
rating.rating = \u7B49\u7D1A
@@ -457,17 +629,18 @@ coverart.change = \u8B8A\u66F4
coverart.zoom = \u653E\u5927
# allmusic.jsp
-allmusic.text = \u5728 allmusic.com \u641C\u5C0B\u5C08\u8F2F {0} - \u8ACB\u7A0D\u5019.
+allmusic.text = \u5728 allmusic.com \u641C\u5C0B\u5C08\u8F2F {0} - \u8ACB\u7A0D\u5019\u3002
# changeCoverArt.jsp
changecoverart.title = \u8B8A\u66F4\u5C08\u8F2F\u5C01\u9762
changecoverart.address = \u6216\u662F\u8F38\u5165\u5716\u5F62\u7684\u4F4D\u5740
changecoverart.artist = \u6B4C\u624B
changecoverart.album = \u5C08\u8F2F
-changecoverart.wait = \u8ACB\u7A0D\u5019...
-changecoverart.success = \u5716\u5F62\u4E0B\u8F09\u6210\u529F.
-changecoverart.error = \u7121\u6CD5\u4E0B\u8F09\u5716\u5F62.
-changecoverart.noimagesfound = \u627E\u4E0D\u5230\u5716\u5F62\u6A94.
+changecoverart.search = Google \u5716\u7247\u641C\u5C0B
+changecoverart.wait = \u8ACB\u7A0D\u5019\u2026
+changecoverart.success = \u5716\u7247\u4E0B\u8F09\u6210\u529F\u3002
+changecoverart.error = \u7121\u6CD5\u4E0B\u8F09\u5716\u7247\u3002
+changecoverart.noimagesfound = \u627E\u4E0D\u5230\u5716\u7247\u3002
# changeCoverArtConfirm.jsp
changeCoverArtConfirm.failed = \u7121\u6CD5\u4FEE\u6539\u5C08\u8F2F\u5C01\u9762:
"{0}"
@@ -492,8 +665,48 @@ edittags.updated = Updated
edittags.skipped = \u7565\u904E
edittags.error = \u932F\u8AA4
+# share.jsp
+share.title = Share
+share.warning = IMPORTANT NOTICE!
Play fair – Don't share copyrighted material in any manner that violates the law.
+share.facebook = \u5206\u4EAB\u81F3 Facebook
+share.twitter = \u5206\u4EAB\u81F3 Twitter
+share.googleplus = \u5206\u4EAB\u81F3 Google+
+share.link = Or share this with someone by sending them this link: {0}
+share.disabled = To share your music with someone you must first register your own libresonic.org address.
\
+ Please go to Settings > Network (administrative rights required).
+share.manage = Manage my shared media
+
+# premium.jsp
+premium.title = Subsonic Premium
+premium.invalidlicense = Invalid license key.
+premium.text = Upgrade to Subsonic Premium to enjoy these extra features:
\
+ \
+ - Apps for Android, iPhone, Windows Phone, Mac, Chrome and more*.
\
+ - Video streaming.
\
+ - Stream to your Chromecast and Sonos devices.
\
+ - Podcast receiver.
\
+ - Your personal server address: yourname.libresonic.org (see Settings > Network).
\
+ - Play your media on compatible DLNA/UPnP devices.
\
+ - Share your media on Facebook, Twitter, Google+.
\
+ - No ads in the web interface.
\
+ - Other features to be released later.
\
+
\
+ * Some apps must be purchased separately.
+premium.getpremium = \u53D6\u5F97 Subsonic Premium
+premium.licensed = You have a valid Subsonic Premium license!
+premium.licensedexpires = Your Subsonic Premium license is valid until {0}
+premium.licensedexpired = Your Subsonic Premium license expired {0}
+premium.licensedto = The license is registered to {0}.
+premium.forcechange = Register a different license key
+premium.register = When upgrading to Subsonic Premium you receive a license key by email. Please register it below.
+premium.resend = Lost the license key? Send it again.
+premium.register.email = Email
+premium.register.license = License key
+
# podcastReceiver.jsp
podcastreceiver.title = \u64AD\u5BA2\u63A5\u6536\u5668
+podcastreceiver.empty = You haven't subscribed to any podcasts yet.
+podcastreceiver.episodes = {0} \u7AE0\u7BC0
podcastreceiver.expandall = \u986F\u793A\u6536\u85CF\u96C6
podcastreceiver.collapseall = \u96B1\u85CF\u6536\u85CF\u96C6
podcastreceiver.status.new = \u65B0\u7684
@@ -509,78 +722,86 @@ podcastreceiver.check = \u6838\u5C0D\u65B0\u7684\u6536\u85CF\u96C6
podcastreceiver.refresh = \u5237\u65B0\u672C\u9801
podcastreceiver.settings = \u64AD\u5BA2\u8A2D\u5B9A
podcastreceiver.subscribe = \u8A02\u95B1\u64AD\u5BA2
+podcastreceiver.newestepisodes = \u6700\u65B0\u7AE0\u7BC0
# lyrics.jsp
lyrics.title = \u6B4C\u8A5E
lyrics.artist = \u6B4C\u624B
lyrics.song = \u6B4C\u66F2
lyrics.search = \u641C\u5C0B
-lyrics.wait = \u641C\u5C0B\u6B4C\u8A5E\u4E2D, \u8ACB\u7A0D\u5019...
+lyrics.wait = \u641C\u5C0B\u6B4C\u8A5E\u4E2D\uFF0C\u8ACB\u7A0D\u5019\u2026
lyrics.courtesy = (\u6B4C\u8A5E\u7531chartlyrics.com\u63D0\u4F9B)
-lyrics.nolyricsfound = \u627E\u4E0D\u5230\u6B4C\u8A5E.
+lyrics.nolyricsfound = \u627E\u4E0D\u5230\u6B4C\u8A5E\u3002
+lyrics.trylater = Sorry, the lyrics search engine allows just one search every 20 seconds. Try again later.
# helpPopup.jsp
helppopup.title = {0} \u5354\u52A9
-helppopup.cover.title = \u5C08\u8F2F\u5C01\u9762\u5927\u5C0F
-helppopup.cover.text = \u7531\u60A8\u6307\u5B9A\u986F\u793A\u5C08\u8F2F\u5C01\u9762\u7684\u5927\u5C0F\uFF0C\u4E5F\u53EF\u4EE5\u5B8C\u5168\u95DC\u9589.
helppopup.transcode.title = \u6700\u5927\u50B3\u8F38\u7387
-helppopup.transcode.text = \u5982\u679C\u60A8\u7684\u64AD\u653E\u983B\u5BEC\u6709\u9650\uFF0C\u53EF\u4EE5\u904E\u8A2D\u5B9A\u6700\u5927\u50B3\u8F38\u7387\u4F86\u6539\u5584. \
- \u4F8B\u5982,\u5982\u679Cmp3\u539F\u672C\u7684\u58D3\u7E2E\u6BD4\u4F8B\u70BA256Kbps(kilobits per second), \u5982\u679C\u8A2D\u5B9A\u6700\u5927\u50B3\u8F38\u7387\u70BA128\
- \u6703\u4F7F{0}\u81EA\u52D5\u5C07\u539F\u672C 256Kbps\u7684\u97F3\u6A02\u8ABF\u964D\u6210 128 Kbps.
-helppopup.playlistfolder.title = \u9EDE\u64AD\u6E05\u55AE\u8CC7\u6599\u593E
-helppopup.playlistfolder.text = \u5B58\u653E\u9EDE\u64AD\u6E05\u55AE\u7684\u8CC7\u6599\u593E.
+helppopup.transcode.text = \u5982\u679C\u60A8\u7684\u64AD\u653E\u983B\u5BEC\u6709\u9650\uFF0C\u53EF\u4EE5\u904E\u8A2D\u5B9A\u6700\u5927\u50B3\u8F38\u7387\u4F86\u6539\u5584\u3002 \
+ \u4F8B\u5982\uFF0C\u5982\u679C\u60A8\u539F\u672C\u7684 mp3 \u6A94\u6848\u7684\u7DE8\u78BC\u7387\u70BA 256Kbps(\u6BCF\u79D2\u5343\u4F4D\u5143)\uFF0C\u5982\u679C\u8A2D\u5B9A\u6700\u5927\u50B3\u8F38\u7387\u70BA128\
+ \u6703\u4F7F {0} \u81EA\u52D5\u5C07\u539F\u672C 256Kbps \u7684\u97F3\u6A02\u7DE8\u78BC\u70BA\u6210 128 Kbps\u3002
+helppopup.playlistfolder.title = \u64AD\u653E\u6E05\u55AE\u8CC7\u6599\u593E
+helppopup.playlistfolder.text = \u5B58\u653E\u64AD\u653E\u6E05\u55AE\u7684\u8CC7\u6599\u593E\u3002
helppopup.musicmask.title = \u97F3\u6A02\u7684\u9644\u5C6C\u6A94\u540D
helppopup.musicmask.text = \u6307\u5B9A\u97F3\u6A02\u6A94\u6848\u7684\u9644\u5C6C\u6A94\u540D
helppopup.videomask.title = \u8996\u8A0A\u6A94\u7684\u9644\u5C6C\u6A94\u540D
helppopup.videomask.text = \u6307\u5B9A\u8996\u8A0A\u6A94\u6848\u7684\u8CA0\u6578\u6A94\u540D
helppopup.coverartmask.title = \u5C08\u8F2F\u5C01\u9762\u9644\u5C6C\u6A94\u540D
-helppopup.coverartmask.text = \u8207\u97F3\u6A02\u593E\u653E\u5728\u4E00\u8D77\u7684\u5C08\u8F2F\u5C01\u9762\uFF0C\u5148\u6307\u5B9A\u5C08\u8F2F\u5C01\u9762\u6A94\u6848\u7684\u9644\u5C6C\u6A94\u540D.
+helppopup.coverartmask.text = \u8207\u97F3\u6A02\u8CC7\u6599\u593E\u653E\u5728\u4E00\u8D77\u7684\u5C08\u8F2F\u5C01\u9762\uFF0C\u5148\u6307\u5B9A\u5C08\u8F2F\u5C01\u9762\u6A94\u6848\u7684\u9644\u5C6C\u6A94\u540D\u3002
helppopup.downsamplecommand.title = \u964D\u983B\u6307\u4EE4
-helppopup.downsamplecommand.text = \u8B93\u60A8\u8A2D\u5B9A\u8ABF\u964D\u64AD\u653E\u97F3\u6A02\u6642\u964D\u4F4E\u53D6\u6A23\u983B\u7387\u7684\u6307\u4EE4.
\
- (%s = \u8981\u964D\u983B\u7684\u6A94\u6848, %b = \u64A5\u653E\u5668\u7684\u6700\u5927\u50B3\u8F38\u7387)
+helppopup.downsamplecommand.text = \u8B93\u60A8\u8A2D\u5B9A\u8ABF\u964D\u64AD\u653E\u97F3\u6A02\u6642\u964D\u4F4E\u53D6\u6A23\u983B\u7387\u7684\u6307\u4EE4\u3002
\
+ (%s = \u8981\u964D\u983B\u7684\u6A94\u6848\uFF0C%b = \u64A5\u653E\u5668\u7684\u6700\u5927\u50B3\u8F38\u7387\uFF0C%t = \u6A19\u984C\uFF0C%a = \u6B4C\u624B\uFF0C%l = \u5C08\u8F2F)
+helppopup.hlscommand.title = HTTP Live Streaming command
+helppopup.hlscommand.text = The command used to create video segments for Apple''s HLS (HTTP Live Streaming) protocol.
helppopup.index.title = \u5206\u985E\u6AA2\u7D22
-helppopup.index.text = \u8A2D\u5B9A\u97F3\u6A02\u6AA2\u7D22\u7684\u65B9\u5F0F\uFF0C\uFF08\u5C31\u5982\u540C\u73FE\u5728\u5728\u87A2\u5E55\u5DE6\u4E0A\u65B9\u7684\u5206\u985E\uFF09. \u5728\u97F3\u6A02\u593E\u88E1\u7684\u6A94\u6848\u5F88\u5BB9\u6613\u5206\u985E\u6AA2\u7D22
\
- \u901A\u5E38\u4EE5\u7A7A\u767D\u4F86\u5206\u9694\u6AA2\u7D22\u9805\u76EE. \u4E00\u822C\u4F86\u8AAA\uFF0C\u4E00\u500B\u5B57\u6BCD\uFF08\u570B\u5B57\uFF09\u70BA\u4E00\u500B\u9805\u76EE, \
- \u4F46\u4E5F\u53EF\u4EE5\u591A\u500B\u5B57\u6BCD\uFF08\u570B\u5B57\uFF09\u653E\u5728\u540C\u4E00\u5206\u985E\u9805\u76EE\u4E2D. \u4F8B\u5982\uFF1A\u3105(\u5305\u9B91),\u53EF\u4EE5\u5C07 \u5305\u9B91\u8996\u70BA\u540C\u4E00\u5206\u985E\
-
\u800C\u7121\u6CD5\u6B78\u985E\u7684\u6A94\u6848\uFF0C\u5C07\u5168\u90E8\u6B78\u65BC "#"\u9805\u76EE\u4E2D.
+helppopup.index.text = \u8A2D\u5B9A\u97F3\u6A02\u7D22\u5F15(\u5728\u87A2\u5E55\u5DE6\u65B9)\u6B78\u985E\u7684\u65B9\u5F0F\u3002\u5728\u97F3\u6A02\u8CC7\u6599\u593E\u88E1\u7684 \
+ \u6A94\u6848\u5F88\u5BB9\u6613\u900F\u904E\u7D22\u5F15\u5B58\u53D6\u3002
\
+ \u5B9A\u7FA9\u65B9\u5F0F\u662F\u4EE5\u7A7A\u767D\u5206\u9694\u7684\u7D22\u5F15\u9805\u76EE\u3002\u4E00\u822C\u4F86\u8AAA\uFF0C\u9805\u76EE\u662F\u55AE\u4E00\u5B57\u6BCD\uFF0C \
+ \u4F46\u60A8\u4E5F\u53EF\u4EE5\u6307\u5B9A\u591A\u500B\u5B57\u6BCD\u3002\u4F8B\u5982\uFF1A\u9805\u76EE The \u6703\u9023\u7D50\u5230\u6240\u6709 \
+ \u958B\u982D\u70BA "The" \u7684\u8CC7\u6599\u593E\u8207\u6A94\u6848\u3002
\
+ \u60A8\u4E5F\u53EF\u4EE5\u7528\u62EC\u5F27\u4F86\u5305\u542B\u591A\u500B\u7D22\u5F15\u5B57\u5143\u3002\u4F8B\u5982\uFF1A \
+ A-E(ABCDE) \u6703\u986F\u793A\u70BA A-E \u4E26\u9023\u7D50\u5230\u6240\u6709\u958B\u982D\u70BA \
+ A\u3001B\u3001C\u3001D\u6216E\u7684\u8CC7\u6599\u593E\u8207\u6A94\u6848\u3002\u9019\u5C0D\u65BC\u6536\u7D0D\u5C11\u898B\u7684\u5B57\u5143(\u50CF\u662FX\u3001Y\u8207Z)\u5F88\u6709\u5E6B\u52A9\uFF0C\u6216 \
+ \u6B78\u985E\u91CD\u97F3\u5B57\u5143(\u5982A\u3001\u00C0\u8207\u00C1)
\
+ \u7121\u6CD5\u6B78\u985E\u7684\u8CC7\u6599\u593E\u8207\u6A94\u6848\uFF0C\u5C07\u5168\u90E8\u6B78\u65BC "#" \u9805\u76EE\u4E2D\u3002
helppopup.ignoredarticles.title = \u5FFD\u7565\u5B57\u9996
-helppopup.ignoredarticles.text = \u6709\u4E9B\u5B57\u9996(\u4F8B\u5982"The") \u901A\u5E38\u5728\u66F2\u76EE\u6B78\u985E\u4E2D\u61C9\u8A72\u5FFD\u7565\uFF0C\u8ACB\u5728\u6B64\u8655\u8A2D\u5B9A.
+helppopup.ignoredarticles.text = \u6709\u4E9B\u5B57\u9996(\u4F8B\u5982"The") \u901A\u5E38\u5728\u66F2\u76EE\u6B78\u985E\u4E2D\u61C9\u8A72\u5FFD\u7565\uFF0C\u8ACB\u5728\u6B64\u8655\u8A2D\u5B9A\u3002
helppopup.shortcuts.title = \u6377\u5F91
-helppopup.shortcuts.text = \u4EE5\u7A7A\u767D\u4F86\u5206\u9694\u5728\u6700\u4E0A\u5C64\u76EE\u9304\u4E2D\u5EFA\u7ACB\u6377\u5F91\u6AA2\u7D22. \u7528\u5F15\u865F\u4F86\u5206\u7D44\u5B57\u5143, \u4F8B\u5982:
\
+helppopup.shortcuts.text = \u4EE5\u7A7A\u767D\u4F86\u5206\u9694\u5728\u6700\u4E0A\u5C64\u76EE\u9304\u4E2D\u5EFA\u7ACB\u6377\u5F91\u6AA2\u7D22\u3002\u7528\u5F15\u865F\u4F86\u5206\u7D44\u5B57\u5143\uFF0C\u4F8B\u5982\uFF1A
\
New Incoming "Sound tracks"
-helppopup.language.title = Language
-helppopup.language.text = \u5728\u9019\u88E1\u9078\u64C7\u6240\u63D0\u4F9B\u7684\u986F\u793A\u8A9E\u8A00.
+helppopup.language.title = \u8A9E\u8A00
+helppopup.language.text = \u5728\u9019\u88E1\u9078\u64C7\u6240\u63D0\u4F9B\u7684\u986F\u793A\u8A9E\u8A00\u3002
helppopup.visibility.title = \u986F\u793A\u9805\u76EE
-helppopup.visibility.text = \u9078\u64C7\u5728\u700F\u89BD\u6216\u662F\u5728\u9EDE\u64AD\u6E05\u55AE\u4E2D\uFF0C\u986F\u793A\u97F3\u6A02\u7684\u5404\u7A2E\u8A73\u7D30\u8CC7\u8A0A
+helppopup.visibility.text = \u9078\u64C7\u5728\u700F\u89BD\u6216\u662F\u5728\u64AD\u653E\u6E05\u55AE\u4E2D\uFF0C\u986F\u793A\u97F3\u6A02\u7684\u5404\u7A2E\u8A73\u7D30\u8CC7\u8A0A
helppopup.partymode.title = \u5BB4\u6703\u6A21\u5F0F
helppopup.partymode.text = \u4F7F\u7528\u5BB4\u6703\u6A21\u5F0F\u7C21\u5316\u4F7F\u7528\u8005\u754C\u9762\uFF0C\u63D0\u4F9B\u7D66\u7121\u7D93\u9A57\u7684\u4F7F\u7528\u8005\u64CD\u4F5C\
- \u4E5F\u53EF\u4EE5\u907F\u514D\u56E0\u70BA\u610F\u5916\u64CD\u4F5C\u800C\u5F04\u4E82\u4E86\u9EDE\u64AD\u6E05\u55AE.
+ \u4E5F\u53EF\u4EE5\u907F\u514D\u56E0\u70BA\u610F\u5916\u64CD\u4F5C\u800C\u5F04\u4E82\u4E86\u64AD\u653E\u6E05\u55AE\u3002
helppopup.theme.title = \u4F48\u666F\u4E3B\u984C
-helppopup.theme.text = \u8B93\u60A8\u53EF\u4EE5\u9078\u64C7\u4E0D\u540C\u7684\u4F48\u666F\u4E3B\u984C. \u4F48\u666F\u4E3B\u984C\u900F\u904E\u4E0D\u540C\u7684\u984F\u8272\u3001\u5B57\u9AD4\u3001\u5716\u50CF\u7B49\uFF0C\u5E36\u7D66\u60A8\u4E0D\u540C\u7684{0}\u611F\u53D7.
+helppopup.theme.text = \u8B93\u60A8\u53EF\u4EE5\u9078\u64C7\u4E0D\u540C\u7684\u4F48\u666F\u4E3B\u984C\u3002\u4F48\u666F\u4E3B\u984C\u900F\u904E\u4E0D\u540C\u7684\u984F\u8272\u3001\u5B57\u9AD4\u3001\u5716\u50CF\u7B49\uFF0C\u5E36\u7D66\u60A8\u4E0D\u540C\u7684{0}\u611F\u53D7\u3002
helppopup.welcomemessage.title = \u6B61\u8FCE\u6A19\u984C
-helppopup.welcomemessage.text = \u5728\u9996\u9801\u4E2D\u986F\u793A\u7684\u6A19\u984C.
+helppopup.welcomemessage.text = \u5728\u9996\u9801\u4E2D\u986F\u793A\u7684\u6A19\u984C\u3002
helppopup.loginmessage.title = \u767B\u5165\u8A0A\u606F
-helppopup.loginmessage.text = \u5728\u767B\u5165\u756B\u9762\u986F\u793A\u7684\u63D0\u793A\u8A0A\u606F.
+helppopup.loginmessage.text = \u5728\u767B\u5165\u756B\u9762\u986F\u793A\u7684\u63D0\u793A\u8A0A\u606F\u3002
helppopup.coverartlimit.title = \u5C08\u8F2F\u5C01\u9762\u9650\u5236
-helppopup.coverartlimit.text = \u5728\u4E00\u9801\u756B\u9762\u4E2D\u986F\u793A\u5C08\u8F2F\u5C01\u9762\u7684\u6700\u5927\u6578\u91CF.
+helppopup.coverartlimit.text = \u5728\u4E00\u9801\u756B\u9762\u4E2D\u986F\u793A\u5C08\u8F2F\u5C01\u9762\u7684\u6700\u5927\u6578\u91CF\u3002
helppopup.downloadlimit.title = \u4E0B\u8F09\u9650\u5236
-helppopup.downloadlimit.text = \u4E0B\u8F09\u6A94\u6848\u6642\u7684\u983B\u5BEC\u9650\u5236.
+helppopup.downloadlimit.text = \u4E0B\u8F09\u6A94\u6848\u6642\u7684\u983B\u5BEC\u9650\u5236\u3002
helppopup.uploadlimit.title = \u4E0A\u50B3\u9650\u5236
-helppopup.uploadlimit.text = \u4E0A\u50B3\u6A94\u6848\u6642\u7684\u983B\u5BEC\u9650\u5236.
-helppopup.streamport.title = \u975E-SSL \u4E32\u6D41 Port
-helppopup.streamport.text = \u672C\u9078\u9805\u53EA\u662F\u7528\u65BC\u5728\u4F3A\u670D\u5668\u4E0A\u7684 {0} \u4F7F\u7528 SSL (HTTPS)\u50B3\u8F38\u5354\u5B9A.
\u6709\u4E9B\u64AD\u653E\u5668 \
- (\u4F8B\u5982 Winamp) \u4E26\u672A\u652F\u63F4\u7D93\u7531SSL\u7684\u4E32\u6D41\u5354\u5B9A. \u5982\u679C\u60A8\u4E0D\u7D93\u7531SSL\u50B3\u9001\u4E32\u6D41\uFF0C\u8ACB\u6307\u5B9A\u901A\u8A0APORT(\u901A\u5E38\u662F80\u62164040)\
- \u8ACB\u6CE8\u610F\uFF0C\u4E32\u6D41\u97F3\u6A02\u4E26\u4E0D\u6703\u88AB\u52A0\u5BC6.
+helppopup.uploadlimit.text = \u4E0A\u50B3\u6A94\u6848\u6642\u7684\u983B\u5BEC\u9650\u5236\u3002
+helppopup.streamport.title = \u975ESSL \u4E32\u6D41 Port
+helppopup.streamport.text = \u672C\u9078\u9805\u53EA\u662F\u7528\u65BC\u5728\u4F3A\u670D\u5668\u4E0A\u7684 {0} \u4F7F\u7528 SSL (HTTPS)\u50B3\u8F38\u5354\u5B9A\u3002
\u6709\u4E9B\u64AD\u653E\u5668 \
+ (\u4F8B\u5982 Winamp) \u4E0D\u652F\u63F4\u7D93\u7531SSL\u7684\u4E32\u6D41\u5354\u5B9A\u3002\u5982\u679C\u60A8\u4E0D\u7D93\u7531SSL\u50B3\u9001\u4E32\u6D41\uFF0C\u8ACB\u6307\u5B9A\u901A\u8A0APORT(\u901A\u5E38\u662F80\u62164040)\
+ \u8ACB\u6CE8\u610F\uFF0C\u4E32\u6D41\u97F3\u6A02\u4E26\u4E0D\u6703\u88AB\u52A0\u5BC6\u3002
helppopup.ldap.title = LDAP \u9A57\u8B49
-helppopup.ldap.text = \u4F7F\u7528\u8005\u53EF\u4EE5\u7D93\u7531\u5916\u90E8\u7684LDAP\u4F3A\u670D\u5668\u9A57\u8B49 (\u5305\u62ECWindows Active Directory). \
- \u7576\u8A2D\u5B9A\u4F7F\u7528LDAP\u4F7F\u7528\u8005\u767B\u5165 {0}, \u5E33\u865F\u53CA\u5BC6\u78BC\u5C31\u7531\u5916\u90E8\u4F3A\u670D\u5668\u9A57\u8B49, \u800C\u4E0D\u662F\u7531{0}\u4F86\u9A57\u8B49.
+helppopup.ldap.text = \u4F7F\u7528\u8005\u53EF\u4EE5\u7D93\u7531\u5916\u90E8\u7684LDAP\u4F3A\u670D\u5668\u9A57\u8B49 (\u5305\u62ECWindows Active Directory)\u3002\
+ \u7576\u8A2D\u5B9A\u4F7F\u7528LDAP\u4F7F\u7528\u8005\u767B\u5165 {0}\uFF0C\u5E33\u865F\u53CA\u5BC6\u78BC\u5C31\u7531\u5916\u90E8\u4F3A\u670D\u5668\u9A57\u8B49\uFF0C\u800C\u4E0D\u662F\u7531{0}\u4F86\u9A57\u8B49\u3002
helppopup.ldapurl.title = LDAP \u4F4D\u5740
-helppopup.ldapurl.text = \u8A2D\u5B9A LDAP \u4F3A\u670D\u5668\u7684\u4F4D\u5740. \u5354\u5B9A\u61C9\u8A72\u662F ldap:// \u6216 ldaps:// \
- (\u7D93\u7531SSL\u7684LDAP\u5354\u5B9A). \u8ACB\u53C3\u8003\u9019\u88E1 \
- \u6709\u66F4\u591A\u8A73\u7D30\u8AAA\u660E.
+helppopup.ldapurl.text = \u8A2D\u5B9A LDAP \u4F3A\u670D\u5668\u7684\u4F4D\u5740\u3002\u5354\u5B9A\u61C9\u8A72\u662F ldap:// \u6216 ldaps:// \
+ (\u7D93\u7531SSL\u7684LDAP\u5354\u5B9A)\u3002\u8ACB\u53C3\u8003\u9019\u88E1 \
+ \u6709\u66F4\u591A\u8A73\u7D30\u8AAA\u660E\u3002
helppopup.ldapsearchfilter.title = LDAP \u641C\u5C0B\u904E\u6FFE
helppopup.ldapsearchfilter.text = \u8490\u5C0BLDAP\u7528\u6236\u6642\uFF0C\u5728\u9019\u88E1\u8A2D\u5B9A\u904E\u6FFE\u8868\u793A\u5F0F \
- (\u5B9A\u7FA9\u5728RFC 2254). \
+ (\u5B9A\u7FA9\u5728RFC 2254)\u3002 \
The pattern "'{0'}" is replaced by the username, \u4F8B\u5982: \
helppopup.ldapmanagerdn.title = LDAP \u7BA1\u7406\u8005 DN
helppopup.ldapmanagerdn.text = \u5982\u679C LDAP \u4F3A\u670D\u5668\u4E0D\u652F\u63F4\u533F\u540D\u4F7F\u7528\u8005\u9023\u7DDA\uFF0C\u60A8\u5FC5\u9808\u6307\u5B9A DN \
- (Distinguished Name)\u53CALDAP\u4F7F\u7528\u8005\u7684\u5BC6\u78BC.
+ (Distinguished Name)\u53CALDAP\u4F7F\u7528\u8005\u7684\u5BC6\u78BC\u3002
helppopup.ldapautoshadowing.title = \u5728 {0} \u81EA\u52D5\u5EFA\u7ACB LDAP \u5E33\u865F
-helppopup.ldapautoshadowing.text = \u8A2D\u5B9A\u9019\u500B\u9078\u9805, \u5247LDAP \u7528\u6236\u4E0D\u5FC5\u5728\u767B\u5165\u4E4B\u524D\u624B\u52D5\u5EFA\u7ACB{0}\u7684\u5E33\u865F.
\
- \u6CE8\u610F! \u9019\u610F\u5473\u6240\u6709\u5728LDAP\u4E0A\u7684\u4F7F\u7528\u8005\u90FD\u53EF\u4EE5\u767B\u5165\u60A8\u7684{0}, \
- \u4E5F\u8A31\u9019\u4E0D\u662F\u60A8\u60F3\u8981\u7684\u529F\u80FD.
+helppopup.ldapautoshadowing.text = \u8A2D\u5B9A\u9019\u500B\u9078\u9805\uFF0C\u5247LDAP \u7528\u6236\u4E0D\u5FC5\u5728\u767B\u5165\u4E4B\u524D\u624B\u52D5\u5EFA\u7ACB{0}\u7684\u5E33\u865F\u3002
\
+ \u6CE8\u610F\uFF01 \u9019\u8868\u793A\u6240\u6709\u5728LDAP\u4E0A\u7684\u4F7F\u7528\u8005\u90FD\u53EF\u4EE5\u767B\u5165\u60A8\u7684{0}\uFF0C\
+ \u4E5F\u8A31\u9019\u4E0D\u662F\u60A8\u60F3\u8981\u7684\u529F\u80FD\u3002
helppopup.playername.title = \u64A5\u653E\u5668\u540D\u7A31
-helppopup.playername.text = \u8B93\u4F60\u5E6B\u64AD\u653E\u5668\u6307\u5B9A\u4E00\u500B\u5BB9\u6613\u8A18\u4F4F\u7684\u540D\u5B57\uFF0C\u5982\u201C\u5DE5\u4F5C\u5BA4\u201D\u6216\u201C\u5BA2\u5EF3\u201D
+helppopup.playername.text = \u8B93\u60A8\u5E6B\u64AD\u653E\u5668\u6307\u5B9A\u4E00\u500B\u5BB9\u6613\u8A18\u4F4F\u7684\u540D\u5B57\uFF0C\u5982\u201C\u5DE5\u4F5C\u5BA4\u201D\u6216\u201C\u5BA2\u5EF3\u201D
helppopup.autocontrol.title = \u63A7\u5236\u64AD\u653E\u5668\u81EA\u52D5\u64AD\u653E
-helppopup.autocontrol.text = \u8A2D\u5B9A\u9019\u500B\u9078\u9805, {0} \u5728\u60A8\u958B\u59CB\u64AD\u653E\u6642\uFF0C\u6703\u81EA\u52D5\u555F\u52D5\u64AD\u653E\u5668\
- \u5426\u5247\u60A8\u5FC5\u9808\u81EA\u5DF1\u555F\u52D5\u4E26\u4E14\u9023\u63A5\u60A8\u7684\u64A5\u653E\u5668.
+helppopup.autocontrol.text = \u8A2D\u5B9A\u9019\u500B\u9078\u9805\uFF0C {0} \u5728\u60A8\u958B\u59CB\u64AD\u653E\u6642\uFF0C\u6703\u81EA\u52D5\u555F\u52D5\u64AD\u653E\u5668\
+ \u5426\u5247\u60A8\u5FC5\u9808\u81EA\u5DF1\u555F\u52D5\u4E26\u4E14\u9023\u63A5\u60A8\u7684\u64A5\u653E\u5668\u3002
helppopup.dynamicip.title = \u52D5\u614B IP \u4F4D\u5740
-helppopup.dynamicip.text = \u95DC\u9589\u6B64\u9078\u9805\uFF0C\u5982\u679C\u60A8\u4F7F\u7528\u975C\u614BIP\u4F4D\u5740.
+helppopup.dynamicip.text = \u95DC\u9589\u6B64\u9078\u9805\uFF0C\u5982\u679C\u60A8\u4F7F\u7528\u975C\u614BIP\u4F4D\u5740\u3002
+helppopup.smtpServer.title = SMTP \u4F3A\u670D\u5668
+helppopup.smtpServer.text = The hostname of the SMTP server. This server will be used to send e-mails to users \
+ who have requested a password reset.
+helppopup.smtpPort.title = SMTP Port
+helppopup.smtpPort.text = The server's port that should be connected to for SMTP traffic.
+helppopup.smtpCredentials.title = SMTP Credentials
+helppopup.smtpCredentials.text = The credentials to be used to connect to the SMTP server. Leave empty to connect without authentication.
+helppopup.smtpEncryption.title = SMTP Encryption
+helppopup.smtpEncryption.text = The encryption method to be used to connect to the SMTP server. Choose "None" for no encryption.
+helppopup.smtpFrom.title = From address
+helppopup.smtpFrom.text = The sender address for mails originating from the Libresonic server. Must be a valid e-mail address.
# wap/index.jsp
wap.index.missing = \u627E\u4E0D\u5230\u97F3\u6A02
-wap.index.playlist = \u9EDE\u64AD\u6E05\u55AE
+wap.index.playlist = \u64AD\u653E\u6E05\u55AE
wap.index.search = \u641C\u5C0B
wap.index.settings = \u8A2D\u5B9A
@@ -616,7 +848,7 @@ wap.browse.downloadone = \u4E0B\u8F09\u6B4C\u66F2
wap.browse.downloadall = \u5168\u90E8\u4E0B\u8F09
# wap/playlist.jsp
-wap.playlist.title =\u9EDE\u64AD\u6E05\u55AE
+wap.playlist.title = \u64AD\u653E\u6E05\u55AE
wap.playlist.noplayer = \u9023\u63A5\u4E0D\u5230\u64AD\u653E\u5668
wap.playlist.clear = \u6E05\u9664
wap.playlist.load = \u8F09\u5165
@@ -627,7 +859,7 @@ wap.playlist.play = \u5728\u96FB\u8A71\u4E2D\u64AD\u9001
wap.search.title = \u641C\u5C0B
# wap/searchResult.jsp
-wap.searchresult.index = \u6B63\u5728\u5EFA\u7ACB\u641C\u5C0B\u7D22\u5F15\u3002\u8ACB\u7A0D\u5F8C\u518D\u8A66.
+wap.searchresult.index = \u6B63\u5728\u5EFA\u7ACB\u641C\u5C0B\u7D22\u5F15\u3002\u8ACB\u7A0D\u5F8C\u518D\u8A66\u3002
# wap/settings.jsp
wap.settings.selectplayer = \u9078\u64C7\u64AD\u653E\u5668
diff --git a/libresonic-main/src/main/webapp/WEB-INF/applicationContext-cache.xml b/libresonic-main/src/main/webapp/WEB-INF/applicationContext-cache.xml
index da4c296a..3a33be97 100644
--- a/libresonic-main/src/main/webapp/WEB-INF/applicationContext-cache.xml
+++ b/libresonic-main/src/main/webapp/WEB-INF/applicationContext-cache.xml
@@ -2,7 +2,7 @@
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
diff --git a/libresonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml b/libresonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml
index ee7ab0ac..daa22901 100644
--- a/libresonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml
+++ b/libresonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml
@@ -2,7 +2,7 @@
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
diff --git a/libresonic-main/src/main/webapp/WEB-INF/applicationContext-sonos.xml b/libresonic-main/src/main/webapp/WEB-INF/applicationContext-sonos.xml
index ae2e9b60..b3157491 100644
--- a/libresonic-main/src/main/webapp/WEB-INF/applicationContext-sonos.xml
+++ b/libresonic-main/src/main/webapp/WEB-INF/applicationContext-sonos.xml
@@ -2,7 +2,7 @@
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
diff --git a/libresonic-main/src/main/webapp/WEB-INF/jsp/albumMain.jsp b/libresonic-main/src/main/webapp/WEB-INF/jsp/albumMain.jsp
index 19fd2f79..429275b5 100644
--- a/libresonic-main/src/main/webapp/WEB-INF/jsp/albumMain.jsp
+++ b/libresonic-main/src/main/webapp/WEB-INF/jsp/albumMain.jsp
@@ -481,6 +481,7 @@
+
diff --git a/libresonic-main/src/main/webapp/WEB-INF/jsp/artistMain.jsp b/libresonic-main/src/main/webapp/WEB-INF/jsp/artistMain.jsp
index c7290c15..f843dac0 100644
--- a/libresonic-main/src/main/webapp/WEB-INF/jsp/artistMain.jsp
+++ b/libresonic-main/src/main/webapp/WEB-INF/jsp/artistMain.jsp
@@ -273,6 +273,7 @@
+
diff --git a/libresonic-main/src/main/webapp/WEB-INF/jsp/coverArt.jsp b/libresonic-main/src/main/webapp/WEB-INF/jsp/coverArt.jsp
index c4242ecd..8d9eee77 100644
--- a/libresonic-main/src/main/webapp/WEB-INF/jsp/coverArt.jsp
+++ b/libresonic-main/src/main/webapp/WEB-INF/jsp/coverArt.jsp
@@ -15,6 +15,7 @@ PARAMETERS
showZoom: Whether to display a link for zooming the cover art.
showChange: Whether to display a link for changing the cover art.
appearAfter: Fade in after this many milliseconds, or nil if no fading in should happen.
+ hideOverflow: Hide cover art overflow when height is greater than width
--%>
@@ -32,7 +33,7 @@ PARAMETERS
-
+
overflow:hidden;" title="${param.caption1}" id="${divId}">
diff --git a/libresonic-main/src/main/webapp/WEB-INF/jsp/home.jsp b/libresonic-main/src/main/webapp/WEB-INF/jsp/home.jsp
index 124d16a3..38040f27 100644
--- a/libresonic-main/src/main/webapp/WEB-INF/jsp/home.jsp
+++ b/libresonic-main/src/main/webapp/WEB-INF/jsp/home.jsp
@@ -7,7 +7,9 @@