mirror of
https://github.com/janeczku/calibre-web.git
synced 2024-11-28 08:58:41 +02:00
Merge branch 'Chinese_tanslation' (#90)
Thanks @idalin user language should be detected from browser, or otherwise with enabled anonymous browsing it can be selected as admin (configure language for user guest). Annymous browsing can be deactivated afterwards
This commit is contained in:
commit
2335252b1f
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,3 +22,4 @@ cps/static/[0-9]*
|
|||||||
.idea/
|
.idea/
|
||||||
*.bak
|
*.bak
|
||||||
*.log.*
|
*.log.*
|
||||||
|
tags
|
||||||
|
147
cps/static/js/context.js
Normal file
147
cps/static/js/context.js
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*!
|
||||||
|
* context.js Library associated with > v0.9.6.2 of intention.js
|
||||||
|
* http://intentionjs.com/
|
||||||
|
*
|
||||||
|
* Copyright 2011, 2013 Dowjones and other contributors
|
||||||
|
* Released under the MIT license
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var context = function($, Intention){
|
||||||
|
|
||||||
|
// create a brand spankin new intention object
|
||||||
|
var intent=new Intention(),
|
||||||
|
// placeholder for the horizontal axis
|
||||||
|
horizontal_axis,
|
||||||
|
orientation_axis;
|
||||||
|
|
||||||
|
// throttle funtion used for keeping calls to the resize responive
|
||||||
|
// callback to a minimum
|
||||||
|
function throttle(callback, interval){
|
||||||
|
var lastExec = new Date(),
|
||||||
|
timer = null;
|
||||||
|
|
||||||
|
return function(e){
|
||||||
|
var d = new Date();
|
||||||
|
if (d-lastExec < interval) {
|
||||||
|
if (timer) {
|
||||||
|
window.clearTimeout(timer);
|
||||||
|
}
|
||||||
|
var callbackWrapper = function(event){
|
||||||
|
return function(){
|
||||||
|
callback(event);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
timer = window.setTimeout(callbackWrapper(e), interval);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
callback(e);
|
||||||
|
lastExec = d;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// catchall
|
||||||
|
// =======================================================================
|
||||||
|
intent.responsive([{name:'base'}]).respond('base');
|
||||||
|
|
||||||
|
// width context?
|
||||||
|
// =======================================================================
|
||||||
|
horizontal_axis = intent.responsive({
|
||||||
|
ID:'width',
|
||||||
|
contexts: [
|
||||||
|
{name:'standard', min:840},
|
||||||
|
{name:'tablet', min:510},
|
||||||
|
{name:'mobile', min:0}],
|
||||||
|
// compare the return value of the callback to each context
|
||||||
|
// return true for a match
|
||||||
|
matcher: function(test, context){
|
||||||
|
if(typeof test === 'string'){
|
||||||
|
|
||||||
|
return test === context.name;
|
||||||
|
}
|
||||||
|
return test>=context.min;
|
||||||
|
},
|
||||||
|
// callback, return value is passed to matcher()
|
||||||
|
// to compare against current context
|
||||||
|
measure: function(arg){
|
||||||
|
|
||||||
|
if(typeof arg === 'string'){
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $(window).width();
|
||||||
|
}});
|
||||||
|
|
||||||
|
// orientation context?
|
||||||
|
// =======================================================================
|
||||||
|
orientation_axis = intent.responsive({
|
||||||
|
ID:'orientation',
|
||||||
|
contexts: [{name:'portrait', rotation: 0},
|
||||||
|
{name:'landscape', rotation:90}],
|
||||||
|
matcher: function(measure, ctx){
|
||||||
|
return measure === ctx.rotation;
|
||||||
|
},
|
||||||
|
measure: function(){
|
||||||
|
var test = Math.abs(window.orientation);
|
||||||
|
if(test > 0) {
|
||||||
|
test = 180 - test;
|
||||||
|
}
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ONE TIME CHECK AXES:
|
||||||
|
// touch device?
|
||||||
|
// =======================================================================
|
||||||
|
intent.responsive({
|
||||||
|
ID:'touch',
|
||||||
|
contexts:[{name:'touch'}],
|
||||||
|
matcher: function() {
|
||||||
|
return "ontouchstart" in window;
|
||||||
|
}}).respond();
|
||||||
|
|
||||||
|
// retina display?
|
||||||
|
// =======================================================================
|
||||||
|
intent.responsive({
|
||||||
|
ID: 'highres',
|
||||||
|
// contexts
|
||||||
|
contexts:[{name:'highres'}],
|
||||||
|
// matching:
|
||||||
|
matcher: function(){
|
||||||
|
return window.devicePixelRatio > 1;
|
||||||
|
}}).respond();
|
||||||
|
|
||||||
|
// bind events to the window
|
||||||
|
$(window).on('resize', throttle(horizontal_axis.respond, 100))
|
||||||
|
.on('orientationchange', horizontal_axis.respond)
|
||||||
|
.on('orientationchange', orientation_axis.respond);
|
||||||
|
|
||||||
|
// register the current width and orientation without waiting for a window
|
||||||
|
// resize
|
||||||
|
horizontal_axis.respond();
|
||||||
|
orientation_axis.respond();
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
// at doc ready grab all of the elements in the doc
|
||||||
|
intent.elements(document);
|
||||||
|
});
|
||||||
|
|
||||||
|
// return the intention object so that it can be extended by other plugins
|
||||||
|
return intent;
|
||||||
|
};
|
||||||
|
|
||||||
|
(function (root, factory) {
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
// AMD. Register as an anonymous module.
|
||||||
|
define('context', ['jquery', 'intention'], factory);
|
||||||
|
} else {
|
||||||
|
// Browser globals
|
||||||
|
root.intent = factory(root.jQuery, root.Intention);
|
||||||
|
}
|
||||||
|
}(this, function ($, Intention) {
|
||||||
|
return context($, Intention);
|
||||||
|
}));
|
||||||
|
}).call(this);
|
564
cps/static/js/intention.js
Normal file
564
cps/static/js/intention.js
Normal file
@ -0,0 +1,564 @@
|
|||||||
|
/*!
|
||||||
|
* intention.js Library v0.9.7.2
|
||||||
|
* http://intentionjs.com/
|
||||||
|
*
|
||||||
|
* Copyright 2011, 2013 Dowjones and other contributors
|
||||||
|
* Released under the MIT license
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function(root, factory) {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define('intention', ['jquery', 'underscore'], factory);
|
||||||
|
} else {
|
||||||
|
root.Intention = factory(root.jQuery, root._);
|
||||||
|
}
|
||||||
|
}(this, function($, _) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Intention = function(params){
|
||||||
|
var intent = _.extend(this, params,
|
||||||
|
{_listeners:{}, contexts:[], elms:$(), axes:{}, priority:[]});
|
||||||
|
|
||||||
|
return intent;
|
||||||
|
};
|
||||||
|
|
||||||
|
Intention.prototype = {
|
||||||
|
|
||||||
|
// public methods
|
||||||
|
responsive:function responsive(contexts, options){
|
||||||
|
// for generating random ids for axis when not specified
|
||||||
|
var idChars = 'abcdefghijklmnopqrstuvwxyz0123456789',
|
||||||
|
id='', i;
|
||||||
|
|
||||||
|
// create a random id for the axis
|
||||||
|
for(i=0; i<5; i++){
|
||||||
|
id += idChars[Math.floor(Math.random() * idChars.length)];
|
||||||
|
}
|
||||||
|
var defaults = {
|
||||||
|
// if no matcher function is specified expect to compare a
|
||||||
|
// string to the ctx.name property
|
||||||
|
matcher: function(measure, ctx){
|
||||||
|
return measure === ctx.name;
|
||||||
|
},
|
||||||
|
// function takes one arg and returns it
|
||||||
|
measure: _.identity,
|
||||||
|
ID: id
|
||||||
|
};
|
||||||
|
|
||||||
|
if(_.isObject(options) === false) {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if((_.isArray(contexts)) && (_.isArray(contexts[0].contexts))){
|
||||||
|
_.each(contexts, function(axis){
|
||||||
|
responsive.apply(this, axis);
|
||||||
|
}, this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((_.isArray(contexts) === false) && _.isObject(contexts)){
|
||||||
|
options = contexts;
|
||||||
|
} else {
|
||||||
|
options.contexts = contexts;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill in the options
|
||||||
|
options = _.extend({}, defaults, options);
|
||||||
|
|
||||||
|
// bind an the respond function to the axis ID and prefix it
|
||||||
|
// with an underscore so that it does not get whomped accidentally
|
||||||
|
this.on('_' + options.ID + ':', _.bind(
|
||||||
|
function(e){
|
||||||
|
this.axes = this._contextualize(
|
||||||
|
options.ID, e.context, this.axes);
|
||||||
|
this._respond(this.axes, this.elms);
|
||||||
|
|
||||||
|
}, this));
|
||||||
|
|
||||||
|
var axis = {
|
||||||
|
ID:options.ID,
|
||||||
|
current:null,
|
||||||
|
contexts:options.contexts,
|
||||||
|
respond:_.bind(this._responder(options.ID, options.contexts,
|
||||||
|
options.matcher, options.measure), this)
|
||||||
|
};
|
||||||
|
|
||||||
|
this.axes[options.ID] = axis;
|
||||||
|
|
||||||
|
this.axes.__keys__ = this.priority;
|
||||||
|
|
||||||
|
this.priority.unshift(options.ID);
|
||||||
|
|
||||||
|
return axis;
|
||||||
|
},
|
||||||
|
|
||||||
|
elements: function(scope){
|
||||||
|
|
||||||
|
// find all responsive elms in a specific dom scope
|
||||||
|
if(!scope){
|
||||||
|
scope = document;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('[data-intent],[intent],[data-in],[in]',
|
||||||
|
scope).each(_.bind(function(i, elm){
|
||||||
|
this.add($(elm));
|
||||||
|
}, this));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
add: function(elms, options){
|
||||||
|
|
||||||
|
var spec;
|
||||||
|
|
||||||
|
if(!options) {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// is expecting a jquery object
|
||||||
|
elms.each(_.bind(function(i, elm){
|
||||||
|
var exists = false;
|
||||||
|
this.elms.each(function(i, respElm){
|
||||||
|
if(elm === respElm) {
|
||||||
|
exists=true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(exists === false){
|
||||||
|
// create the elements responsive data
|
||||||
|
spec = this._fillSpec(
|
||||||
|
_.extend(options, this._attrsToSpec(elm.attributes, this.axes)));
|
||||||
|
// make any appropriate changes based on the current contexts
|
||||||
|
this._makeChanges($(elm), spec, this.axes);
|
||||||
|
|
||||||
|
this.elms.push({
|
||||||
|
elm: elm,
|
||||||
|
spec: spec
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}, this));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: function(elms){
|
||||||
|
// is expecting a jquery object
|
||||||
|
var respElms = this.elms;
|
||||||
|
// elms to remove
|
||||||
|
elms.each(function(i, elm){
|
||||||
|
// elms to check against
|
||||||
|
respElms.each(function(i, candidate){
|
||||||
|
if(elm === candidate.elm){
|
||||||
|
respElms.splice(i, 1);
|
||||||
|
// found the match, break the loop
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
is: function(ctxName){
|
||||||
|
var axes = this.axes;
|
||||||
|
return _.some(axes.__keys__, function(key){
|
||||||
|
return ctxName === axes[key].current;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
current: function(axisName){
|
||||||
|
if(this.axes.hasOwnProperty(axisName)){
|
||||||
|
return this.axes[axisName].current;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// code and concept taken from simple implementation of
|
||||||
|
// observer pattern outlined here:
|
||||||
|
// http://www.nczonline.net/blog/2010/03/09/custom-events-in-javascript/
|
||||||
|
on: function(type, listener){
|
||||||
|
|
||||||
|
var events = type.split(' '),
|
||||||
|
i=0;
|
||||||
|
|
||||||
|
for(i;i<events.length;i++){
|
||||||
|
if(this._listeners[events[i]] === undefined) {
|
||||||
|
this._listeners[events[i]]=[];
|
||||||
|
}
|
||||||
|
this._listeners[events[i]].push(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
off: function(type, listener){
|
||||||
|
if(_.isArray(this._listeners[type])){
|
||||||
|
var listeners = this._listeners[type],
|
||||||
|
i;
|
||||||
|
for(i=0;listeners.length; i++){
|
||||||
|
if(listeners[i] === listener){
|
||||||
|
listeners.splice(i,1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// privates
|
||||||
|
_responder: function(axisID, contexts, matcher, measure){
|
||||||
|
|
||||||
|
var currentContext;
|
||||||
|
|
||||||
|
// called to perform a check
|
||||||
|
return function(){
|
||||||
|
|
||||||
|
var measurement = measure.apply(this, arguments);
|
||||||
|
|
||||||
|
_.every(contexts, function(ctx){
|
||||||
|
if( matcher(measurement, ctx)) {
|
||||||
|
// first time, or different than last context
|
||||||
|
if( (currentContext===undefined) ||
|
||||||
|
(ctx.name !== currentContext.name)){
|
||||||
|
|
||||||
|
currentContext = ctx;
|
||||||
|
|
||||||
|
// event emitting!
|
||||||
|
// emit the private axis event
|
||||||
|
this._emitter(
|
||||||
|
{_type: '_' + axisID + ':', context:currentContext.name},
|
||||||
|
currentContext, this)
|
||||||
|
|
||||||
|
// emit the public axis event
|
||||||
|
._emitter({_type: axisID + ':', context:currentContext.name},
|
||||||
|
currentContext, this)
|
||||||
|
|
||||||
|
// attempt to trigger the axis to context pair
|
||||||
|
._emitter(_.extend({},
|
||||||
|
{_type: axisID + ':' + currentContext.name},
|
||||||
|
currentContext), currentContext, this)
|
||||||
|
|
||||||
|
// then emit the context event (second ensures the context
|
||||||
|
// changes happen after all dom manipulations)
|
||||||
|
._emitter(_.extend({}, {_type:currentContext.name},
|
||||||
|
currentContext), currentContext, this);
|
||||||
|
|
||||||
|
// done, break the loop
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// same context, break the loop
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
// return the intention object for chaining
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
_emitter: function(event){
|
||||||
|
if(typeof event === 'string') {
|
||||||
|
event={_type:event};
|
||||||
|
}
|
||||||
|
if(!event.target){
|
||||||
|
event.target=this;
|
||||||
|
}
|
||||||
|
if(!event._type){
|
||||||
|
throw new Error(event._type + ' is not a supported event.');
|
||||||
|
}
|
||||||
|
if(_.isArray(this._listeners[event._type])){
|
||||||
|
var listeners = this._listeners[event._type],
|
||||||
|
i;
|
||||||
|
for(i=0; i<listeners.length; i++){
|
||||||
|
listeners[i].apply(this, arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
_fillSpec: function(spec){
|
||||||
|
|
||||||
|
var applySpec = function(fn){
|
||||||
|
_.each(spec, function(axisOptions, axis){
|
||||||
|
_.each(axisOptions, function(ctxOptions, ctx){
|
||||||
|
fn(ctxOptions, ctx, axis);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, filler={};
|
||||||
|
|
||||||
|
applySpec(function(options){
|
||||||
|
// check to see if the ctx val is an object, could be a string
|
||||||
|
if(_.isObject(options)){
|
||||||
|
_.each(options, function(val, func){
|
||||||
|
filler[func] = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
applySpec(function(options, ctx, axis){
|
||||||
|
if(_.isObject(options)){
|
||||||
|
spec[axis][ctx] = _.extend({}, filler, options);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return spec;
|
||||||
|
},
|
||||||
|
|
||||||
|
_assocAxis: function(ctx, axes){
|
||||||
|
|
||||||
|
var match=false;
|
||||||
|
|
||||||
|
_.every(axes.__keys__, function(axis){
|
||||||
|
|
||||||
|
if(match === false){
|
||||||
|
_.every(axes[axis].contexts, function(ctxCandidate){
|
||||||
|
if(ctxCandidate.name === ctx){
|
||||||
|
match = axis;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return match;
|
||||||
|
},
|
||||||
|
|
||||||
|
_makeSpec: function(axis, ctx, sAttr, value, spec){
|
||||||
|
var axisObj,
|
||||||
|
ctxObj;
|
||||||
|
|
||||||
|
if(spec[axis] !== undefined){
|
||||||
|
axisObj = spec[axis];
|
||||||
|
|
||||||
|
if(axisObj[ctx] === undefined) {
|
||||||
|
axisObj[ctx] = {};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
axisObj = {};
|
||||||
|
axisObj[ctx] = {};
|
||||||
|
spec[axis] = axisObj;
|
||||||
|
}
|
||||||
|
axisObj[ctx][sAttr] = value;
|
||||||
|
|
||||||
|
return spec;
|
||||||
|
},
|
||||||
|
|
||||||
|
_attrsToSpec: function(attrs, axes){
|
||||||
|
|
||||||
|
var spec={},
|
||||||
|
fullPattern = new RegExp(
|
||||||
|
'^(data-)?(in|intent)-(([a-zA-Z0-9][a-zA-Z0-9]*:)?([a-zA-Z0-9]*))-([A-Za-z:-]+)'),
|
||||||
|
axisPattern = new RegExp(
|
||||||
|
'^(data-)?(in|intent)-([a-zA-Z0-9][_a-zA-Z0-9]*):$');
|
||||||
|
|
||||||
|
_.each(attrs, function(attr){
|
||||||
|
|
||||||
|
var specMatch = attr.name.match(fullPattern),
|
||||||
|
axisName;
|
||||||
|
|
||||||
|
if(specMatch !== null) {
|
||||||
|
|
||||||
|
specMatch = specMatch.slice(-3);
|
||||||
|
axisName = specMatch[0];
|
||||||
|
|
||||||
|
if(specMatch[0] === undefined){
|
||||||
|
|
||||||
|
// if there is no axis find one:
|
||||||
|
specMatch[0] = this._assocAxis(specMatch[1], axes);
|
||||||
|
|
||||||
|
if(specMatch[0] === false) {
|
||||||
|
// there is no context, so get outa here
|
||||||
|
return; // skipt the attr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
specMatch[0] = specMatch[0].replace(/:$/, '');}
|
||||||
|
|
||||||
|
specMatch.push(attr.value);
|
||||||
|
specMatch.push(spec);
|
||||||
|
|
||||||
|
spec = this._makeSpec.apply(this, specMatch);
|
||||||
|
|
||||||
|
} else if(axisPattern.test(attr.name)){
|
||||||
|
|
||||||
|
axisName = attr.name.match(axisPattern)[3];
|
||||||
|
|
||||||
|
_.each(axes[axisName].contexts,
|
||||||
|
function(context){
|
||||||
|
this._makeSpec(axisName, context.name, 'class', context.name +
|
||||||
|
' ' + attr.value, spec);
|
||||||
|
},
|
||||||
|
this);}},
|
||||||
|
this);
|
||||||
|
|
||||||
|
return spec;
|
||||||
|
},
|
||||||
|
|
||||||
|
_contextSpec: function(ctxObj, specs){
|
||||||
|
if(specs.hasOwnProperty(ctxObj.axis) &&
|
||||||
|
specs[ctxObj.axis].hasOwnProperty(ctxObj.ctx)){
|
||||||
|
return specs[ctxObj.axis][ctxObj.ctx];
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
_resolveSpecs: function(currentContexts, specs){
|
||||||
|
|
||||||
|
var changes={},
|
||||||
|
moveFuncs=['append', 'prepend', 'before', 'after'];
|
||||||
|
|
||||||
|
_.each(currentContexts, function(ctxObj){
|
||||||
|
// if the axis or the context to not exist in the specs object
|
||||||
|
// skip to the next one
|
||||||
|
_.each(this._contextSpec(ctxObj, specs), function(val, func){
|
||||||
|
|
||||||
|
if(func==='class'){
|
||||||
|
if(!changes[func]){
|
||||||
|
changes[func] = [];
|
||||||
|
}
|
||||||
|
changes[func] = _.union(changes[func], val.split(' '));
|
||||||
|
|
||||||
|
} else if(((changes.move === undefined) ||
|
||||||
|
(changes.move.value === '')) &&
|
||||||
|
($.inArray(func, moveFuncs) !== -1)){
|
||||||
|
|
||||||
|
changes.move = {value:val, placement:func};
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if((changes[func] === undefined) || (changes[func] === '')){
|
||||||
|
changes[func]=val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
}, this);
|
||||||
|
return changes;
|
||||||
|
},
|
||||||
|
|
||||||
|
_currentContexts: function(axes) {
|
||||||
|
var contexts = [];
|
||||||
|
|
||||||
|
_.each(axes.__keys__, function(ID){
|
||||||
|
if(axes[ID].current !== null) {
|
||||||
|
contexts.push({ctx:axes[ID].current, axis:ID});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return contexts;
|
||||||
|
},
|
||||||
|
|
||||||
|
_removeClasses: function(specs, axes) {
|
||||||
|
|
||||||
|
var toRemove = [];
|
||||||
|
|
||||||
|
_.each(axes.__keys__, function(key){
|
||||||
|
|
||||||
|
var axis = axes[key];
|
||||||
|
|
||||||
|
_.each(axis.contexts, function(ctx){
|
||||||
|
|
||||||
|
// ignore the current context, those classes SHOULD be applied
|
||||||
|
if(ctx.name === axis.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var contextSpec = this._contextSpec(
|
||||||
|
{axis:axis.ID, ctx:ctx.name}, specs),
|
||||||
|
classes;
|
||||||
|
|
||||||
|
if(contextSpec !== undefined) {
|
||||||
|
if(contextSpec['class'] !== undefined) {
|
||||||
|
classes = contextSpec['class'].split(' ');
|
||||||
|
if(classes !== undefined){
|
||||||
|
toRemove = _.union(toRemove, classes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
return toRemove;
|
||||||
|
},
|
||||||
|
|
||||||
|
_contextConfig: function(specs, axes){
|
||||||
|
|
||||||
|
return this._resolveSpecs(this._currentContexts(axes), specs, axes);
|
||||||
|
},
|
||||||
|
|
||||||
|
_makeChanges: function(elm, specs, axes){
|
||||||
|
|
||||||
|
if(_.isEmpty(axes)===false){
|
||||||
|
var ctxConfig = this._contextConfig(specs, axes);
|
||||||
|
|
||||||
|
_.each(ctxConfig, function(change, func){
|
||||||
|
if(func==='move'){
|
||||||
|
if( (specs.__placement__ !== change.placement) ||
|
||||||
|
(specs.__move__ !== change.value)){
|
||||||
|
|
||||||
|
$(change.value)[change.placement](elm);
|
||||||
|
|
||||||
|
// save the last placement of the element so
|
||||||
|
// we're not moving it around for no good reason
|
||||||
|
specs.__placement__ = change.placement;
|
||||||
|
specs.__move__ = change.value;
|
||||||
|
}
|
||||||
|
} else if(func === 'class') {
|
||||||
|
|
||||||
|
var classes = elm.attr('class') || '';
|
||||||
|
|
||||||
|
// the class add/remove formula
|
||||||
|
classes = _.union(change,
|
||||||
|
_.difference(classes.split(' '),
|
||||||
|
this._removeClasses(specs, axes)));
|
||||||
|
|
||||||
|
elm.attr('class', classes.join(' '));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
elm.attr(func, change);
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
return elm;
|
||||||
|
},
|
||||||
|
|
||||||
|
_respond: function(axes, elms){
|
||||||
|
// go through all of the responsive elms
|
||||||
|
elms.each(_.bind(function(i, elm){
|
||||||
|
var $elm = $(elm.elm);
|
||||||
|
this._makeChanges($elm, elm.spec, axes);
|
||||||
|
$elm.trigger('intent', this);
|
||||||
|
}, this));
|
||||||
|
},
|
||||||
|
|
||||||
|
_contextualize: function(axisID, context, axes){
|
||||||
|
axes[axisID].current = context;
|
||||||
|
return axes;
|
||||||
|
},
|
||||||
|
|
||||||
|
// private props
|
||||||
|
|
||||||
|
// axis test, does it begin with an underscore? for testing inside
|
||||||
|
// spec objects
|
||||||
|
_axis_test_pattern: new RegExp("^_[a-zA-Z0-9]"),
|
||||||
|
|
||||||
|
// match a group after the underscore:
|
||||||
|
_axis_match_pattern: new RegExp("^_([a-zA-Z0-9][_a-zA-Z0-9]*)"),
|
||||||
|
|
||||||
|
// simple trim
|
||||||
|
_trim_pattern:new RegExp( "^\s+|\s+$", "g" )
|
||||||
|
};
|
||||||
|
|
||||||
|
return Intention;
|
||||||
|
}));
|
@ -24,7 +24,7 @@
|
|||||||
<script src="{{ url_for('static', filename='js/libs/jquery.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/libs/jquery.min.js') }}"></script>
|
||||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||||
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/underscore.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/underscore-min.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/intention.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/intention.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/context.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/context.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/plugins.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/plugins.js') }}"></script>
|
||||||
|
@ -23,16 +23,14 @@
|
|||||||
<label for="kindle_mail">{{_('Kindle E-Mail')}}</label>
|
<label for="kindle_mail">{{_('Kindle E-Mail')}}</label>
|
||||||
<input type="email" class="form-control" name="kindle_mail" id="kindle_mail" value="{{ content.kindle_mail if content.kindle_mail != None }}">
|
<input type="email" class="form-control" name="kindle_mail" id="kindle_mail" value="{{ content.kindle_mail if content.kindle_mail != None }}">
|
||||||
</div>
|
</div>
|
||||||
{% if not content.role_anonymous() %}
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="locale">{{_('Language')}}</label>
|
<label for="locale">{{_('Language')}}</label>
|
||||||
<select name="locale" id="locale" class="form-control">
|
<select name="locale" id="locale" class="form-control">
|
||||||
{% for translation in translations %}
|
{% for translation in translations %}
|
||||||
<option value="{{translation.language}}" {% if translation.language == content.locale %}selected{% endif %}>{{ translation.display_name }}</option>
|
<option value="{{translation}}" {% if translation|string == content.locale %}selected{% endif %}>{{ translation.display_name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="default_language">{{_('Show books with language')}}</label>
|
<label for="default_language">{{_('Show books with language')}}</label>
|
||||||
<select name="default_language" id="default_language" class="form-control">
|
<select name="default_language" id="default_language" class="form-control">
|
||||||
|
BIN
cps/translations/zh_Hans_CN/LC_MESSAGES/messages.mo
Normal file
BIN
cps/translations/zh_Hans_CN/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
824
cps/translations/zh_Hans_CN/LC_MESSAGES/messages.po
Normal file
824
cps/translations/zh_Hans_CN/LC_MESSAGES/messages.po
Normal file
@ -0,0 +1,824 @@
|
|||||||
|
# Chinese (Simplified, China) translations for PROJECT.
|
||||||
|
# Copyright (C) 2017 ORGANIZATION
|
||||||
|
# This file is distributed under the same license as the PROJECT project.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
|
"POT-Creation-Date: 2017-01-03 19:50+0100\n"
|
||||||
|
"PO-Revision-Date: 2017-01-06 17:00+0800\n"
|
||||||
|
"Last-Translator: dalin <dalin.lin@gmail.com>\n"
|
||||||
|
"Language: zh_Hans_CN\n"
|
||||||
|
"Language-Team: zh_Hans_CN <LL@li.org>\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: Babel 2.3.4\n"
|
||||||
|
|
||||||
|
#: cps/book_formats.py:109 cps/book_formats.py:113 cps/web.py:928
|
||||||
|
msgid "not installed"
|
||||||
|
msgstr "未安装"
|
||||||
|
|
||||||
|
#: cps/helper.py:98
|
||||||
|
msgid "Calibre-web test email"
|
||||||
|
msgstr "Calibre-web 测试邮件"
|
||||||
|
|
||||||
|
#: cps/helper.py:99 cps/helper.py:152
|
||||||
|
msgid "This email has been sent via calibre web."
|
||||||
|
msgstr "此邮件已通过calibre web发送"
|
||||||
|
|
||||||
|
#: cps/helper.py:133 cps/helper.py:221
|
||||||
|
#, python-format
|
||||||
|
msgid "Failed to send mail: %s"
|
||||||
|
msgstr "发送邮件失败: %s"
|
||||||
|
|
||||||
|
#: cps/helper.py:151 cps/templates/detail.html:124
|
||||||
|
msgid "Send to Kindle"
|
||||||
|
msgstr "发送到Kindle"
|
||||||
|
|
||||||
|
#: cps/helper.py:174 cps/helper.py:189
|
||||||
|
msgid "Could not find any formats suitable for sending by email"
|
||||||
|
msgstr "无法适合邮件发送的格式"
|
||||||
|
|
||||||
|
#: cps/helper.py:183
|
||||||
|
msgid "Could not convert epub to mobi"
|
||||||
|
msgstr "无法转换epub到mobi"
|
||||||
|
|
||||||
|
#: cps/helper.py:241
|
||||||
|
msgid "The requested file could not be read. Maybe wrong permissions?"
|
||||||
|
msgstr "无法读取所请求的文件。可能是错误权限不对?"
|
||||||
|
|
||||||
|
#: cps/web.py:722
|
||||||
|
msgid "Latest Books"
|
||||||
|
msgstr "最新书籍"
|
||||||
|
|
||||||
|
#: cps/web.py:747
|
||||||
|
msgid "Hot Books (most downloaded)"
|
||||||
|
msgstr "热门书籍(最多下载)"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:29 cps/web.py:755
|
||||||
|
msgid "Random Books"
|
||||||
|
msgstr "随机书籍"
|
||||||
|
|
||||||
|
#: cps/web.py:768
|
||||||
|
msgid "Author list"
|
||||||
|
msgstr "作者列表"
|
||||||
|
|
||||||
|
#: cps/web.py:785
|
||||||
|
#, python-format
|
||||||
|
msgid "Author: %(nam)s"
|
||||||
|
msgstr "作者: %(nam)s"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:50 cps/web.py:798
|
||||||
|
msgid "Series list"
|
||||||
|
msgstr "丛书列表"
|
||||||
|
|
||||||
|
#: cps/web.py:809
|
||||||
|
#, python-format
|
||||||
|
msgid "Series: %(serie)s"
|
||||||
|
msgstr "丛书: %(serie)s"
|
||||||
|
|
||||||
|
#: cps/web.py:811 cps/web.py:907 cps/web.py:1102 cps/web.py:1838
|
||||||
|
msgid "Error opening eBook. File does not exist or file is not accessible:"
|
||||||
|
msgstr "无法打开电子书。 文件不存在或者文件不可访问:"
|
||||||
|
|
||||||
|
#: cps/web.py:842
|
||||||
|
msgid "Available languages"
|
||||||
|
msgstr "可用语言"
|
||||||
|
|
||||||
|
#: cps/web.py:857
|
||||||
|
#, python-format
|
||||||
|
msgid "Language: %(name)s"
|
||||||
|
msgstr "语言: %(name)s"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:43 cps/web.py:870
|
||||||
|
msgid "Category list"
|
||||||
|
msgstr "分类列表"
|
||||||
|
|
||||||
|
#: cps/web.py:880
|
||||||
|
#, python-format
|
||||||
|
msgid "Category: %(name)s"
|
||||||
|
msgstr "分类: %(name)s"
|
||||||
|
|
||||||
|
#: cps/web.py:936
|
||||||
|
msgid "Statistics"
|
||||||
|
msgstr "统计"
|
||||||
|
|
||||||
|
#: cps/web.py:944
|
||||||
|
msgid "Server restarts"
|
||||||
|
msgstr "重启服务器"
|
||||||
|
|
||||||
|
#: cps/web.py:1078 cps/web.py:1085 cps/web.py:1092 cps/web.py:1099
|
||||||
|
msgid "Read a Book"
|
||||||
|
msgstr "阅读一本书"
|
||||||
|
|
||||||
|
#: cps/web.py:1141 cps/web.py:1474
|
||||||
|
msgid "Please fill out all fields!"
|
||||||
|
msgstr "请填写所有字段"
|
||||||
|
|
||||||
|
#: cps/web.py:1157
|
||||||
|
msgid "An unknown error occured. Please try again later."
|
||||||
|
msgstr "发生一个未知错误。请稍后再试。"
|
||||||
|
|
||||||
|
#: cps/web.py:1162
|
||||||
|
msgid "This username or email address is already in use."
|
||||||
|
msgstr "此用户名或邮箱已被使用。"
|
||||||
|
|
||||||
|
#: cps/web.py:1165
|
||||||
|
msgid "register"
|
||||||
|
msgstr "注册"
|
||||||
|
|
||||||
|
#: cps/web.py:1181
|
||||||
|
#, python-format
|
||||||
|
msgid "you are now logged in as: '%(nickname)s'"
|
||||||
|
msgstr "您现在已以'%(nickname)s'身份登录"
|
||||||
|
|
||||||
|
#: cps/web.py:1185
|
||||||
|
msgid "Wrong Username or Password"
|
||||||
|
msgstr "用户名或密码错误"
|
||||||
|
|
||||||
|
#: cps/web.py:1187
|
||||||
|
msgid "login"
|
||||||
|
msgstr "登录"
|
||||||
|
|
||||||
|
#: cps/web.py:1204
|
||||||
|
msgid "Please configure the SMTP mail settings first..."
|
||||||
|
msgstr "请先配置SMTP邮箱..."
|
||||||
|
|
||||||
|
#: cps/web.py:1208
|
||||||
|
#, python-format
|
||||||
|
msgid "Book successfully send to %(kindlemail)s"
|
||||||
|
msgstr "此书已被成功发给 %(kindlemail)s"
|
||||||
|
|
||||||
|
#: cps/web.py:1212
|
||||||
|
#, python-format
|
||||||
|
msgid "There was an error sending this book: %(res)s"
|
||||||
|
msgstr "发送 %(res)s 这本书的时候出现错误"
|
||||||
|
|
||||||
|
#: cps/web.py:1214
|
||||||
|
msgid "Please configure your kindle email address first..."
|
||||||
|
msgstr "请先配置您的kindle电子邮箱地址..."
|
||||||
|
|
||||||
|
#: cps/web.py:1234
|
||||||
|
#, python-format
|
||||||
|
msgid "Book has been added to shelf: %(sname)s"
|
||||||
|
msgstr "此书已被添加到书架: %(sname)s"
|
||||||
|
|
||||||
|
#: cps/web.py:1255
|
||||||
|
#, python-format
|
||||||
|
msgid "Book has been removed from shelf: %(sname)s"
|
||||||
|
msgstr "此书已从书架 %(sname)s 中删除"
|
||||||
|
|
||||||
|
#: cps/web.py:1273 cps/web.py:1294
|
||||||
|
#, python-format
|
||||||
|
msgid "A shelf with the name '%(title)s' already exists."
|
||||||
|
msgstr "已存在书架 '%(title)s'。"
|
||||||
|
|
||||||
|
#: cps/web.py:1278
|
||||||
|
#, python-format
|
||||||
|
msgid "Shelf %(title)s created"
|
||||||
|
msgstr "书架 %(title)s 已被创建"
|
||||||
|
|
||||||
|
#: cps/web.py:1280 cps/web.py:1305
|
||||||
|
msgid "There was an error"
|
||||||
|
msgstr "发生错误"
|
||||||
|
|
||||||
|
#: cps/web.py:1281 cps/web.py:1283
|
||||||
|
msgid "create a shelf"
|
||||||
|
msgstr "创建书架"
|
||||||
|
|
||||||
|
#: cps/web.py:1303
|
||||||
|
#, python-format
|
||||||
|
msgid "Shelf %(title)s changed"
|
||||||
|
msgstr "书架 %(title)s 已被修改"
|
||||||
|
|
||||||
|
#: cps/web.py:1306 cps/web.py:1308
|
||||||
|
msgid "Edit a shelf"
|
||||||
|
msgstr "编辑书架"
|
||||||
|
|
||||||
|
#: cps/web.py:1329
|
||||||
|
#, python-format
|
||||||
|
msgid "successfully deleted shelf %(name)s"
|
||||||
|
msgstr "成功删除书架 %(name)s"
|
||||||
|
|
||||||
|
#: cps/web.py:1350
|
||||||
|
#, python-format
|
||||||
|
msgid "Shelf: '%(name)s'"
|
||||||
|
msgstr "书架: '%(name)s'"
|
||||||
|
|
||||||
|
#: cps/web.py:1378
|
||||||
|
#, python-format
|
||||||
|
msgid "Change order of Shelf: '%(name)s'"
|
||||||
|
msgstr "修改书架 '%(name)s' 顺序"
|
||||||
|
|
||||||
|
#: cps/web.py:1433
|
||||||
|
msgid "Found an existing account for this email address."
|
||||||
|
msgstr "找到已使用此邮箱的账号。"
|
||||||
|
|
||||||
|
#: cps/web.py:1435 cps/web.py:1438
|
||||||
|
#, python-format
|
||||||
|
msgid "%(name)s's profile"
|
||||||
|
msgstr "%(name)s 的资料"
|
||||||
|
|
||||||
|
#: cps/web.py:1436
|
||||||
|
msgid "Profile updated"
|
||||||
|
msgstr "资料已更新"
|
||||||
|
|
||||||
|
#: cps/web.py:1447 cps/web.py:1455
|
||||||
|
msgid "Admin page"
|
||||||
|
msgstr "管理页"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:32 cps/web.py:1475
|
||||||
|
msgid "Add new user"
|
||||||
|
msgstr "添加新用户"
|
||||||
|
|
||||||
|
#: cps/web.py:1508
|
||||||
|
#, python-format
|
||||||
|
msgid "User '%(user)s' created"
|
||||||
|
msgstr "用户 '%(user)s' 已被创建"
|
||||||
|
|
||||||
|
#: cps/web.py:1512
|
||||||
|
msgid "Found an existing account for this email address or nickname."
|
||||||
|
msgstr "已找到使用此邮箱或昵称的账号。"
|
||||||
|
|
||||||
|
#: cps/web.py:1535 cps/web.py:1546
|
||||||
|
msgid "Mail settings updated"
|
||||||
|
msgstr "邮箱设置已更新"
|
||||||
|
|
||||||
|
#: cps/web.py:1541
|
||||||
|
#, python-format
|
||||||
|
msgid "Test E-Mail successfully send to %(kindlemail)s"
|
||||||
|
msgstr "测试邮件已成功发送到 %(kindlemail)s"
|
||||||
|
|
||||||
|
#: cps/web.py:1544
|
||||||
|
#, python-format
|
||||||
|
msgid "There was an error sending the Test E-Mail: %(res)s"
|
||||||
|
msgstr "发送测试邮件时发生错误: %(res)s"
|
||||||
|
|
||||||
|
#: cps/web.py:1547
|
||||||
|
msgid "Edit mail settings"
|
||||||
|
msgstr "编辑邮箱设置"
|
||||||
|
|
||||||
|
#: cps/web.py:1570
|
||||||
|
#, python-format
|
||||||
|
msgid "User '%(nick)s' deleted"
|
||||||
|
msgstr "用户 '%(nick)s' 已被删除"
|
||||||
|
|
||||||
|
#: cps/web.py:1625
|
||||||
|
#, python-format
|
||||||
|
msgid "User '%(nick)s' updated"
|
||||||
|
msgstr "用户 '%(nick)s' 已被更新"
|
||||||
|
|
||||||
|
#: cps/web.py:1628
|
||||||
|
msgid "An unknown error occured."
|
||||||
|
msgstr "发生未知错误。"
|
||||||
|
|
||||||
|
#: cps/web.py:1630
|
||||||
|
#, python-format
|
||||||
|
msgid "Edit User %(nick)s"
|
||||||
|
msgstr "编辑用户 %(nick)s"
|
||||||
|
|
||||||
|
#: cps/web.py:1868
|
||||||
|
#, python-format
|
||||||
|
msgid "Failed to create path %s (Permission denied)."
|
||||||
|
msgstr "创建路径 %s 失败(权限拒绝)。"
|
||||||
|
|
||||||
|
#: cps/web.py:1873
|
||||||
|
#, python-format
|
||||||
|
msgid "Failed to store file %s (Permission denied)."
|
||||||
|
msgstr "存储文件 %s 失败(权限拒绝)。"
|
||||||
|
|
||||||
|
#: cps/web.py:1878
|
||||||
|
#, python-format
|
||||||
|
msgid "Failed to delete file %s (Permission denied)."
|
||||||
|
msgstr "删除文件 %s 失败(权限拒绝)。"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:4
|
||||||
|
msgid "User list"
|
||||||
|
msgstr "用户列表"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:7
|
||||||
|
msgid "Nickname"
|
||||||
|
msgstr "昵称"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:8
|
||||||
|
msgid "Email"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:9
|
||||||
|
msgid "Kindle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:10
|
||||||
|
msgid "DLS"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:11 cps/templates/layout.html:83
|
||||||
|
msgid "Admin"
|
||||||
|
msgstr "管理"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:12 cps/templates/detail.html:114
|
||||||
|
msgid "Download"
|
||||||
|
msgstr "下载"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:13 cps/templates/layout.html:76
|
||||||
|
msgid "Upload"
|
||||||
|
msgstr "上传"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:14
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "编辑"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:15
|
||||||
|
msgid "Passwd"
|
||||||
|
msgstr "修改密码"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:33
|
||||||
|
msgid "SMTP mail settings"
|
||||||
|
msgstr "SMTP设置"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:36 cps/templates/email_edit.html:7
|
||||||
|
msgid "SMTP hostname"
|
||||||
|
msgstr "SMTP地址"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:37
|
||||||
|
msgid "SMTP port"
|
||||||
|
msgstr "SMTP端口"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:38
|
||||||
|
msgid "SSL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:39 cps/templates/email_edit.html:19
|
||||||
|
msgid "SMTP login"
|
||||||
|
msgstr "SMTP用户名"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:40 cps/templates/email_edit.html:23
|
||||||
|
msgid "SMTP password"
|
||||||
|
msgstr "SMTP密码"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:41
|
||||||
|
msgid "From mail"
|
||||||
|
msgstr "来自邮箱"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:53
|
||||||
|
msgid "Change SMTP settings"
|
||||||
|
msgstr "修改SMTP设置"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:55
|
||||||
|
msgid "Configuration"
|
||||||
|
msgstr "配置"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:58
|
||||||
|
msgid "Log File"
|
||||||
|
msgstr "日志文件"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:59
|
||||||
|
msgid "Log Level"
|
||||||
|
msgstr "日志级别"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:60
|
||||||
|
msgid "Port"
|
||||||
|
msgstr "端口"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:61
|
||||||
|
msgid "Books per page"
|
||||||
|
msgstr "每页书籍数"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:62
|
||||||
|
msgid "Uploading"
|
||||||
|
msgstr "上传"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:63
|
||||||
|
msgid "Public registration"
|
||||||
|
msgstr "开放注册"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:64
|
||||||
|
msgid "Anonymous browsing"
|
||||||
|
msgstr "匿名浏览"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:75
|
||||||
|
msgid "Administration"
|
||||||
|
msgstr "管理"
|
||||||
|
|
||||||
|
#: cps/templates/admin.html:77
|
||||||
|
msgid "Restart Calibre-web"
|
||||||
|
msgstr "重启 Calibre-web"
|
||||||
|
|
||||||
|
#: cps/templates/detail.html:38
|
||||||
|
msgid "Book"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/detail.html:38
|
||||||
|
msgid "of"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/detail.html:44
|
||||||
|
msgid "language"
|
||||||
|
msgstr "语言"
|
||||||
|
|
||||||
|
#: cps/templates/detail.html:103
|
||||||
|
msgid "Description:"
|
||||||
|
msgstr "简介:"
|
||||||
|
|
||||||
|
#: cps/templates/detail.html:128
|
||||||
|
msgid "Read in browser"
|
||||||
|
msgstr "在浏览器中阅读"
|
||||||
|
|
||||||
|
#: cps/templates/detail.html:147
|
||||||
|
msgid "Add to shelf"
|
||||||
|
msgstr "添加到书架"
|
||||||
|
|
||||||
|
#: cps/templates/detail.html:187
|
||||||
|
msgid "Edit metadata"
|
||||||
|
msgstr "编辑元数据"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:14 cps/templates/search_form.html:6
|
||||||
|
msgid "Book Title"
|
||||||
|
msgstr "书名"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:18 cps/templates/search_form.html:10
|
||||||
|
msgid "Author"
|
||||||
|
msgstr "作者"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:22
|
||||||
|
msgid "Description"
|
||||||
|
msgstr "简介"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:26 cps/templates/search_form.html:13
|
||||||
|
msgid "Tags"
|
||||||
|
msgstr "标签"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:31 cps/templates/layout.html:133
|
||||||
|
#: cps/templates/search_form.html:33
|
||||||
|
msgid "Series"
|
||||||
|
msgstr "丛书"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:35
|
||||||
|
msgid "Series id"
|
||||||
|
msgstr "丛书ID"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:39
|
||||||
|
msgid "Rating"
|
||||||
|
msgstr "评分"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:43
|
||||||
|
msgid "Cover URL (jpg)"
|
||||||
|
msgstr "封面URL (jpg)"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:48 cps/templates/user_edit.html:27
|
||||||
|
msgid "Language"
|
||||||
|
msgstr "语言"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:59
|
||||||
|
msgid "Yes"
|
||||||
|
msgstr "确认"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:60
|
||||||
|
msgid "No"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:102
|
||||||
|
msgid "view book after edit"
|
||||||
|
msgstr "编辑后查看书籍"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:105 cps/templates/login.html:19
|
||||||
|
#: cps/templates/search_form.html:75 cps/templates/shelf_edit.html:15
|
||||||
|
#: cps/templates/user_edit.html:94
|
||||||
|
msgid "Submit"
|
||||||
|
msgstr "提交"
|
||||||
|
|
||||||
|
#: cps/templates/edit_book.html:106 cps/templates/email_edit.html:32
|
||||||
|
#: cps/templates/shelf_edit.html:17 cps/templates/shelf_order.html:12
|
||||||
|
#: cps/templates/user_edit.html:96
|
||||||
|
msgid "Back"
|
||||||
|
msgstr "后退"
|
||||||
|
|
||||||
|
#: cps/templates/email_edit.html:11
|
||||||
|
msgid "SMTP port (usually 25 for plain SMTP and 587 for SSL)"
|
||||||
|
msgstr "SMTP端口(不加密的SMTP通常是25, SSL加密的是587)"
|
||||||
|
|
||||||
|
#: cps/templates/email_edit.html:15
|
||||||
|
msgid "Server uses SSL (StartTLS)"
|
||||||
|
msgstr "服务器使用SSL (StartTLS)"
|
||||||
|
|
||||||
|
#: cps/templates/email_edit.html:27
|
||||||
|
msgid "From e-mail"
|
||||||
|
msgstr "来自邮箱"
|
||||||
|
|
||||||
|
#: cps/templates/email_edit.html:30
|
||||||
|
msgid "Save settings"
|
||||||
|
msgstr "保存设置"
|
||||||
|
|
||||||
|
#: cps/templates/email_edit.html:31
|
||||||
|
msgid "Save settings and send Test E-Mail"
|
||||||
|
msgstr "保存设置并发送测试邮件"
|
||||||
|
|
||||||
|
#: cps/templates/feed.xml:14
|
||||||
|
msgid "Next"
|
||||||
|
msgstr "下一个"
|
||||||
|
|
||||||
|
#: cps/templates/index.html:5
|
||||||
|
msgid "Discover (Random Books)"
|
||||||
|
msgstr "发现(随机书籍)"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:5
|
||||||
|
msgid "Start"
|
||||||
|
msgstr "开始"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:7 cps/templates/layout.html:61
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "搜索"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:15 cps/templates/layout.html:124
|
||||||
|
msgid "Hot Books"
|
||||||
|
msgstr "热门书籍"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:19
|
||||||
|
msgid "Popular publications from this catalog based on Rating."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:22 cps/templates/layout.html:122
|
||||||
|
msgid "New Books"
|
||||||
|
msgstr "新书"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:26
|
||||||
|
msgid "The latest Books"
|
||||||
|
msgstr "最新书籍"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:33
|
||||||
|
msgid "Show Random Books"
|
||||||
|
msgstr "显示随机书籍"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:36 cps/templates/layout.html:135
|
||||||
|
msgid "Authors"
|
||||||
|
msgstr "作者"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:40
|
||||||
|
msgid "Books ordered by Author"
|
||||||
|
msgstr "书籍按作者排序"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:47
|
||||||
|
msgid "Books ordered by category"
|
||||||
|
msgstr "书籍按分类排序"
|
||||||
|
|
||||||
|
#: cps/templates/index.xml:54
|
||||||
|
msgid "Books ordered by series"
|
||||||
|
msgstr "书籍按丛书排序"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:48
|
||||||
|
msgid "Toggle navigation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:63
|
||||||
|
msgid "Go!"
|
||||||
|
msgstr "走起!"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:66
|
||||||
|
msgid "Advanced Search"
|
||||||
|
msgstr "高级搜索"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:87
|
||||||
|
msgid "Logout"
|
||||||
|
msgstr "注销"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:91 cps/templates/login.html:4
|
||||||
|
msgid "Login"
|
||||||
|
msgstr "登录"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:92 cps/templates/register.html:18
|
||||||
|
msgid "Register"
|
||||||
|
msgstr "注册"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:121
|
||||||
|
msgid "Browse"
|
||||||
|
msgstr "浏览"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:127
|
||||||
|
msgid "Discover"
|
||||||
|
msgstr "发现"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:130
|
||||||
|
msgid "Categories"
|
||||||
|
msgstr "分类"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:137 cps/templates/search_form.html:54
|
||||||
|
msgid "Languages"
|
||||||
|
msgstr "语言"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:140
|
||||||
|
msgid "Public Shelves"
|
||||||
|
msgstr "公开书架"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:144
|
||||||
|
msgid "Your Shelves"
|
||||||
|
msgstr "您的书架"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:149
|
||||||
|
msgid "Create a Shelf"
|
||||||
|
msgstr "创建书架"
|
||||||
|
|
||||||
|
#: cps/templates/layout.html:152
|
||||||
|
msgid "About"
|
||||||
|
msgstr "关于"
|
||||||
|
|
||||||
|
#: cps/templates/login.html:7 cps/templates/login.html:8
|
||||||
|
#: cps/templates/register.html:7 cps/templates/user_edit.html:8
|
||||||
|
msgid "Username"
|
||||||
|
msgstr "用户名"
|
||||||
|
|
||||||
|
#: cps/templates/login.html:11 cps/templates/login.html:12
|
||||||
|
#: cps/templates/register.html:11 cps/templates/user_edit.html:18
|
||||||
|
msgid "Password"
|
||||||
|
msgstr "密码"
|
||||||
|
|
||||||
|
#: cps/templates/login.html:16
|
||||||
|
msgid "Remember me"
|
||||||
|
msgstr "记住我"
|
||||||
|
|
||||||
|
#: cps/templates/read.html:136
|
||||||
|
msgid "Reflow text when sidebars are open."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/readpdf.html:29
|
||||||
|
msgid "PDF.js viewer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/readtxt.html:6
|
||||||
|
msgid "Basic txt Reader"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/register.html:4
|
||||||
|
msgid "Register a new account"
|
||||||
|
msgstr "注册新用户"
|
||||||
|
|
||||||
|
#: cps/templates/register.html:8
|
||||||
|
msgid "Choose a username"
|
||||||
|
msgstr "选择一个用户名"
|
||||||
|
|
||||||
|
#: cps/templates/register.html:12
|
||||||
|
msgid "Choose a password"
|
||||||
|
msgstr "选择一个密码"
|
||||||
|
|
||||||
|
#: cps/templates/register.html:15 cps/templates/user_edit.html:13
|
||||||
|
msgid "Email address"
|
||||||
|
msgstr "邮箱地址"
|
||||||
|
|
||||||
|
#: cps/templates/register.html:16
|
||||||
|
msgid "Your email address"
|
||||||
|
msgstr "您的邮箱地址"
|
||||||
|
|
||||||
|
#: cps/templates/search.html:6
|
||||||
|
msgid "No Results for:"
|
||||||
|
msgstr "找不到结果:"
|
||||||
|
|
||||||
|
#: cps/templates/search.html:7
|
||||||
|
msgid "Please try a diffrent Search"
|
||||||
|
msgstr "请尝试别的关键字"
|
||||||
|
|
||||||
|
#: cps/templates/search.html:9
|
||||||
|
msgid "Results for:"
|
||||||
|
msgstr "结果:"
|
||||||
|
|
||||||
|
#: cps/templates/search_form.html:23
|
||||||
|
msgid "Exclude Tags"
|
||||||
|
msgstr "排除标签"
|
||||||
|
|
||||||
|
#: cps/templates/search_form.html:43
|
||||||
|
msgid "Exclude Series"
|
||||||
|
msgstr "排除丛书"
|
||||||
|
|
||||||
|
#: cps/templates/search_form.html:64
|
||||||
|
msgid "Exclude Languages"
|
||||||
|
msgstr "排除语言"
|
||||||
|
|
||||||
|
#: cps/templates/shelf.html:6
|
||||||
|
msgid "Delete this Shelf"
|
||||||
|
msgstr "删除此书架"
|
||||||
|
|
||||||
|
#: cps/templates/shelf.html:7
|
||||||
|
msgid "Edit Shelf name"
|
||||||
|
msgstr "编辑书架名"
|
||||||
|
|
||||||
|
#: cps/templates/shelf.html:8
|
||||||
|
msgid "change order"
|
||||||
|
msgstr "修改顺序"
|
||||||
|
|
||||||
|
#: cps/templates/shelf_edit.html:7
|
||||||
|
msgid "Title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/shelf_edit.html:12
|
||||||
|
msgid "should the shelf be public?"
|
||||||
|
msgstr "要公开此书架吗?"
|
||||||
|
|
||||||
|
#: cps/templates/shelf_order.html:5
|
||||||
|
msgid "Drag 'n drop to rearrange order"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/shelf_order.html:11
|
||||||
|
msgid "Change order"
|
||||||
|
msgstr "修改顺序"
|
||||||
|
|
||||||
|
#: cps/templates/stats.html:3
|
||||||
|
msgid "Linked libraries"
|
||||||
|
msgstr "链接库"
|
||||||
|
|
||||||
|
#: cps/templates/stats.html:8
|
||||||
|
msgid "Program library"
|
||||||
|
msgstr "程序库"
|
||||||
|
|
||||||
|
#: cps/templates/stats.html:9
|
||||||
|
msgid "Installed Version"
|
||||||
|
msgstr "已安装版本"
|
||||||
|
|
||||||
|
#: cps/templates/stats.html:36
|
||||||
|
msgid "Calibre library statistics"
|
||||||
|
msgstr "Calibre书库统计"
|
||||||
|
|
||||||
|
#: cps/templates/stats.html:41
|
||||||
|
msgid "Books in this Library"
|
||||||
|
msgstr "本书在此书库"
|
||||||
|
|
||||||
|
#: cps/templates/stats.html:45
|
||||||
|
msgid "Authors in this Library"
|
||||||
|
msgstr "个作者在此书库"
|
||||||
|
|
||||||
|
#: cps/templates/stats.html:49
|
||||||
|
msgid "Series in this Library"
|
||||||
|
msgstr "个丛书在此书库"
|
||||||
|
|
||||||
|
#: cps/templates/stats.html:53
|
||||||
|
msgid "Tags in this Library"
|
||||||
|
msgstr "个标签在此书库"
|
||||||
|
|
||||||
|
#: cps/templates/stats.html:57
|
||||||
|
msgid "Usercount for calibre web"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:23
|
||||||
|
msgid "Kindle E-Mail"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:35
|
||||||
|
msgid "Show books with language"
|
||||||
|
msgstr "按语言显示书籍"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:37
|
||||||
|
msgid "Show all"
|
||||||
|
msgstr "显示全部"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:45
|
||||||
|
msgid "Show random books"
|
||||||
|
msgstr "显示随机书籍"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:49
|
||||||
|
msgid "Show hot books"
|
||||||
|
msgstr "显示热门书籍"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:53
|
||||||
|
msgid "Show language selection"
|
||||||
|
msgstr "显示语言选择"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:57
|
||||||
|
msgid "Show series selection"
|
||||||
|
msgstr "显示丛书选择"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:61
|
||||||
|
msgid "Show category selection"
|
||||||
|
msgstr "显示分类选择"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:68
|
||||||
|
msgid "Admin user"
|
||||||
|
msgstr "管理用户"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:72
|
||||||
|
msgid "Allow Downloads"
|
||||||
|
msgstr "允许下载"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:76
|
||||||
|
msgid "Allow Uploads"
|
||||||
|
msgstr "允许上传"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:80
|
||||||
|
msgid "Allow Edit"
|
||||||
|
msgstr "允许编辑"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:84
|
||||||
|
msgid "Allow Changing Password"
|
||||||
|
msgstr "允许修改密码"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:90
|
||||||
|
msgid "Delete this user"
|
||||||
|
msgstr "删除此用户"
|
||||||
|
|
||||||
|
#: cps/templates/user_edit.html:101
|
||||||
|
msgid "Recent Downloads"
|
||||||
|
msgstr "最近下载"
|
||||||
|
|
||||||
|
msgid "Latin"
|
||||||
|
msgstr ""
|
||||||
|
|
@ -132,6 +132,7 @@ class Anonymous(AnonymousUserMixin,UserBase):
|
|||||||
self.category_books = data.category_books
|
self.category_books = data.category_books
|
||||||
self.hot_books = data.hot_books
|
self.hot_books = data.hot_books
|
||||||
self.default_language = data.default_language
|
self.default_language = data.default_language
|
||||||
|
self.locale = data.locale
|
||||||
|
|
||||||
def role_admin(self):
|
def role_admin(self):
|
||||||
return False
|
return False
|
||||||
|
10
cps/web.py
10
cps/web.py
@ -122,13 +122,6 @@ lm.anonymous_user = ub.Anonymous
|
|||||||
|
|
||||||
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
|
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
|
||||||
|
|
||||||
LANGUAGES = {
|
|
||||||
'en': 'English',
|
|
||||||
'de': 'Deutsch',
|
|
||||||
'fr': 'Français',
|
|
||||||
'es': 'Español'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@babel.localeselector
|
@babel.localeselector
|
||||||
def get_locale():
|
def get_locale():
|
||||||
@ -136,8 +129,9 @@ def get_locale():
|
|||||||
user = getattr(g, 'user', None)
|
user = getattr(g, 'user', None)
|
||||||
if user is not None and hasattr(user, "locale"):
|
if user is not None and hasattr(user, "locale"):
|
||||||
return user.locale
|
return user.locale
|
||||||
|
translations=[item.language for item in babel.list_translations()]+ ['en']
|
||||||
preferred = [x.replace('-', '_') for x in request.accept_languages.values()]
|
preferred = [x.replace('-', '_') for x in request.accept_languages.values()]
|
||||||
return negotiate_locale(preferred, LANGUAGES.keys())
|
return negotiate_locale(preferred, translations)
|
||||||
|
|
||||||
|
|
||||||
@babel.timezoneselector
|
@babel.timezoneselector
|
||||||
|
Loading…
Reference in New Issue
Block a user