forked from Archives/Athou_commafeed
i18n implementation (#55)
This commit is contained in:
1
pom.xml
1
pom.xml
@@ -86,6 +86,7 @@
|
||||
<extension>.class</extension>
|
||||
</extensions>
|
||||
<updateOnlyExtensions>
|
||||
<updateOnlyExtension>.properties</updateOnlyExtension>
|
||||
<updateOnlyExtension>.html</updateOnlyExtension>
|
||||
<updateOnlyExtension>.js</updateOnlyExtension>
|
||||
<updateOnlyExtension>.css</updateOnlyExtension>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package com.commafeed.backend;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -14,6 +18,7 @@ import javax.ejb.Startup;
|
||||
import javax.enterprise.inject.Instance;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.mutable.MutableBoolean;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -27,6 +32,7 @@ import com.commafeed.backend.model.ApplicationSettings;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.backend.services.UserService;
|
||||
import com.google.api.client.util.Maps;
|
||||
|
||||
@Startup
|
||||
@Singleton
|
||||
@@ -59,6 +65,7 @@ public class StartupBean {
|
||||
Instance<FeedRefreshWorker> workers;
|
||||
|
||||
private long startupTime;
|
||||
private Map<String, String> supportedLanguages = Maps.newHashMap();
|
||||
|
||||
private ExecutorService executor;
|
||||
private MutableBoolean running = new MutableBoolean(true);
|
||||
@@ -70,6 +77,8 @@ public class StartupBean {
|
||||
initialData();
|
||||
}
|
||||
|
||||
initSupportedLanguages();
|
||||
|
||||
ApplicationSettings settings = applicationSettingsService.get();
|
||||
int threads = settings.getBackgroundThreads();
|
||||
log.info("Starting {} background threads", threads);
|
||||
@@ -88,13 +97,30 @@ public class StartupBean {
|
||||
|
||||
}
|
||||
|
||||
private void initSupportedLanguages() {
|
||||
Properties props = new Properties();
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = getClass().getResourceAsStream("/i18n/languages.properties");
|
||||
props.load(new InputStreamReader(is, "UTF-8"));
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
for (Object key : props.keySet()) {
|
||||
supportedLanguages.put(key.toString(),
|
||||
props.getProperty(key.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
private void initialData() {
|
||||
log.info("Populating database with default values");
|
||||
|
||||
|
||||
ApplicationSettings settings = new ApplicationSettings();
|
||||
settings.setAnnouncement("Set the Public URL in the admin section !");
|
||||
applicationSettingsService.save(settings);
|
||||
|
||||
|
||||
userService.register(USERNAME_ADMIN, "admin",
|
||||
Arrays.asList(Role.ADMIN, Role.USER));
|
||||
userService.register(USERNAME_DEMO, "demo", Arrays.asList(Role.USER));
|
||||
@@ -104,6 +130,10 @@ public class StartupBean {
|
||||
return startupTime;
|
||||
}
|
||||
|
||||
public Map<String, String> getSupportedLanguages() {
|
||||
return supportedLanguages;
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void shutdown() {
|
||||
running.setValue(false);
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.commafeed.frontend.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import com.google.api.client.util.Maps;
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@@ -15,6 +17,7 @@ import com.wordnik.swagger.annotations.ApiClass;
|
||||
public class ServerInfo implements Serializable {
|
||||
|
||||
private String announcement;
|
||||
private Map<String, String> supportedLanguages = Maps.newHashMap();
|
||||
|
||||
public String getAnnouncement() {
|
||||
return announcement;
|
||||
@@ -24,4 +27,12 @@ public class ServerInfo implements Serializable {
|
||||
this.announcement = announcement;
|
||||
}
|
||||
|
||||
public Map<String, String> getSupportedLanguages() {
|
||||
return supportedLanguages;
|
||||
}
|
||||
|
||||
public void setSupportedLanguages(Map<String, String> supportedLanguages) {
|
||||
this.supportedLanguages = supportedLanguages;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.apache.wicket.request.cycle.RequestCycle;
|
||||
import org.apache.wicket.util.crypt.Base64;
|
||||
|
||||
import com.commafeed.backend.MetricsBean;
|
||||
import com.commafeed.backend.StartupBean;
|
||||
import com.commafeed.backend.dao.FeedCategoryDAO;
|
||||
import com.commafeed.backend.dao.FeedDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryDAO;
|
||||
@@ -89,6 +90,9 @@ public abstract class AbstractREST {
|
||||
@Inject
|
||||
UserService userService;
|
||||
|
||||
@Inject
|
||||
StartupBean startupBean;
|
||||
|
||||
@Inject
|
||||
UserSettingsDAO userSettingsDAO;
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ public class ServerREST extends AbstractResourceREST {
|
||||
ServerInfo infos = new ServerInfo();
|
||||
infos.setAnnouncement(applicationSettingsService.get()
|
||||
.getAnnouncement());
|
||||
infos.getSupportedLanguages().putAll(
|
||||
startupBean.getSupportedLanguages());
|
||||
return infos;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,10 @@ public class UserREST extends AbstractResourceREST {
|
||||
public Response saveSettings(@ApiParam Settings settings) {
|
||||
Preconditions.checkNotNull(settings);
|
||||
|
||||
if (startupBean.getSupportedLanguages().get(settings.getLanguage()) == null) {
|
||||
settings.setLanguage("en");
|
||||
}
|
||||
|
||||
UserSettings s = userSettingsDAO.findByUser(getUser());
|
||||
if (s == null) {
|
||||
s = new UserSettings();
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.commafeed.frontend.utils;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -67,9 +68,10 @@ public class InternationalizationDevelopmentFilter implements Filter {
|
||||
String lang = settings.getLanguage() == null ? "en" : settings
|
||||
.getLanguage();
|
||||
|
||||
byte[] bytes = translate(wrapper.toString(), lang).getBytes();
|
||||
response.getOutputStream().write(bytes);
|
||||
byte[] bytes = translate(wrapper.toString(), lang).getBytes("UTF-8");
|
||||
response.setContentLength(bytes.length);
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.getOutputStream().write(bytes);
|
||||
response.getOutputStream().close();
|
||||
|
||||
}
|
||||
@@ -80,7 +82,7 @@ public class InternationalizationDevelopmentFilter implements Filter {
|
||||
try {
|
||||
is = getClass()
|
||||
.getResourceAsStream("/i18n/" + lang + ".properties");
|
||||
props.load(is);
|
||||
props.load(new InputStreamReader(is, "UTF-8"));
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} finally {
|
||||
@@ -98,7 +100,9 @@ public class InternationalizationDevelopmentFilter implements Filter {
|
||||
while (m.find()) {
|
||||
String var = m.group(1);
|
||||
Object replacement = props.get(var);
|
||||
m.appendReplacement(sb, replacement.toString());
|
||||
String replacementValue = replacement == null ? var : replacement
|
||||
.toString();
|
||||
m.appendReplacement(sb, replacementValue);
|
||||
}
|
||||
m.appendTail(sb);
|
||||
return sb.toString();
|
||||
|
||||
@@ -1 +1,88 @@
|
||||
toolbar.refresh=Refresh
|
||||
global.save=Save
|
||||
global.cancel=Cancel
|
||||
global.delete=Delete
|
||||
global.required=Required
|
||||
|
||||
tree.subscribe=Subscribe
|
||||
tree.import=Import
|
||||
tree.new_category=New category
|
||||
tree.all=All
|
||||
tree.starred=Starred
|
||||
|
||||
subscribe.feed_url=Feed URL
|
||||
subscribe.feed_name=Feed Name
|
||||
subscribe.category=Category
|
||||
|
||||
import.google_reader_prefix=Let me import your feeds from your
|
||||
import.google_reader_suffix= account.
|
||||
import.google_download=Alternatively, upload your subscriptions.xml file.
|
||||
import.google_download_link=Download it from here.
|
||||
import.xml_file=XML File
|
||||
|
||||
new_category.name=Name
|
||||
new_category.parent=Parent
|
||||
|
||||
toolbar.unread=Unread
|
||||
toolbar.all=All
|
||||
toolbar.refresh=Refresh
|
||||
toolbar.mark_all_as_read=Mark all as read
|
||||
toolbar.settings=Settings
|
||||
toolbar.profile=Profile
|
||||
toolbar.admin=Admin
|
||||
toolbar.about=About
|
||||
toolbar.logout=Logout
|
||||
toolbar.donate=Donate
|
||||
|
||||
view.error_while_loading_feed=Error while loading this feed
|
||||
view.keep_unread=Keep unread
|
||||
view.no_unread_items=has no unread items.
|
||||
|
||||
settings.general=General
|
||||
settings.general.language=Language
|
||||
settings.general.show_unread=Show feeds and categories with no unread entries
|
||||
settings.general.social_buttons=Show social sharing buttons
|
||||
settings.general.scroll_marks=In expanded view, scrolling through entries mark them as read
|
||||
settings.custom_css=Custom CSS
|
||||
|
||||
details.feed_details=Feed details
|
||||
details.url=URL
|
||||
details.name=Name
|
||||
details.category=Category
|
||||
details.last_refresh=Last refresh
|
||||
details.feed_url=Feed URL
|
||||
details.generate_api_key_first=Generate an API key in your profile first.
|
||||
details.unsubscribe=Unsubscribe
|
||||
details.category_details=Category details
|
||||
details.parent_category=Parent category
|
||||
|
||||
profile.user_name=User name
|
||||
profile.email=E-mail
|
||||
profile.change_password=Change password
|
||||
profile.confirm_password=Confirm password
|
||||
profile.minimum_6_chars=Minimum 6 characters
|
||||
profile.passwords_do_not_match=Passwords do not match
|
||||
profile.api_key=API key
|
||||
profile.api_key_not_generated=Not generated yet
|
||||
profile.generate_new_api_key=Generate new API key
|
||||
profile.generate_new_api_key_info=Changing password will generate a new API key
|
||||
profile.delete_account=Delete account
|
||||
|
||||
about.rest_api=REST API
|
||||
about.keyboard_shortcuts=Keyboard shortcuts
|
||||
about.line1_prefix=CommaFeed is an open-source project. Sources are hosted on
|
||||
about.line1_suffix=.
|
||||
about.line2_prefix=If you encounter an issue, please report it on the issues page of the
|
||||
about.line2_suffix= project.
|
||||
about.line3=If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online.
|
||||
about.rest_api.line1=CommaFeed is built on top of JAX-RS and AngularJS. As such, a REST API is available.
|
||||
about.rest_api.link_to_documentation=Link to the documentation.
|
||||
|
||||
about.shortcuts.mouse_middleclick=mouse middleclick
|
||||
about.shortcuts.open_next_entry=open next entry
|
||||
about.shortcuts.open_previous_entry=open previous entry
|
||||
about.shortcuts.open_close_current_entry=open/close current entry
|
||||
about.shortcuts.open_current_entry_in_new_window=open current entry in a new window
|
||||
about.shortcuts.star_unstar=star/unstar current entry
|
||||
about.shortcuts.mark_current_entry=mark as read/unread current entry
|
||||
about.shortcuts.mark_all_as_read=mark all entries as read
|
||||
about.shortcuts.open_in_new_tab_mark_as_read=open entry in new tab and mark as read
|
||||
@@ -1 +1,88 @@
|
||||
toolbar.refresh=Rafraichir
|
||||
global.save=Enregistrer
|
||||
global.cancel=Annuler
|
||||
global.delete=Effacer
|
||||
global.required=Obligatoire
|
||||
|
||||
tree.subscribe=S'abonner
|
||||
tree.import=Importer
|
||||
tree.new_category=Nouvelle catégorie
|
||||
tree.all=Tous
|
||||
tree.starred=Etoiles
|
||||
|
||||
subscribe.feed_url=URL du flux
|
||||
subscribe.feed_name=Nom du flux
|
||||
subscribe.category=Catégorie
|
||||
|
||||
import.google_reader_prefix=Laissez-moi importer vos flux depuis votre compte
|
||||
import.google_reader_suffix=.
|
||||
import.google_download=Ou alors, téléchargez votre fichier subscriptions.xml.
|
||||
import.google_download_link=Récuperez-le ici.
|
||||
import.xml_file=Fichier XML
|
||||
|
||||
new_category.name=Nom
|
||||
new_category.parent=Parent
|
||||
|
||||
toolbar.unread=Non-lus
|
||||
toolbar.all=Tous
|
||||
toolbar.refresh=Rafraîchir
|
||||
toolbar.mark_all_as_read=Tout marquer comme lu
|
||||
toolbar.settings=Préférences
|
||||
toolbar.profile=Profil
|
||||
toolbar.admin=Administration
|
||||
toolbar.about=A propos
|
||||
toolbar.logout=Déconnexion
|
||||
toolbar.donate=Faire un don
|
||||
|
||||
view.error_while_loading_feed=Erreur durant le chargement de ce flux
|
||||
view.keep_unread=Garder non-lu
|
||||
view.no_unread_items=n'a pas d'entrées non-lues.
|
||||
|
||||
settings.general=Général
|
||||
settings.general.language=Langue
|
||||
settings.general.show_unread=Afficher les flux et les catégories pour lesquels tout est déjà lu
|
||||
settings.general.social_buttons=Afficher les boutons de partage sur réseaux sociaux
|
||||
settings.general.scroll_marks=En mode de lecture étendu, marquer comme lu les éléments lorsque la fenêtre descend.
|
||||
settings.custom_css=CSS personnelle
|
||||
|
||||
details.feed_details=Détails du flux
|
||||
details.url=URL
|
||||
details.name=Nom
|
||||
details.category=Catégorie
|
||||
details.last_refresh=Dernière mise à jour
|
||||
details.feed_url=URL du flux
|
||||
details.generate_api_key_first=Génerez une clé API dans votre profil d'abord.
|
||||
details.unsubscribe=Se désabonner
|
||||
details.category_details=Détails de la catégorie
|
||||
details.parent_category=Catégorie parente
|
||||
|
||||
profile.user_name=Nom
|
||||
profile.email=E-mail
|
||||
profile.change_password=Changer de mot de passe
|
||||
profile.confirm_password=Confirmer le mot de passe
|
||||
profile.minimum_6_chars=Minimum 6 caractères
|
||||
profile.passwords_do_not_match=Les mots de passe ne correspondent pas
|
||||
profile.api_key=Clé API
|
||||
profile.api_key_not_generated=Pas encore générée
|
||||
profile.generate_new_api_key=Générer une nouvelle clé API
|
||||
profile.generate_new_api_key_info=Changer de password va générer une nouvelle clé API
|
||||
profile.delete_account=Effacer le compte
|
||||
|
||||
about.rest_api=API REST
|
||||
about.keyboard_shortcuts=Raccourcis clavier
|
||||
about.line1_prefix=CommaFeed est un projet open-source. Les sources sont disponibles sur
|
||||
about.line1_suffix=.
|
||||
about.line2_prefix=Si vous rencontrez un problème, rapportez-le sur la page du projet sur
|
||||
about.line2_suffix=.
|
||||
about.line3=Si vous aimez ce projet, n'hésitez pas à faire un don pour encourager le développeur et aider à couvrir les coûts d'hébergement de la plate-forme.
|
||||
about.rest_api.line1=CommaFeed utilise JAX-RS et AngularJS et une API REST est donc disponible.
|
||||
about.rest_api.link_to_documentation=Lien vers la documentation.
|
||||
|
||||
about.shortcuts.mouse_middleclick=click du milieu de la souris
|
||||
about.shortcuts.open_next_entry=ouvrir l'entrée suivante
|
||||
about.shortcuts.open_previous_entry=ouvrir l'entrée précédente
|
||||
about.shortcuts.open_close_current_entry=ouvrir/fermer l'entrée courante
|
||||
about.shortcuts.open_current_entry_in_new_window=ouvrir l'entrée courrnte dans une nouvelle fenêtre
|
||||
about.shortcuts.star_unstar=Marquer/enlever l'étoile de l'entrée courante
|
||||
about.shortcuts.mark_current_entry=Marquer comme lue/non-lue l'entrée cour-ante
|
||||
about.shortcuts.mark_all_as_read=Marquer toutes les entrées comme lues
|
||||
about.shortcuts.open_in_new_tab_mark_as_read=ouvrir l'entrée courante dans une nouvelle fenêtre et marquer comme lue
|
||||
2
src/main/resources/i18n/languages.properties
Normal file
2
src/main/resources/i18n/languages.properties
Normal file
@@ -0,0 +1,2 @@
|
||||
en=English
|
||||
fr=Français
|
||||
@@ -28,13 +28,13 @@ public class HTMLConcat {
|
||||
}
|
||||
sb.append("</div>");
|
||||
String dest = destination.substring(0, destination.lastIndexOf(".")) + "." + i18n.getName().split("\\.")[0] + ".html";
|
||||
FileUtils.writeStringToFile(new File(dest), sb.toString());
|
||||
FileUtils.writeStringToFile(new File(dest), sb.toString(), "UTF-8");
|
||||
}
|
||||
}
|
||||
|
||||
public String translate(String content, File i18n) {
|
||||
Properties props = new Properties();
|
||||
props.load(new FileInputStream(i18n));
|
||||
props.load(new InputStreamReader(new FileInputStream(i18n), "UTF-8"));
|
||||
return replace(content, props);
|
||||
}
|
||||
|
||||
|
||||
@@ -793,19 +793,12 @@ function($scope, $state, $stateParams, $dialog, AdminUsersService) {
|
||||
};
|
||||
}]);
|
||||
|
||||
module.controller('SettingsCtrl', ['$scope', '$location', 'SettingsService', 'AnalyticsService',
|
||||
function($scope, $location, SettingsService, AnalyticsService) {
|
||||
module.controller('SettingsCtrl', ['$scope', '$location', 'SettingsService', 'AnalyticsService', 'ServerService',
|
||||
function($scope, $location, SettingsService, AnalyticsService, ServerService) {
|
||||
|
||||
AnalyticsService.track();
|
||||
|
||||
|
||||
$scope.languages = [ {
|
||||
id : 'en',
|
||||
label : 'English'
|
||||
}, {
|
||||
id : 'fr',
|
||||
label : 'Français'
|
||||
} ];
|
||||
$scope.ServerService = ServerService.get();
|
||||
|
||||
$scope.settingsService = SettingsService;
|
||||
$scope.$watch('settingsService.settings', function(value) {
|
||||
|
||||
@@ -34,6 +34,7 @@ module.factory('SettingsService', ['$resource', function($resource) {
|
||||
s.init = function(callback) {
|
||||
res.get(function(data) {
|
||||
s.settings = data;
|
||||
moment.lang(s.settings.language || 'en');
|
||||
if (callback) {
|
||||
callback(data);
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt>k</dt>
|
||||
<dd>open next entry</dd>
|
||||
<dd>${about.shortcuts.open_next_entry}</dd>
|
||||
|
||||
<dt>j</dt>
|
||||
<dd>open previous entry</dd>
|
||||
<dd>${about.shortcuts.open_previous_entry}</dd>
|
||||
|
||||
<dt>o, enter</dt>
|
||||
<dd>open/close current entry</dd>
|
||||
<dd>${about.shortcuts.open_close_current_entry}</dd>
|
||||
|
||||
<dt>v</dt>
|
||||
<dd>open current entry in a new window</dd>
|
||||
<dd>${about.shortcuts.open_current_entry_in_new_window}</dd>
|
||||
|
||||
<dt>s</dt>
|
||||
<dd>star/unstar current entry</dd>
|
||||
<dd>${about.shortcuts.star_unstar}</dd>
|
||||
|
||||
<dt>m</dt>
|
||||
<dd>mark as read/unread current entry</dd>
|
||||
<dd>${about.shortcuts.mark_current_entry}</dd>
|
||||
|
||||
<dt>shift+a</dt>
|
||||
<dd>mark all entries as read</dd>
|
||||
<dd>${about.shortcuts.mark_all_as_read}</dd>
|
||||
|
||||
<dt>mouse middleclick</dt>
|
||||
<dd>open entry in new tab and mark as read</dd>
|
||||
<dt>${about.shortcuts.mouse_middleclick}</dt>
|
||||
<dd>${about.shortcuts.open_in_new_tab_mark_as_read}</dd>
|
||||
</dl>
|
||||
@@ -1,109 +1,109 @@
|
||||
<div ng-controller="SubscribeCtrl">
|
||||
<div class="btn-group">
|
||||
<button class="btn" ng-click="open()"><span class="icon-rss"></span> Subscribe</button>
|
||||
<button class="btn" ng-click="open()"><span class="icon-rss"></span> ${tree.subscribe}</button>
|
||||
<button class="btn dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a ng-click="openImport()"><i class="icon-arrow-down"></i> Import</a></li>
|
||||
<li><a ng-click="openCategory()"><i class="icon-plus"></i> Add a category</a></li>
|
||||
<li><a ng-click="openImport()"><i class="icon-arrow-down"></i> ${tree.import}</a></li>
|
||||
<li><a ng-click="openCategory()"><i class="icon-plus"></i> ${tree.new_category}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div modal="isOpen" close="close()" options="opts">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" ng-click="close()">×</button>
|
||||
<h4>Subscribe</h4>
|
||||
<h4>${tree.subscribe}</h4>
|
||||
</div>
|
||||
<form name="subscribeForm" class="form-horizontal" ng-submit="save()">
|
||||
<div class="modal-body">
|
||||
<div class="control-group" ng-class="{error : !subscribeForm.url.$valid}">
|
||||
<label class="control-label">Feed URL</label>
|
||||
<label class="control-label">${subscribe.feed_url}</label>
|
||||
<div class="controls">
|
||||
<input type="text" name="url" ng-model="sub.url" ng-blur="urlChanged()" placeholder="http://example.com/feed"
|
||||
class="input-block-level" required ng-disabled="state=='loading'"></input>
|
||||
<span class="help-block" ng-show="!subscribeForm.url.$valid">Required</span>
|
||||
<span class="help-block" ng-show="!subscribeForm.url.$valid">${global.required}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" ng-class="{error : !subscribeForm.title.$valid}">
|
||||
<label class="control-label">Feed Name</label>
|
||||
<label class="control-label">${subscribe.feed_name}</label>
|
||||
<div class="controls">
|
||||
<input type="text" name="title" ng-model="sub.title"
|
||||
class="input-block-level" required ng-disabled="state=='loading'"></input>
|
||||
<span class="help-block" ng-show="!subscribeForm.title.$valid">Required</span>
|
||||
<span class="help-block" ng-show="!subscribeForm.title.$valid">${global.required}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" ng-class="{error : !subscribeForm.category.$valid}">
|
||||
<label class="control-label">Category</label>
|
||||
<label class="control-label">${subscribe.category}</label>
|
||||
<div class="controls">
|
||||
<select name="category" ng-model="sub.categoryId" class="input-block-level"
|
||||
ng-options="cat.id as cat.name for cat in CategoryService.flatCategories" required>
|
||||
</select>
|
||||
<span class="help-block" ng-show="!subscribeForm.category.$valid">Required</span>
|
||||
<span class="help-block" ng-show="!subscribeForm.category.$valid">${global.required}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn cancel" ng-click="close()" type="button">Cancel</button>
|
||||
<button class="btn btn-primary ok" type="submit" ng-disabled="state!='ok'">Save</button>
|
||||
<button class="btn cancel" ng-click="close()" type="button">${global.cancel}</button>
|
||||
<button class="btn btn-primary ok" type="submit" ng-disabled="state!='ok'">${global.save}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div modal="isOpenImport" close="closeImport()" options="opts">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" ng-click="closeImport()">×</button>
|
||||
<h4>Import</h4>
|
||||
<h4>${tree.import}</h4>
|
||||
</div>
|
||||
<form ng-upload class="form-horizontal" action="rest/feed/import">
|
||||
<div class="modal-body">
|
||||
<div class="control-group">
|
||||
<div>Let me import your feeds from your
|
||||
<div>${import.google_reader_prefix}
|
||||
<a href="google/import/redirect">
|
||||
<img src="images/google_reader_icon.png" class="favicon" />
|
||||
Google Reader account
|
||||
</a>.
|
||||
Google Reader
|
||||
</a>${import.google_reader_suffix}
|
||||
</div>
|
||||
<div>Alternatively, upload your subscriptions.xml file (download it from <a target="_blank" href="https://www.google.com/reader/subscriptions/export">here)</a>.</div>
|
||||
<div>${import.google_download} <a target="_blank" href="https://www.google.com/reader/subscriptions/export">${import.google_download_link}</a></div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">XML File</label>
|
||||
<label class="control-label">${import.xml_file}</label>
|
||||
<div class="controls">
|
||||
<input type="file" name="file"></input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn cancel" ng-click="closeImport()">Cancel</button>
|
||||
<button class="btn btn-primary ok" type="submit" upload-submit="uploadComplete(contents, completed)">Import</button>
|
||||
<button type="button" class="btn cancel" ng-click="closeImport()">${global.cancel}</button>
|
||||
<button class="btn btn-primary ok" type="submit" upload-submit="uploadComplete(contents, completed)">${tree.import}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div modal="isOpenCategory" close="closeCategory()" options="opts">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" ng-click="closeCategory()">×</button>
|
||||
<h4>New category</h4>
|
||||
<h4>${tree.new_category}</h4>
|
||||
</div>
|
||||
<form name="categoryForm" class="form-horizontal" ng-submit="saveCategory()">
|
||||
<div class="modal-body">
|
||||
<div class="control-group" ng-class="{error : !categoryForm.name.$valid}">
|
||||
<label class="control-label">Name</label>
|
||||
<label class="control-label">${new_category.name}</label>
|
||||
<div class="controls">
|
||||
<input type="text" name="name" ng-model="cat.name" required></input>
|
||||
<span class="help-block" ng-show="!categoryForm.name.$valid">Required</span>
|
||||
<span class="help-block" ng-show="!categoryForm.name.$valid">${global.required}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" ng-class="{error : !categoryForm.category.$valid}">
|
||||
<label class="control-label">Parent</label>
|
||||
<label class="control-label">${new_category.parent}</label>
|
||||
<div class="controls">
|
||||
<select name="category" ng-model="cat.parentId" class="input-block-level"
|
||||
ng-options="cat.id as cat.name for cat in CategoryService.flatCategories"required>
|
||||
</select>
|
||||
<span class="help-block" ng-show="!categoryForm.category.$valid">Required</span>
|
||||
<span class="help-block" ng-show="!categoryForm.category.$valid">${global.required}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn cancel" ng-click="closeCategory()">Cancel</button>
|
||||
<button class="btn btn-primary ok" type="submit">Save</button>
|
||||
<button type="button" class="btn cancel" ng-click="closeCategory()">${global.cancel}</button>
|
||||
<button class="btn btn-primary ok" type="submit">${global.save}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<div class="form-horizontal">
|
||||
<span>
|
||||
<div class="btn-group read-mode" data-toggle="buttons-radio">
|
||||
<button type="button" class="btn" ng-model="settingsService.settings.readingMode" btn-radio="'unread'">Unread</button>
|
||||
<button type="button" class="btn" ng-model="settingsService.settings.readingMode" btn-radio="'all'">All</button>
|
||||
<button type="button" class="btn" ng-model="settingsService.settings.readingMode" btn-radio="'unread'">${toolbar.unread}</button>
|
||||
<button type="button" class="btn" ng-model="settingsService.settings.readingMode" btn-radio="'all'">${toolbar.all}</button>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn" ng-click="toggleOrder()">
|
||||
@@ -16,19 +16,19 @@
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn" ng-click="refresh()"><i class="icon-refresh"></i> ${toolbar.refresh}</button>
|
||||
<button type="button" class="btn" ng-click="markAllAsRead()"><i class="icon-ok"></i> Mark all as read</button>
|
||||
<button type="button" class="btn" ng-click="markAllAsRead()"><i class="icon-ok"></i> ${toolbar.mark_all_as_read}</button>
|
||||
|
||||
<div class="btn-group">
|
||||
<a class="btn" ng-click="toSettings()"><i class="icon-cog"></i> Settings</a>
|
||||
<a class="btn" ng-click="toSettings()"><i class="icon-cog"></i> ${toolbar.settings}</a>
|
||||
<button class="btn dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu pull-right">
|
||||
<li><a ng-click="toProfile()"><i class="icon-user"></i> Profile</a></li>
|
||||
<li ng-show="session.admin"><a ng-click="toAdmin()"><i class="icon-edit"></i> Admin</a></li>
|
||||
<li><a ng-click="toProfile()"><i class="icon-user"></i> ${toolbar.profile}</a></li>
|
||||
<li ng-show="session.admin"><a ng-click="toAdmin()"><i class="icon-edit"></i> ${toolbar.admin}</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a ng-click="toHelp()"><i class="icon-question-sign"></i> About</a></li>
|
||||
<li><a href="logout"><i class="icon-off"></i> Logout</a></li>
|
||||
<li><a ng-click="toHelp()"><i class="icon-question-sign"></i> ${toolbar.about}</a></li>
|
||||
<li><a href="logout"><i class="icon-off"></i> ${toolbar.logout}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</span>
|
||||
@@ -37,7 +37,7 @@
|
||||
<button class="btn" type="submit"><i class="icon-search"></i></button>
|
||||
</form>
|
||||
<div class="donate">
|
||||
<button class="btn btn-success" type="button" ng-click="toDonate()">Donate</button>
|
||||
<button class="btn btn-success" type="button" ng-click="toDonate()">${toolbar.donate}</button>
|
||||
</div>
|
||||
<div spinner shown="loading"></div>
|
||||
<span>{{ServerService.announcement}}</span>
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
<div>
|
||||
<div class="page-header">
|
||||
<h3>Category details</h3>
|
||||
<h3>${details.category_details}</h3>
|
||||
</div>
|
||||
<form name="form" class="form-horizontal" ng-submit="save()">
|
||||
<div class="control-group" ng-class="{error : !form.name.$valid}" ui-if="!isMeta()">
|
||||
<label class="control-label">Name</label>
|
||||
<label class="control-label">${details.name}</label>
|
||||
<div class="controls">
|
||||
<input type="text" name="name" ng-model="category.name" class="input-block-level" required></input>
|
||||
<span class="help-block" ng-show="!form.name.$valid">Required</span>
|
||||
<span class="help-block" ng-show="!form.name.$valid">${global.required}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-class="{error : !form.category.$valid}" ui-if="!isMeta()">
|
||||
<label class="control-label">Parent category</label>
|
||||
<label class="control-label">${details.parent_category}</label>
|
||||
<div class="controls">
|
||||
<select name="category" class="input-block-level" ng-model="category.parentId"
|
||||
ng-options="cat.id as cat.name for cat in CategoryService.flatCategories | filter: filterCurrent">
|
||||
</select>
|
||||
<span class="help-block" ng-show="!form.category.$valid">Required</span>
|
||||
<span class="help-block" ng-show="!form.category.$valid">${global.required}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Feed URL</label>
|
||||
<label class="control-label">${details.feed_url}</label>
|
||||
<div class="controls horizontal-align">
|
||||
<a ng-show="user.apiKey" href="{{'rest/category/entriesAsFeed?id=' + category.id + '&apiKey=' + user.apiKey}}" target="_blank">link</a>
|
||||
<span ng-show="!user.apiKey">Generate an API key in your profile first.</span>
|
||||
<span ng-show="!user.apiKey">${details.generate_api_key_first}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary" ui-if="!isMeta()">Save</button>
|
||||
<button type="button" class="btn" ng-click="back()">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="deleteCategory()" ui-if="!isMeta()">Delete</button>
|
||||
<button type="submit" class="btn btn-primary" ui-if="!isMeta()">${global.save}</button>
|
||||
<button type="button" class="btn" ng-click="back()">${global.cancel}</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="deleteCategory()" ui-if="!isMeta()">${global.delete}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
<div>
|
||||
<div class="page-header">
|
||||
<h3>Feed details</h3>
|
||||
<h3>${details.feed_details}</h3>
|
||||
</div>
|
||||
<form name="form" class="form-horizontal" ng-submit="save()">
|
||||
<div class="control-group">
|
||||
<label class="control-label">URL</label>
|
||||
<label class="control-label">${details.url}</label>
|
||||
<div class="controls horizontal-align">
|
||||
<a href="{{sub.feedUrl}}" target="_blank">{{sub.feedUrl}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" ng-class="{error : !form.name.$valid}">
|
||||
<label class="control-label">Name</label>
|
||||
<label class="control-label">${details.name}</label>
|
||||
<div class="controls">
|
||||
<input type="text" name="name" ng-model="sub.name" class="input-block-level" required></input>
|
||||
<span class="help-block" ng-show="!form.name.$valid">Required</span>
|
||||
<span class="help-block" ng-show="!form.name.$valid">${global.required}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-class="{error : !form.category.$valid}">
|
||||
<label class="control-label">Category</label>
|
||||
<label class="control-label">${details.category}</label>
|
||||
<div class="controls">
|
||||
<select name="category" class="input-block-level" ng-model="sub.categoryId"
|
||||
ng-options="cat.id as cat.name for cat in CategoryService.flatCategories">
|
||||
</select>
|
||||
<span class="help-block" ng-show="!form.category.$valid">Required</span>
|
||||
<span class="help-block" ng-show="!form.category.$valid">${global.required}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Last refresh</label>
|
||||
<label class="control-label">${details.last_refresh}</label>
|
||||
<div class="controls horizontal-align">
|
||||
<span>{{sub.lastRefresh|entryDate}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Feed URL</label>
|
||||
<label class="control-label">${details.feed_url}</label>
|
||||
<div class="controls horizontal-align">
|
||||
<a ng-show="user.apiKey" href="{{'rest/feed/entriesAsFeed?id=' + sub.id + '&apiKey=' + user.apiKey}}" target="_blank">link</a>
|
||||
<span ng-show="!user.apiKey">Generate an API key in your profile first.</span>
|
||||
<span ng-show="!user.apiKey">${details.generate_api_key_first}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
<button type="button" class="btn" ng-click="back()">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="unsubscribe()">Unsubscribe</button>
|
||||
<button type="submit" class="btn btn-primary">${global.save}</button>
|
||||
<button type="button" class="btn" ng-click="back()">${global.cancel}</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="unsubscribe()">${details.unsubscribe}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@@ -2,28 +2,28 @@
|
||||
<div class="span2">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<li class="active">
|
||||
<a href="#about" data-toggle="pill">About</a>
|
||||
<a href="#about" data-toggle="pill">${toolbar.about}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#api" data-toggle="pill">REST API</a>
|
||||
<a href="#api" data-toggle="pill">${about.rest_api}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#shortcuts" data-toggle="pill">Keyboard shortcuts</a>
|
||||
<a href="#shortcuts" data-toggle="pill">${about.keyboard_shortcuts}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span10">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="about">
|
||||
<h3>About</h3>
|
||||
<h3>${toolbar.about}</h3>
|
||||
<p>
|
||||
CommaFeed is an open-source project. Sources are hosted on <a href="https://github.com/Athou/commafeed" target="_blank">GitHub</a>.
|
||||
${about.line1_prefix} <a href="https://github.com/Athou/commafeed" target="_blank">GitHub</a> ${about.line1_suffix}
|
||||
</p>
|
||||
<p>
|
||||
If you encounter an issue, please report it on the <a href="https://github.com/Athou/commafeed/issues" target="_blank">issues page</a> of the GitHub project.
|
||||
${about.line2_prefix} <a href="https://github.com/Athou/commafeed/issues" target="_blank">GitHub</a> ${about.line2_suffix}
|
||||
</p>
|
||||
<p>
|
||||
If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online.
|
||||
${about.line3}
|
||||
</p>
|
||||
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
|
||||
<input type="hidden" name="cmd" value="_s-xclick">
|
||||
@@ -35,16 +35,16 @@
|
||||
|
||||
</div>
|
||||
<div class="tab-pane" id="api">
|
||||
<h3>REST API</h3>
|
||||
<h3>${about.rest_api}</h3>
|
||||
<p>
|
||||
CommaFeed is built on top of JAX-RS and AngularJS. As such, a REST API is available.
|
||||
${about.rest_api.line1}
|
||||
</p>
|
||||
<p>
|
||||
The documentation about the API is available <a href="api" target="_blank">here</a>.
|
||||
<a href="api" target="_blank">${about.rest_api.link_to_documentation}</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="tab-pane" id="shortcuts">
|
||||
<h3>Keyboard Shortcuts</h3>
|
||||
<h3>${about.keyboard_shortcuts}</h3>
|
||||
<div ng-include="'templates/_shortcuts.html'"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<div infinite-scroll="loadMoreEntries()" infinite-scroll-disabled="busy || !settingsService.settings.readingMode" infinite-scroll-distance="1" id="feed-accordion"
|
||||
ng-class="{'expanded' : settingsService.settings.viewMode == 'expanded' }">
|
||||
<div ng-show="message && errorCount > 10">Error while loading this feed : {{message}}</div>
|
||||
<div ng-show="message && errorCount > 10">${view.error_while_loading_feed} : {{message}}</div>
|
||||
<div ng-repeat="entry in entries" class="entry" scroll-to="navigationMode == 'click' && isOpen && current == entry" scroll-to-offset="-58"
|
||||
on-scroll-middle="onScroll(entry)" ng-class="{current: current==entry}">
|
||||
<a href="{{entry.url}}" target="_blank" class="entry-heading" ng-click="noop($event)" ng-mouseup="entryClicked(entry, $event)"
|
||||
@@ -69,11 +69,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-entries" ng-show="name && entries.length == 0 && !busy">"{{name}}" has no unread items.</div>
|
||||
<div class="no-entries" ng-show="name && entries.length == 0 && !busy">"{{name}}" ${view.no_unread_items}</div>
|
||||
<div modal="shortcutsModal" close="shortcutsModal=false" options="shortcutsOpts">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" ng-click="shortcutsModal=false">×</button>
|
||||
<h4>Keyboard shortcuts</h4>
|
||||
<h4>${about.keyboard_shortcuts}</h4>
|
||||
</div>
|
||||
<div ng-include="'templates/_shortcuts.html'"></div>
|
||||
</div>
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
<div class="container-fluid profile">
|
||||
<div class="page-header">
|
||||
<h1>Profile</h1>
|
||||
<h1>${toolbar.profile}</h1>
|
||||
</div>
|
||||
<form name="profileForm" ng-submit="save()" class="form-horizontal">
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="email">User name</label>
|
||||
<label class="control-label" for="email">${profile.user_name}</label>
|
||||
<div class="controls horizontal-align">
|
||||
<span>{{user.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="email">E-mail</label>
|
||||
<label class="control-label" for="email">${profile.email}</label>
|
||||
<div class="controls">
|
||||
<input type="email" id="email" ng-model="user.email" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="password">Change password</label>
|
||||
<label class="control-label" for="password">${profile.change_password}</label>
|
||||
<div class="controls">
|
||||
<input type="password" name="password" id="password" ng-model="user.password"
|
||||
ng-minlength="6" />
|
||||
<span class="help-inline" ng-show="profileForm.password.$error.minlength">Minimum 6 characters</span>
|
||||
<span class="help-inline" ng-show="profileForm.password.$error.minlength">${profile.minimum_6_chars}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="password">Confirm password</label>
|
||||
<label class="control-label" for="password">${profile.confirm_password}</label>
|
||||
<div class="controls">
|
||||
<input type="password" name="password_c" id="password_c" ng-model="password_c"
|
||||
ui-validate="'$value==user.password'" ui-validate-watch="'user.password'">
|
||||
<span class="help-inline" ng-show="profileForm.password_c.$error.validator">Passwords do not match</span>
|
||||
<span class="help-inline" ng-show="profileForm.password_c.$error.validator">${profile.passwords_do_not_match}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="password">API key</label>
|
||||
<label class="control-label" for="password">${profile.api_key}</label>
|
||||
<div class="controls horizontal-align">
|
||||
<span ng-show="user.apiKey">{{user.apiKey}}</span>
|
||||
<span ng-show="!user.apiKey">Not generated yet</span>
|
||||
<span ng-show="!user.apiKey">${profile.api_key_not_generated}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="password">Generate new API key</label>
|
||||
<label class="control-label" for="password">${profile.generate_new_api_key}</label>
|
||||
<div class="controls">
|
||||
<input type="checkbox" name="newApiKey" id="newApiKey" ng-model="newApiKey">
|
||||
<span class="help-block">Changing password will generate a new API key</span>
|
||||
<span class="help-block">${profile.generate_new_api_key_info}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
<button type="button" class="btn" ng-click="cancel()">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="deleteAccount()">Delete account</button>
|
||||
<button type="submit" class="btn btn-primary">${global.save}</button>
|
||||
<button type="button" class="btn" ng-click="cancel()">${global.cancel}</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="deleteAccount()">${profile.delete_account}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -7,11 +7,11 @@
|
||||
<div class="span2">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<li class="active">
|
||||
<a href="#general" data-toggle="pill">General</a>
|
||||
<a href="#general" data-toggle="pill">${settings.general}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#custom-css" data-toggle="pill"
|
||||
ng-click="refreshCodemirror=!refreshCodemirror">Custom CSS</a>
|
||||
ng-click="refreshCodemirror=!refreshCodemirror">${settings.custom_css}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -20,10 +20,10 @@
|
||||
<div class="tab-pane active" id="general">
|
||||
<div class="form-horizontal">
|
||||
<div class="control-group">
|
||||
<label class="control-label">Language</label>
|
||||
<label class="control-label">${settings.general.language}</label>
|
||||
<div class="controls">
|
||||
<select name="language" ng-model="settings.language" class="input-block-level"
|
||||
ng-options="lang.id as lang.label for lang in languages" required>
|
||||
ng-options="id as label for (id,label) in ServerService.supportedLanguages" required>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -31,21 +31,21 @@
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="showRead"
|
||||
ng-model="settings.showRead" />
|
||||
Show feeds and categories with no unread entries
|
||||
${settings.general.show_unread}
|
||||
</label>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="socialButtons"
|
||||
ng-model="settings.socialButtons" />
|
||||
Show social sharing buttons
|
||||
${settings.general.social_buttons}
|
||||
</label>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="scrollMarks"
|
||||
ng-model="settings.scrollMarks" />
|
||||
In expanded view, scrolling through entries mark them as read
|
||||
${settings.general.scroll_marks}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -58,8 +58,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
<button type="button" class="btn" ng-click="cancel()">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">${global.save}</button>
|
||||
<button type="button" class="btn" ng-click="cancel()">${global.cancel}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
3
src/main/webapp/vendor/momentjs/moment-langs.min.js
vendored
Normal file
3
src/main/webapp/vendor/momentjs/moment-langs.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user