From c62a2c21ba0dc186c560acef92f6451be122b4d9 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 30 Oct 2007 07:57:03 +0100 Subject: [PATCH] digest improvements and bugfixes --- MiniTemplator.class.php | 922 +++++++++++++++++++++++++++ config.php-dist | 3 - functions.php | 110 ++-- locale/fr_FR/LC_MESSAGES/messages.mo | Bin 37676 -> 37132 bytes locale/fr_FR/LC_MESSAGES/messages.po | 108 ++-- locale/pt_BR/LC_MESSAGES/messages.mo | Bin 13406 -> 13406 bytes locale/pt_BR/LC_MESSAGES/messages.po | 87 ++- locale/ru_RU/LC_MESSAGES/messages.mo | Bin 25533 -> 25404 bytes locale/ru_RU/LC_MESSAGES/messages.po | 90 ++- locale/zh_CN/LC_MESSAGES/messages.mo | Bin 28093 -> 27634 bytes locale/zh_CN/LC_MESSAGES/messages.po | 100 ++- templates/digest_template.txt | 14 + templates/digest_template_html.txt | 14 + 13 files changed, 1195 insertions(+), 253 deletions(-) create mode 100644 MiniTemplator.class.php create mode 100644 templates/digest_template.txt create mode 100644 templates/digest_template_html.txt diff --git a/MiniTemplator.class.php b/MiniTemplator.class.php new file mode 100644 index 00000000..69281cb5 --- /dev/null +++ b/MiniTemplator.class.php @@ -0,0 +1,922 @@ + +* Template syntax: +* +* Variables: +* ${VariableName} +* +* Blocks: +* <!-- $BeginBlock BlockName --> +* ... block content ... +* <!-- $EndBlock BlockName --> +* +* Include a subtemplate: +* <!-- $Include RelativeFileName --> +* +* +*
+* General remarks:
+*  - Variable names and block names are case-insensitive.
+*  - The same variable may be used multiple times within a template.
+*  - Blocks can be nested.
+*  - Multiple blocks with the same name may occur within a template.
+* 
+* +*
+* Public methods:
+*   readTemplateFromFile   - Reads the template from a file.
+*   setTemplateString      - Assigns a new template string.
+*   setVariable            - Sets a template variable.
+*   setVariableEsc         - Sets a template variable to an escaped string value.
+*   variableExists         - Checks whether a template variable exists.
+*   addBlock               - Adds an instance of a template block.
+*   blockExists            - Checks whether a block exists.
+*   reset                  - Clears all variables and blocks.
+*   generateOutput         - Generates the HTML page and writes it to the PHP output stream.
+*   generateOutputToFile   - Generates the HTML page and writes it to a file.
+*   generateOutputToString - Generates the HTML page and writes it to a string.
+* 
+* +* Home page: {@link http://www.source-code.biz/MiniTemplator}
+* License: This module is released under the GNU/LGPL license ({@link http://www.gnu.org/licenses/lgpl.html}).
+* Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland. All rights reserved.
+* This product is provided "as is" without warranty of any kind.
+* +* Version history:
+* 2001-10-24 Christian d'Heureuse (chdh): VBasic version created.
+* 2002-01-26 Markus Angst: ported to PHP4.
+* 2003-04-07 chdh: changes to adjust to Java version.
+* 2003-07-08 chdh: Method variableExists added. +* Method setVariable changed to trigger an error when the variable does not exist.
+* 2004-04-07 chdh: Parameter isOptional added to method setVariable. +* Licensing changed from GPL to LGPL.
+* 2004-04-18 chdh: Method blockExists added.
+* 2004-10-28 chdh:
+* Method setVariableEsc added.
+* Multiple blocks with the same name may now occur within a template.
+* No error ("unknown command") is generated any more, if a HTML comment starts with "${".
+* 2004-11-06 chdh:
+* "$Include" command implemented.
+* 2004-11-20 chdh:
+* "$Include" command changed so that the command text is not copied to the output file.
+*/ + +class MiniTemplator { + +//--- public member variables --------------------------------------------------------------------------------------- + +/** +* Base path for relative file names of subtemplates (for the $Include command). +* This path is prepended to the subtemplate file names. It must be set before +* readTemplateFromFile or setTemplateString. +* @access public +*/ +var $subtemplateBasePath; + +//--- private member variables -------------------------------------------------------------------------------------- + +/**#@+ +* @access private +*/ + +var $maxNestingLevel = 50; // maximum number of block nestings +var $maxInclTemplateSize = 1000000; // maximum length of template string when including subtemplates +var $template; // Template file data +var $varTab; // variables table, array index is variable no + // Fields: + // varName // variable name + // varValue // variable value +var $varTabCnt; // no of entries used in VarTab +var $varNameToNoMap; // maps variable names to variable numbers +var $varRefTab; // variable references table + // Contains an entry for each variable reference in the template. Ordered by TemplatePos. + // Fields: + // varNo // variable no + // tPosBegin // template position of begin of variable reference + // tPosEnd // template position of end of variable reference + // blockNo // block no of the (innermost) block that contains this variable reference + // blockVarNo // block variable no. Index into BlockInstTab.BlockVarTab +var $varRefTabCnt; // no of entries used in VarRefTab +var $blockTab; // Blocks table, array index is block no + // Contains an entry for each block in the template. Ordered by TPosBegin. + // Fields: + // blockName // block name + // nextWithSameName; // block no of next block with same name or -1 (blocks are backward linked in relation to template position) + // tPosBegin // template position of begin of block + // tPosContentsBegin // template pos of begin of block contents + // tPosContentsEnd // template pos of end of block contents + // tPosEnd // template position of end of block + // nestingLevel // block nesting level + // parentBlockNo // block no of parent block + // definitionIsOpen // true while $BeginBlock processed but no $EndBlock + // instances // number of instances of this block + // firstBlockInstNo // block instance no of first instance of this block or -1 + // lastBlockInstNo // block instance no of last instance of this block or -1 + // currBlockInstNo // current block instance no, used during generation of output file + // blockVarCnt // no of variables in block + // blockVarNoToVarNoMap // maps block variable numbers to variable numbers + // firstVarRefNo // variable reference no of first variable of this block or -1 +var $blockTabCnt; // no of entries used in BlockTab +var $blockNameToNoMap; // maps block names to block numbers +var $openBlocksTab; + // During parsing, this table contains the block numbers of the open parent blocks (nested outer blocks). + // Indexed by the block nesting level. +var $blockInstTab; // block instances table + // This table contains an entry for each block instance that has been added. + // Indexed by BlockInstNo. + // Fields: + // blockNo // block number + // instanceLevel // instance level of this block + // InstanceLevel is an instance counter per block. + // (In contrast to blockInstNo, which is an instance counter over the instances of all blocks) + // parentInstLevel // instance level of parent block + // nextBlockInstNo // pointer to next instance of this block or -1 + // Forward chain for instances of same block. + // blockVarTab // block instance variables +var $blockInstTabCnt; // no of entries used in BlockInstTab + +var $currentNestingLevel; // Current block nesting level during parsing. +var $templateValid; // true if a valid template is prepared +var $outputMode; // 0 = to PHP output stream, 1 = to file, 2 = to string +var $outputFileHandle; // file handle during writing of output file +var $outputError; // true when an output error occurred +var $outputString; // string buffer for the generated HTML page + +/**#@-*/ + +//--- constructor --------------------------------------------------------------------------------------------------- + +/** +* Constructs a MiniTemplator object. +* @access public +*/ +function MiniTemplator() { + $this->templateValid = false; } + +//--- template string handling -------------------------------------------------------------------------------------- + +/** +* Reads the template from a file. +* @param string $fileName name of the file that contains the template. +* @return boolean true on success, false on error. +* @access public +*/ +function readTemplateFromFile ($fileName) { + if (!$this->readFileIntoString($fileName,$s)) { + $this->triggerError ("Error while reading template file " . $fileName . "."); + return false; } + if (!$this->setTemplateString($s)) return false; + return true; } + +/** +* Assigns a new template string. +* @param string $templateString contents of the template file. +* @return boolean true on success, false on error. +* @access public +*/ +function setTemplateString ($templateString) { + $this->templateValid = false; + $this->template = $templateString; + if (!$this->parseTemplate()) return false; + $this->reset(); + $this->templateValid = true; + return true; } + +/** +* Loads the template string for a subtemplate (used for the $Include command). +* @return boolean true on success, false on error. +* @access private +*/ +function loadSubtemplate ($subtemplateName, &$s) { + $subtemplateFileName = $this->combineFileSystemPath($this->subtemplateBasePath,$subtemplateName); + if (!$this->readFileIntoString($subtemplateFileName,$s)) { + $this->triggerError ("Error while reading subtemplate file " . $subtemplateFileName . "."); + return false; } + return true; } + +//--- template parsing ---------------------------------------------------------------------------------------------- + +/** +* Parses the template. +* @return boolean true on success, false on error. +* @access private +*/ +function parseTemplate() { + $this->initParsing(); + $this->beginMainBlock(); + if (!$this->parseTemplateCommands()) return false; + $this->endMainBlock(); + if (!$this->checkBlockDefinitionsComplete()) return false; + if (!$this->parseTemplateVariables()) return false; + $this->associateVariablesWithBlocks(); + return true; } + +/** +* @access private +*/ +function initParsing() { + $this->varTab = array(); + $this->varTabCnt = 0; + $this->varNameToNoMap = array(); + $this->varRefTab = array(); + $this->varRefTabCnt = 0; + $this->blockTab = array(); + $this->blockTabCnt = 0; + $this->blockNameToNoMap = array(); + $this->openBlocksTab = array(); } + +/** +* Registers the main block. +* The main block is an implicitly defined block that covers the whole template. +* @access private +*/ +function beginMainBlock() { + $blockNo = 0; + $this->registerBlock('@@InternalMainBlock@@', $blockNo); + $bte =& $this->blockTab[$blockNo]; + $bte['tPosBegin'] = 0; + $bte['tPosContentsBegin'] = 0; + $bte['nestingLevel'] = 0; + $bte['parentBlockNo'] = -1; + $bte['definitionIsOpen'] = true; + $this->openBlocksTab[0] = $blockNo; + $this->currentNestingLevel = 1; } + +/** +* Completes the main block registration. +* @access private +*/ +function endMainBlock() { + $bte =& $this->blockTab[0]; + $bte['tPosContentsEnd'] = strlen($this->template); + $bte['tPosEnd'] = strlen($this->template); + $bte['definitionIsOpen'] = false; + $this->currentNestingLevel -= 1; } + +/** +* Parses commands within the template in the format "". +* @return boolean true on success, false on error. +* @access private +*/ +function parseTemplateCommands() { + $p = 0; + while (true) { + $p0 = strpos($this->template,'',$p0); + if ($p === false) { + $this->triggerError ("Invalid HTML comment in template at offset $p0."); + return false; } + $p += 3; + $cmdL = substr($this->template,$p0+4,$p-$p0-7); + if (!$this->processTemplateCommand($cmdL,$p0,$p,$resumeFromStart)) + return false; + if ($resumeFromStart) $p = $p0; } + return true; } + +/** +* @return boolean true on success, false on error. +* @access private +*/ +function processTemplateCommand ($cmdL, $cmdTPosBegin, $cmdTPosEnd, &$resumeFromStart) { + $resumeFromStart = false; + $p = 0; + $cmd = ''; + if (!$this->parseWord($cmdL,$p,$cmd)) return true; + $parms = substr($cmdL,$p); + switch (strtoupper($cmd)) { + case '$BEGINBLOCK': + if (!$this->processBeginBlockCmd($parms,$cmdTPosBegin,$cmdTPosEnd)) + return false; + break; + case '$ENDBLOCK': + if (!$this->processEndBlockCmd($parms,$cmdTPosBegin,$cmdTPosEnd)) + return false; + break; + case '$INCLUDE': + if (!$this->processincludeCmd($parms,$cmdTPosBegin,$cmdTPosEnd)) + return false; + $resumeFromStart = true; + break; + default: + if ($cmd{0} == '$' && !(strlen($cmd) >= 2 && $cmd{1} == '{')) { + $this->triggerError ("Unknown command \"$cmd\" in template at offset $cmdTPosBegin."); + return false; }} + return true; } + +/** +* Processes the $BeginBlock command. +* @return boolean true on success, false on error. +* @access private +*/ +function processBeginBlockCmd ($parms, $cmdTPosBegin, $cmdTPosEnd) { + $p = 0; + if (!$this->parseWord($parms,$p,$blockName)) { + $this->triggerError ("Missing block name in \$BeginBlock command in template at offset $cmdTPosBegin."); + return false; } + if (trim(substr($parms,$p)) != '') { + $this->triggerError ("Extra parameter in \$BeginBlock command in template at offset $cmdTPosBegin."); + return false; } + $this->registerBlock ($blockName, $blockNo); + $btr =& $this->blockTab[$blockNo]; + $btr['tPosBegin'] = $cmdTPosBegin; + $btr['tPosContentsBegin'] = $cmdTPosEnd; + $btr['nestingLevel'] = $this->currentNestingLevel; + $btr['parentBlockNo'] = $this->openBlocksTab[$this->currentNestingLevel-1]; + $this->openBlocksTab[$this->currentNestingLevel] = $blockNo; + $this->currentNestingLevel += 1; + if ($this->currentNestingLevel > $this->maxNestingLevel) { + $trhis->triggerError ("Block nesting overflow in template at offset $cmdTPosBegin."); + return false; } + return true; } + +/** +* Processes the $EndBlock command. +* @return boolean true on success, false on error. +* @access private +*/ +function processEndBlockCmd ($parms, $cmdTPosBegin, $cmdTPosEnd) { + $p = 0; + if (!$this->parseWord($parms,$p,$blockName)) { + $this->triggerError ("Missing block name in \$EndBlock command in template at offset $cmdTPosBegin."); + return false; } + if (trim(substr($parms,$p)) != '') { + $this->triggerError ("Extra parameter in \$EndBlock command in template at offset $cmdTPosBegin."); + return false; } + if (!$this->lookupBlockName($blockName,$blockNo)) { + $this->triggerError ("Undefined block name \"$blockName\" in \$EndBlock command in template at offset $cmdTPosBegin."); + return false; } + $this->currentNestingLevel -= 1; + $btr =& $this->blockTab[$blockNo]; + if (!$btr['definitionIsOpen']) { + $this->triggerError ("Multiple \$EndBlock command for block \"$blockName\" in template at offset $cmdTPosBegin."); + return false; } + if ($btr['nestingLevel'] != $this->currentNestingLevel) { + $this->triggerError ("Block nesting level mismatch at \$EndBlock command for block \"$blockName\" in template at offset $cmdTPosBegin."); + return false; } + $btr['tPosContentsEnd'] = $cmdTPosBegin; + $btr['tPosEnd'] = $cmdTPosEnd; + $btr['definitionIsOpen'] = false; + return true; } + +/** +* @access private +*/ +function registerBlock($blockName, &$blockNo) { + $blockNo = $this->blockTabCnt++; + $btr =& $this->blockTab[$blockNo]; + $btr = array(); + $btr['blockName'] = $blockName; + if (!$this->lookupBlockName($blockName,$btr['nextWithSameName'])) + $btr['nextWithSameName'] = -1; + $btr['definitionIsOpen'] = true; + $btr['instances'] = 0; + $btr['firstBlockInstNo'] = -1; + $btr['lastBlockInstNo'] = -1; + $btr['blockVarCnt'] = 0; + $btr['firstVarRefNo'] = -1; + $btr['blockVarNoToVarNoMap'] = array(); + $this->blockNameToNoMap[strtoupper($blockName)] = $blockNo; } + +/** +* Checks that all block definitions are closed. +* @return boolean true on success, false on error. +* @access private +*/ +function checkBlockDefinitionsComplete() { + for ($blockNo=0; $blockNo < $this->blockTabCnt; $blockNo++) { + $btr =& $this->blockTab[$blockNo]; + if ($btr['definitionIsOpen']) { + $this->triggerError ("Missing \$EndBlock command in template for block " . $btr['blockName'] . "."); + return false; }} + if ($this->currentNestingLevel != 0) { + $this->triggerError ("Block nesting level error at end of template."); + return false; } + return true; } + +/** +* Processes the $Include command. +* @return boolean true on success, false on error. +* @access private +*/ +function processIncludeCmd ($parms, $cmdTPosBegin, $cmdTPosEnd) { + $p = 0; + if (!$this->parseWordOrQuotedString($parms,$p,$subtemplateName)) { + $this->triggerError ("Missing or invalid subtemplate name in \$Include command in template at offset $cmdTPosBegin."); + return false; } + if (trim(substr($parms,$p)) != '') { + $this->triggerError ("Extra parameter in \$include command in template at offset $cmdTPosBegin."); + return false; } + return $this->insertSubtemplate($subtemplateName,$cmdTPosBegin,$cmdTPosEnd); } + +/** +* Processes the $Include command. +* @return boolean true on success, false on error. +* @access private +*/ +function insertSubtemplate ($subtemplateName, $tPos1, $tPos2) { + if (strlen($this->template) > $this->maxInclTemplateSize) { + $this->triggerError ("Subtemplate include aborted because the internal template string is longer than $this->maxInclTemplateSize characters."); + return false; } + if (!$this->loadSubtemplate($subtemplateName,$subtemplate)) return false; + // (Copying the template to insert a subtemplate is a bit slow. In a future implementation of MiniTemplator, + // a table could be used that contains references to the string fragments.) + $this->template = substr($this->template,0,$tPos1) . $subtemplate . substr($this->template,$tPos2); + return true; } + +/** +* Parses variable references within the template in the format "${VarName}". +* @return boolean true on success, false on error. +* @access private +*/ +function parseTemplateVariables() { + $p = 0; + while (true) { + $p = strpos($this->template, '${', $p); + if ($p === false) break; + $p0 = $p; + $p = strpos($this->template, '}', $p); + if ($p === false) { + $this->triggerError ("Invalid variable reference in template at offset $p0."); + return false; } + $p += 1; + $varName = trim(substr($this->template, $p0+2, $p-$p0-3)); + if (strlen($varName) == 0) { + $this->triggerError ("Empty variable name in template at offset $p0."); + return false; } + $this->registerVariableReference ($varName, $p0, $p); } + return true; } + +/** +* @access private +*/ +function registerVariableReference ($varName, $tPosBegin, $tPosEnd) { + if (!$this->lookupVariableName($varName,$varNo)) + $this->registerVariable($varName,$varNo); + $varRefNo = $this->varRefTabCnt++; + $vrtr =& $this->varRefTab[$varRefNo]; + $vrtr = array(); + $vrtr['tPosBegin'] = $tPosBegin; + $vrtr['tPosEnd'] = $tPosEnd; + $vrtr['varNo'] = $varNo; } + +/** +* @access private +*/ +function registerVariable ($varName, &$varNo) { + $varNo = $this->varTabCnt++; + $vtr =& $this->varTab[$varNo]; + $vtr = array(); + $vtr['varName'] = $varName; + $vtr['varValue'] = ''; + $this->varNameToNoMap[strtoupper($varName)] = $varNo; } + +/** +* Associates variable references with blocks. +* @access private +*/ +function associateVariablesWithBlocks() { + $varRefNo = 0; + $activeBlockNo = 0; + $nextBlockNo = 1; + while ($varRefNo < $this->varRefTabCnt) { + $vrtr =& $this->varRefTab[$varRefNo]; + $varRefTPos = $vrtr['tPosBegin']; + $varNo = $vrtr['varNo']; + if ($varRefTPos >= $this->blockTab[$activeBlockNo]['tPosEnd']) { + $activeBlockNo = $this->blockTab[$activeBlockNo]['parentBlockNo']; + continue; } + if ($nextBlockNo < $this->blockTabCnt) { + if ($varRefTPos >= $this->blockTab[$nextBlockNo]['tPosBegin']) { + $activeBlockNo = $nextBlockNo; + $nextBlockNo += 1; + continue; }} + $btr =& $this->blockTab[$activeBlockNo]; + if ($varRefTPos < $btr['tPosBegin']) + $this->programLogicError(1); + $blockVarNo = $btr['blockVarCnt']++; + $btr['blockVarNoToVarNoMap'][$blockVarNo] = $varNo; + if ($btr['firstVarRefNo'] == -1) + $btr['firstVarRefNo'] = $varRefNo; + $vrtr['blockNo'] = $activeBlockNo; + $vrtr['blockVarNo'] = $blockVarNo; + $varRefNo += 1; }} + +//--- build up (template variables and blocks) ---------------------------------------------------------------------- + +/** +* Clears all variables and blocks. +* This method can be used to produce another HTML page with the same +* template. It is faster than creating another MiniTemplator object, +* because the template does not have to be parsed again. +* All variable values are cleared and all added block instances are deleted. +* @access public +*/ +function reset() { + for ($varNo=0; $varNo<$this->varTabCnt; $varNo++) + $this->varTab[$varNo]['varValue'] = ''; + for ($blockNo=0; $blockNo<$this->blockTabCnt; $blockNo++) { + $btr =& $this->blockTab[$blockNo]; + $btr['instances'] = 0; + $btr['firstBlockInstNo'] = -1; + $btr['lastBlockInstNo'] = -1; } + $this->blockInstTab = array(); + $this->blockInstTabCnt = 0; } + +/** +* Sets a template variable. +* For variables that are used in blocks, the variable value +* must be set before {@link addBlock} is called. +* @param string $variableName the name of the variable to be set. +* @param string $variableValue the new value of the variable. +* @param boolean $isOptional Specifies whether an error should be +* generated when the variable does not exist in the template. If +* $isOptional is false and the variable does not exist, an error is +* generated. +* @return boolean true on success, or false on error (e.g. when no +* variable with the specified name exists in the template and +* $isOptional is false). +* @access public +*/ +function setVariable ($variableName, $variableValue, $isOptional=false) { + if (!$this->templateValid) {$this->triggerError ("Template not valid."); return false; } + if (!$this->lookupVariableName($variableName,$varNo)) { + if ($isOptional) return true; + $this->triggerError ("Variable \"$variableName\" not defined in template."); + return false; } + $this->varTab[$varNo]['varValue'] = $variableValue; + return true; } + +/** +* Sets a template variable to an escaped string. +* This method is identical to (@link setVariable), except that +* the characters <, >, &, ' and " of variableValue are +* replaced by their corresponding HTML/XML character entity codes. +* For variables that are used in blocks, the variable value +* must be set before {@link addBlock} is called. +* @param string $variableName the name of the variable to be set. +* @param string $variableValue the new value of the variable. Special HTML/XML characters are escaped. +* @param boolean $isOptional Specifies whether an error should be +* generated when the variable does not exist in the template. If +* $isOptional is false and the variable does not exist, an error is +* generated. +* @return boolean true on success, or false on error (e.g. when no +* variable with the specified name exists in the template and +* $isOptional is false). +* @access public +*/ +function setVariableEsc ($variableName, $variableValue, $isOptional=false) { + return $this->setVariable($variableName,htmlspecialchars($variableValue,ENT_QUOTES),$isOptional); } + +/** +* Checks whether a variable with the specified name exists within the template. +* @param string $variableName the name of the variable. +* @return boolean true if the variable exists, or false when no +* variable with the specified name exists in the template. +* @access public +*/ +function variableExists ($variableName) { + if (!$this->templateValid) {$this->triggerError ("Template not valid."); return false; } + return $this->lookupVariableName($variableName,$varNo); } + +/** +* Adds an instance of a template block. +* If the block contains variables, these variables must be set +* before the block is added. +* If the block contains subblocks (nested blocks), the subblocks +* must be added before this block is added. +* If multiple blocks exist with the specified name, an instance +* is added for each block occurence. +* @param string blockName the name of the block to be added. +* @return boolean true on success, false on error (e.g. when no +* block with the specified name exists in the template). +* @access public +*/ +function addBlock($blockName) { + if (!$this->templateValid) {$this->triggerError ("Template not valid."); return false; } + if (!$this->lookupBlockName($blockName,$blockNo)) { + $this->triggerError ("Block \"$blockName\" not defined in template."); + return false; } + while ($blockNo != -1) { + $this->addBlockByNo($blockNo); + $blockNo = $this->blockTab[$blockNo]['nextWithSameName']; } + return true; } + +/** +* @access private +*/ +function addBlockByNo ($blockNo) { + $btr =& $this->blockTab[$blockNo]; + $this->registerBlockInstance ($blockInstNo); + $bitr =& $this->blockInstTab[$blockInstNo]; + if ($btr['firstBlockInstNo'] == -1) + $btr['firstBlockInstNo'] = $blockInstNo; + if ($btr['lastBlockInstNo'] != -1) + $this->blockInstTab[$btr['lastBlockInstNo']]['nextBlockInstNo'] = $blockInstNo; + // set forward pointer of chain + $btr['lastBlockInstNo'] = $blockInstNo; + $parentBlockNo = $btr['parentBlockNo']; + $blockVarCnt = $btr['blockVarCnt']; + $bitr['blockNo'] = $blockNo; + $bitr['instanceLevel'] = $btr['instances']++; + if ($parentBlockNo == -1) + $bitr['parentInstLevel'] = -1; + else + $bitr['parentInstLevel'] = $this->blockTab[$parentBlockNo]['instances']; + $bitr['nextBlockInstNo'] = -1; + $bitr['blockVarTab'] = array(); + // copy instance variables for this block + for ($blockVarNo=0; $blockVarNo<$blockVarCnt; $blockVarNo++) { + $varNo = $btr['blockVarNoToVarNoMap'][$blockVarNo]; + $bitr['blockVarTab'][$blockVarNo] = $this->varTab[$varNo]['varValue']; }} + +/** +* @access private +*/ +function registerBlockInstance (&$blockInstNo) { + $blockInstNo = $this->blockInstTabCnt++; } + +/** +* Checks whether a block with the specified name exists within the template. +* @param string $blockName the name of the block. +* @return boolean true if the block exists, or false when no +* block with the specified name exists in the template. +* @access public +*/ +function blockExists ($blockName) { + if (!$this->templateValid) {$this->triggerError ("Template not valid."); return false; } + return $this->lookupBlockName($blockName,$blockNo); } + +//--- output generation --------------------------------------------------------------------------------------------- + +/** +* Generates the HTML page and writes it to the PHP output stream. +* @return boolean true on success, false on error. +* @access public +*/ +function generateOutput () { + $this->outputMode = 0; + if (!$this->generateOutputPage()) return false; + return true; } + +/** +* Generates the HTML page and writes it to a file. +* @param string $fileName name of the output file. +* @return boolean true on success, false on error. +* @access public +*/ +function generateOutputToFile ($fileName) { + $fh = fopen($fileName,"wb"); + if ($fh === false) return false; + $this->outputMode = 1; + $this->outputFileHandle = $fh; + $ok = $this->generateOutputPage(); + fclose ($fh); + return $ok; } + +/** +* Generates the HTML page and writes it to a string. +* @param string $outputString variable that receives +* the contents of the generated HTML page. +* @return boolean true on success, false on error. +* @access public +*/ +function generateOutputToString (&$outputString) { + $outputString = "Error"; + $this->outputMode = 2; + $this->outputString = ""; + if (!$this->generateOutputPage()) return false; + $outputString = $this->outputString; + return true; } + +/** +* @access private +* @return boolean true on success, false on error. +*/ +function generateOutputPage() { + if (!$this->templateValid) {$this->triggerError ("Template not valid."); return false; } + if ($this->blockTab[0]['instances'] == 0) + $this->addBlockByNo (0); // add main block + for ($blockNo=0; $blockNo < $this->blockTabCnt; $blockNo++) { + $btr =& $this->blockTab[$blockNo]; + $btr['currBlockInstNo'] = $btr['firstBlockInstNo']; } + $this->outputError = false; + $this->writeBlockInstances (0, -1); + if ($this->outputError) return false; + return true; } + +/** +* Writes all instances of a block that are contained within a specific +* parent block instance. +* Called recursively. +* @access private +*/ +function writeBlockInstances ($blockNo, $parentInstLevel) { + $btr =& $this->blockTab[$blockNo]; + while (!$this->outputError) { + $blockInstNo = $btr['currBlockInstNo']; + if ($blockInstNo == -1) break; + $bitr =& $this->blockInstTab[$blockInstNo]; + if ($bitr['parentInstLevel'] < $parentInstLevel) + $this->programLogicError (2); + if ($bitr['parentInstLevel'] > $parentInstLevel) break; + $this->writeBlockInstance ($blockInstNo); + $btr['currBlockInstNo'] = $bitr['nextBlockInstNo']; }} + +/** +* @access private +*/ +function writeBlockInstance($blockInstNo) { + $bitr =& $this->blockInstTab[$blockInstNo]; + $blockNo = $bitr['blockNo']; + $btr =& $this->blockTab[$blockNo]; + $tPos = $btr['tPosContentsBegin']; + $subBlockNo = $blockNo + 1; + $varRefNo = $btr['firstVarRefNo']; + while (!$this->outputError) { + $tPos2 = $btr['tPosContentsEnd']; + $kind = 0; // assume end-of-block + if ($varRefNo != -1 && $varRefNo < $this->varRefTabCnt) { // check for variable reference + $vrtr =& $this->varRefTab[$varRefNo]; + if ($vrtr['tPosBegin'] < $tPos) { + $varRefNo += 1; + continue; } + if ($vrtr['tPosBegin'] < $tPos2) { + $tPos2 = $vrtr['tPosBegin']; + $kind = 1; }} + if ($subBlockNo < $this->blockTabCnt) { // check for subblock + $subBtr =& $this->blockTab[$subBlockNo]; + if ($subBtr['tPosBegin'] < $tPos) { + $subBlockNo += 1; + continue; } + if ($subBtr['tPosBegin'] < $tPos2) { + $tPos2 = $subBtr['tPosBegin']; + $kind = 2; }} + if ($tPos2 > $tPos) + $this->writeString (substr($this->template,$tPos,$tPos2-$tPos)); + switch ($kind) { + case 0: // end of block + return; + case 1: // variable + $vrtr =& $this->varRefTab[$varRefNo]; + if ($vrtr['blockNo'] != $blockNo) + $this->programLogicError (4); + $variableValue = $bitr['blockVarTab'][$vrtr['blockVarNo']]; + $this->writeString ($variableValue); + $tPos = $vrtr['tPosEnd']; + $varRefNo += 1; + break; + case 2: // sub block + $subBtr =& $this->blockTab[$subBlockNo]; + if ($subBtr['parentBlockNo'] != $blockNo) + $this->programLogicError (3); + $this->writeBlockInstances ($subBlockNo, $bitr['instanceLevel']); // recursive call + $tPos = $subBtr['tPosEnd']; + $subBlockNo += 1; + break; }}} + +/** +* @access private +*/ +function writeString ($s) { + if ($this->outputError) return; + switch ($this->outputMode) { + case 0: // output to PHP output stream + if (!print($s)) + $this->outputError = true; + break; + case 1: // output to file + $rc = fwrite($this->outputFileHandle, $s); + if ($rc === false) $this->outputError = true; + break; + case 2: // output to string + $this->outputString .= $s; + break; }} + +//--- name lookup routines ------------------------------------------------------------------------------------------ + +/** +* Maps variable name to variable number. +* @return boolean true on success, false if the variable is not found. +* @access private +*/ +function lookupVariableName ($varName, &$varNo) { + $x =& $this->varNameToNoMap[strtoupper($varName)]; + if (!isset($x)) return false; + $varNo = $x; + return true; } + +/** +* Maps block name to block number. +* If there are multiple blocks with the same name, the block number of the last +* registered block with that name is returned. +* @return boolean true on success, false when the block is not found. +* @access private +*/ +function lookupBlockName ($blockName, &$blockNo) { + $x =& $this->blockNameToNoMap[strtoupper($blockName)]; + if (!isset($x)) return false; + $blockNo = $x; + return true; } + +//--- general utility routines ----------------------------------------------------------------------------------------- + +/** +* Reads a file into a string. +* @return boolean true on success, false on error. +* @access private +*/ +function readFileIntoString ($fileName, &$s) { + if (function_exists('version_compare') && version_compare(phpversion(),"4.3.0",">=")) { + $s = file_get_contents($fileName); + if ($s === false) return false; + return true; } + $fh = fopen($fileName,"rb"); + if ($fh === false) return false; + $fileSize = filesize($fileName); + if ($fileSize === false) {close ($fh); return false; } + $s = fread($fh,$fileSize); + fclose ($fh); + if (strlen($s) != $fileSize) return false; + return true; } + +/** +* @access private +* @return boolean true on success, false when the end of the string is reached. +*/ +function parseWord ($s, &$p, &$w) { + $sLen = strlen($s); + while ($p < $sLen && ord($s{$p}) <= 32) $p++; + if ($p >= $sLen) return false; + $p0 = $p; + while ($p < $sLen && ord($s{$p}) > 32) $p++; + $w = substr($s, $p0, $p - $p0); + return true; } + +/** +* @access private +* @return boolean true on success, false on error. +*/ +function parseQuotedString ($s, &$p, &$w) { + $sLen = strlen($s); + while ($p < $sLen && ord($s{$p}) <= 32) $p++; + if ($p >= $sLen) return false; + if (substr($s,$p,1) != '"') return false; + $p++; $p0 = $p; + while ($p < $sLen && $s{$p} != '"') $p++; + if ($p >= $sLen) return false; + $w = substr($s, $p0, $p - $p0); + $p++; + return true; } + +/** +* @access private +* @return boolean true on success, false on error. +*/ +function parseWordOrQuotedString ($s, &$p, &$w) { + $sLen = strlen($s); + while ($p < $sLen && ord($s{$p}) <= 32) $p++; + if ($p >= $sLen) return false; + if (substr($s,$p,1) == '"') + return $this->parseQuotedString($s,$p,$w); + else + return $this->parseWord($s,$p,$w); } + +/** +* Combine two file system paths. +* @access private +*/ +function combineFileSystemPath ($path1, $path2) { + if ($path1 == '' || $path2 == '') return $path2; + $s = $path1; + if (substr($s,-1) != '\\' && substr($s,-1) != '/') $s = $s . "/"; + if (substr($path2,0,1) == '\\' || substr($path2,0,1) == '/') + $s = $s . substr($path2,1); + else + $s = $s . $path2; + return $s; } + +/** +* @access private +*/ +function triggerError ($msg) { + trigger_error ("MiniTemplator error: $msg", E_USER_ERROR); } + +/** +* @access private +*/ +function programLogicError ($errorId) { + die ("MiniTemplator: Program logic error $errorId.\n"); } + +} +?> diff --git a/config.php-dist b/config.php-dist index 05ec08ea..6da8eb1f 100644 --- a/config.php-dist +++ b/config.php-dist @@ -105,9 +105,6 @@ define('DIGEST_ENABLE', true); // Global option to enable daily digests - define('DIGEST_HOSTNAME', 'your.domain.dom'); - // Hostname for email digest signature - define('DIGEST_EMAIL_LIMIT', 10); // The maximum amount of emails sent in one digest batch diff --git a/functions.php b/functions.php index 9e9eb6f3..2303f54a 100644 --- a/functions.php +++ b/functions.php @@ -3208,47 +3208,40 @@ $digest = $tuple[0]; $headlines_count = $tuple[1]; $affected_ids = $tuple[2]; + $digest_text = $tuple[3]; if ($headlines_count > 0) { - if (!DIGEST_SMTP_HOST) { + $mail = new PHPMailer(); - $rc = mail($line["login"] . " <" . $line["email"] . ">", - "[tt-rss] New headlines for last 24 hours", $digest, - "From: " . DIGEST_FROM_NAME . " <" . DIGEST_FROM_ADDRESS . ">\n". - "Content-Type: text/plain; charset=\"utf-8\"\n". - "Content-Transfer-Encoding: 8bit\n"); + $mail->PluginDir = "phpmailer/"; + $mail->SetLanguage("en", "phpmailer/language/"); - } else { - - $mail = new PHPMailer(); - - $mail->PluginDir = "phpmailer/"; - $mail->SetLanguage("en", "phpmailer/language/"); + $mail->CharSet = "UTF-8"; - $mail->CharSet = "UTF-8"; + $mail->From = DIGEST_FROM_ADDRESS; + $mail->FromName = DIGEST_FROM_NAME; + $mail->AddAddress($line["email"], $line["login"]); - $mail->From = DIGEST_FROM_ADDRESS; - $mail->FromName = DIGEST_FROM_NAME; - $mail->AddAddress($line["email"], $line["login"]); + if (DIGEST_SMTP_HOST) { $mail->Host = DIGEST_SMTP_HOST; $mail->Mailer = "smtp"; - $mail->Username = DIGEST_SMTP_LOGIN; $mail->Password = DIGEST_SMTP_PASSWORD; + } - $mail->Subject = "[tt-rss] New headlines for last 24 hours"; - $mail->Body = $digest; + $mail->IsHTML(true); + $mail->Subject = "[tt-rss] New headlines for last 24 hours"; + $mail->Body = $digest; + $mail->AltBody = $digest_text; - $rc = $mail->Send(); + $rc = $mail->Send(); - if (!$rc) print "ERROR: " . $mail->ErrorInfo; - - } + if (!$rc) print "ERROR: " . $mail->ErrorInfo; print "RC=$rc\n"; - if ($rc) { + if ($rc && $do_catchup) { print "Marking affected articles as read...\n"; catchupArticlesById($link, $affected_ids, 0, $line["id"]); } @@ -3261,15 +3254,25 @@ } } -// $digest = prepare_headlines_digest($link, $user_id, $days, $limit); - print "All done.\n"; } function prepare_headlines_digest($link, $user_id, $days = 1, $limit = 100) { - $tmp = __("New headlines for last 24 hours, as of ") . date("Y/m/d H:m") . "\n"; - $tmp .= "=======================================================\n\n"; + + require_once "MiniTemplator.class.php"; + + $tpl = new MiniTemplator; + $tpl_t = new MiniTemplator; + + $tpl->readTemplateFromFile("templates/digest_template_html.txt"); + $tpl_t->readTemplateFromFile("templates/digest_template.txt"); + + $tpl->setVariable('CUR_DATE', date('Y/m/d')); + $tpl->setVariable('CUR_TIME', date('G:i')); + + $tpl_t->setVariable('CUR_DATE', date('Y/m/d')); + $tpl_t->setVariable('CUR_TIME', date('G:i')); $affected_ids = array(); @@ -3284,6 +3287,7 @@ date_entered, ttrss_user_entries.ref_id, link, + SUBSTRING(content, 1, 120) AS excerpt, SUBSTRING(last_updated,1,19) AS last_updated FROM ttrss_user_entries,ttrss_entries,ttrss_feeds @@ -3293,38 +3297,60 @@ AND $interval_query AND hidden = false AND ttrss_user_entries.owner_uid = $user_id - AND unread = true ORDER BY ttrss_feeds.title, date_entered DESC + AND unread = true + ORDER BY ttrss_feeds.title, date_entered DESC LIMIT $limit"); $cur_feed_title = ""; $headlines_count = db_num_rows($result); + $headlines = array(); + while ($line = db_fetch_assoc($result)) { + array_push($headlines, $line); + } + + for ($i = 0; $i < sizeof($headlines); $i++) { + + $line = $headlines[$i]; array_push($affected_ids, $line["ref_id"]); $updated = smart_date_time(strtotime($line["last_updated"])); - $feed_title = $line["feed_title"]; - if ($cur_feed_title != $feed_title) { - $cur_feed_title = $feed_title; + $tpl->setVariable('FEED_TITLE', $line["feed_title"]); + $tpl->setVariable('ARTICLE_TITLE', $line["title"]); + $tpl->setVariable('ARTICLE_LINK', $line["link"]); + $tpl->setVariable('ARTICLE_UPDATED', $updated); +// $tpl->setVariable('ARTICLE_EXCERPT', +// truncate_string(strip_tags($line["excerpt"]), 100)); - $tmp .= "$feed_title\n\n"; + $tpl->addBlock('article'); + + $tpl_t->setVariable('FEED_TITLE', $line["feed_title"]); + $tpl_t->setVariable('ARTICLE_TITLE', $line["title"]); + $tpl_t->setVariable('ARTICLE_LINK', $line["link"]); + $tpl_t->setVariable('ARTICLE_UPDATED', $updated); +// $tpl_t->setVariable('ARTICLE_EXCERPT', +// truncate_string(strip_tags($line["excerpt"]), 100)); + + $tpl_t->addBlock('article'); + + if ($headlines[$i]['feed_title'] != $headlines[$i+1]['feed_title']) { + $tpl->addBlock('feed'); + $tpl_t->addBlock('feed'); } - $tmp .= " * " . trim($line["title"]) . " - $updated\n"; - $tmp .= " " . trim($line["link"]) . "\n"; - $tmp .= "\n"; } - $tmp .= "--- \n"; - $tmp .= __("You have been sent this email because you have enabled daily digests in Tiny Tiny RSS at ") . - DIGEST_HOSTNAME . "\n". - __("To unsubscribe, visit your configuration options or contact instance owner.\n"); - + $tpl->addBlock('digest'); + $tpl->generateOutputToString($tmp); + + $tpl_t->addBlock('digest'); + $tpl_t->generateOutputToString($tmp_t); - return array($tmp, $headlines_count, $affected_ids); + return array($tmp, $headlines_count, $affected_ids, $tmp_t); } function check_for_update($link, $brief_fmt = true) { diff --git a/locale/fr_FR/LC_MESSAGES/messages.mo b/locale/fr_FR/LC_MESSAGES/messages.mo index 4802cdc1134d13cf1e387d802d68ed01a7dc6d94..e7279c7b671bb865ee6623681d48aff739e84788 100644 GIT binary patch delta 8492 zcmYk>30&7j{>SkF5l}>KxdeV7ihvi2Al_(#w_#q0sd$T5nu%BaES0vS$1k`C7G4BZfRET>;0SY@!0R9@j0LQUNfJW`GR)f@xV=w1bRP< z4%%Tj_68W!5`)5xX&-3J#YD9l^KgbS!MG38@JUR<Zd<8UNK@qROliU*gY9=sb#jX8jN@e7!Ye@Bh*9O}BOE^gA+ z82VyTodb|$nYoyY+mK|LmtFhk7);zao56-qX+|X!W3daSU<8(76RbpybdGCZhU&n2 z)JS(>S9}8X;!jZ>3dpe?Zi}6Xdtqa|1EX+B4*6Fq*3qEU{~u}*zKD9k`=}0{N8Rwf zYY$*pEr_F0i!d9tIQwG#yqDKBAmf=P0jlJom-gmc`$_y%-Q4hL; z>d?=q7Y5KxJunH?o`K<*jS*PrEJbyAEC%5;Y=X1h`8!c-XEiEwJ5kT~9;BiN9!K@~ zebfstqEdPVm4Vn!#;~)D2erRTQ0J#P*I*>^e%z1GqwX7@XPtrS*dkQNs*(44&An8Z zR$EXxvKxN`G@=-G(tQ>s@a!{%3hq|uZIT=ZknTZ-m9V)edMt!(GMvb_0zU^>N z)Km?|VBT-WQqctyQ6rv(>iJUC$X26XxC52KJvadOp|~)bsvOK>jr+M`+LkKE^=&5;c+rrzy1iHo@5$qd7kmHGoOZ6{w8WVGDc; z)zPCEi=U#V<_C>3`KdVC`H{-sp*eets_u9oQVEygIcxK=>H*wdeAP^-0w%F z_z-GWypDWA%xO%-knVP%>F6OYLS@D~o=Pf}YE+LObSDnE_P0?Tx`gWB4b%(5de|2y zqB@d|nvyQg5?n!CjtttILS?9VPn*GHOxFI-ppw9e-l(YI=_W!$7l)7)QH3sm3R-A=;P%l)9 zhoYup0_s7PsE#Z~b$A=7-tbYTnB9JfZLs=c$j zYcEBmdIWl~95p4&(LX{|2X~@IxEI^tUs0L8h{{+{Uw#Y1H1y_C8AC<;d>yI-2T&b2 zg%}j+gbb9jw51#FP7xfAx4X4fbd7oyThS&b|U^DOE)KVrD{f8ecl#E}@ni4<&tt+7&T12xjxGMmDksMY@*YL4G= zeveVa%|_Z0rlP(NeK8y-pq^WW(YP4>zyIG)MIVlb)PM(Fe9Xlk;0oHm#f-pZcCqH5GFOCJOU0;xl%QTX4m~&nwV3aB@t(2dKZ1rMG$@rPQ7^dQ3}Vwa zCr(A3Z;wj-VANu)LVt&`koaNeX=h|P^H2Lg?1nYi7hgqn*ouiIGY!}euVWteW-I80cc8Z6Q`iHKqt;T;1UuznUMk5nq@y0# z3%lU$*b-||J^eju#D7F}>~+k<&(VXyx7$x@7UmO=!WvwU8!>VsKR0j>cEXF;3%x0m zY>z5Xb29}au^RQlb*_C6#uGn_Nq7RM;1{U5E}d*UP>vdL4YtO|P$T~bmS9LFfAhuR zn4A&+L!?LMGAiW}(`>5Zu^I6|EWpvIk!?av)pMwneua8r{B-{Ef}K#A z{0X(lLuc6Ck$_q=DVW6jO(!aSa0u##ji?mvL8bOEYCoSu?S>Csdjsl0Kcg}dKGXia zAOkg^S*Yt*p`No9GjJa&(|$L|lVQ zaU-hZL38YbV=$XI2Q_7*Py?yNrnt(rZ$v$R=N$6iipl{R^6@Rq#l~}OoQEBVXP~BL z2P(CXV;g)0)qyWj9lwHFl+EYa4^k#7LlaP$n~r);9co}tdZ~1zastvyhSY#b_;3o#wnp$76hR7c))HlUs#xWIP2GwORY7}Zhl3@UojO4NgQV;UYp z559+u@js}MTt{^@=ngxl(WohDiAr%gDz)vfJ@&=6I3Ja~a{wPM_v(DF0nK|X+&zzTV3+;i6?Y{%mqMp-$TJ*nR zF7G#?ci9f)qdHK5T7+v+Q}Qf!z}MaRYp4;lT4LL8MWxz{(fAB%N{?b6JcG(iTD8qw zAM8(DiC(?nF)B*oE7%i1LVYOWm)fc6j&a0;FbpT57UdjNhSs_G52zQNMBV=_>ba52 ztnJW4JP>t$_A>IXMYD;9c&tOE_8_YLm}`FnV~M{&O~ExR!jR>5jTEEKSD>ci4lKrH z*bNV(cE=S|CKFZ|GYm^tkpHPvcF>@dUPC>g4WF$a2(FXJp3!Fqd&Rx zfp^>M5>Nx`fM>A;V=(I;o53Ea4wibU1XEd$x8OF^VmyT*_zU*NAUeuMG5t~PhfvqO zjN9-WuEoWx_z4)m&jeJ*e!16}2QcJ5d;K2FCw>hp(0i3iH8+e}ZAbLR8oS?r!$>X& z;;AwYm5DZ}%yhvd9EOc>7HS}Ku@LV>W%Oy(6r9EgjHu8d(LV<5YWr zS&K^L4%F^=26ONO)OREBetSL&bze3f$04W}$F8#}ABM@q<(P_hVX5~21MY%Puni{~ zP!~q5w;jvH7Q_Qk9hiU`NeybzJ&4?5o<^lQe}mnICs3LB1ery17ISdYMw^)pSit+u zpQud3@2~`K+hqSw$1WU1T)LTg#ah%<1oKrHiSejaT!rQMf{UZK+Bu$#qiNrPgYg?& ziUr$jMh;?`w%cJU33w6}e}!7DSCOURKVIcejpF9a$(@GU{C@uekVr>c3LoggQ3*qLO18 zFC{AUWhdu)28cO}TkINIjXdjk2A>H^+alJWM$8%_Eok4TAS6 zlc@K=ZulvVz!b`d)N3j8sq54J0%ZneA!Rjf^8$P$TXvooL3IM4UDp?o^%ayl;x{Nc)DLK3 z?I##VpyLc>3H6bbpQxXsR8sGV-%{pL5{N@7zfspQN9QRmC_0KLe1*+;;uY9jbxK#_ zYsjB{O^+Q(9V*Ei1--*p$Y_h{*< zW{ybWf1=MH@o^v?PCdoNZ(#@Di=MQ^g`DwF^z*iuRv+qE>$~j9^^PK1MU+Xo-JQ8Y zeJ1q^)X~LaYH4fluDR&is+_U3Z>5Z(Y@%(5YtO*e?w(9+<=Vv>I{_?el1jaVvey@o5g)MJmza^|T}*r*C7ttY@DjG6?4}GQ z{s#X;=}dhPPNwKcB-Swn`?z{9;!gfnehH%OysL{}C=LG;-^uxZ>vx|gXlzLkR(~QR zIkvu8;pxcwyn)XL`5rAvtS=vy85G*3lP9lp_xytTwPo2UzK{js^}o!oj;}vcb2vC) Ts4rl0jL%aORo`XHwV?k3F{kCU delta 8986 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\n" "Language-Team: Français \n" @@ -146,16 +146,16 @@ msgstr "" "Votre version de MySQL n'est pas gérée pour le moment. Reportez-vous au \n" "\t\tsite officiel pour plus d'informations." -#: functions.php:2286 functions.php:2625 functions.php:2985 functions.php:3760 +#: functions.php:2286 functions.php:2625 functions.php:2985 functions.php:3772 msgid "Starred articles" msgstr "Articles remarquables" -#: functions.php:2295 functions.php:2627 functions.php:2987 functions.php:3767 +#: functions.php:2295 functions.php:2627 functions.php:2987 functions.php:3779 #: modules/pref-feeds.php:1068 msgid "Published articles" msgstr "Articles publiés" -#: functions.php:2304 functions.php:2629 functions.php:2989 functions.php:3745 +#: functions.php:2304 functions.php:2629 functions.php:2989 functions.php:3757 msgid "Fresh articles" msgstr "Nouveaux articles" @@ -164,8 +164,8 @@ msgstr "Nouveaux articles" msgid "All feeds" msgstr "Tous les flux" -#: functions.php:2576 functions.php:2615 functions.php:2963 functions.php:3924 -#: functions.php:3954 modules/pref-feeds.php:880 +#: functions.php:2576 functions.php:2615 functions.php:2963 functions.php:3936 +#: functions.php:3966 modules/pref-feeds.php:880 msgid "Uncategorized" msgstr "Sans catégorie" @@ -185,142 +185,123 @@ msgstr "Résultats de recherche" msgid "Searched for" msgstr "Recherché" -#: functions.php:3271 -msgid "New headlines for last 24 hours, as of " -msgstr "Nouveaux en-têtes dans les dernières 24 heures, à compter de " - -#: functions.php:3322 -msgid "" -"You have been sent this email because you have enabled daily digests in Tiny " -"Tiny RSS at " -msgstr "" -"Vous recevez ce courrier électronique parce que vous avez activé la synthèse " -"quotidienne dans TIny Tiny RSS sur " - -#: functions.php:3324 -msgid "" -"To unsubscribe, visit your configuration options or contact instance owner.\n" -msgstr "" -"Pour vous désinscrire, modifiez votre configuration ou contactez " -"l'administrateur de votre TIny Tiny RSS.\n" - -#: functions.php:3555 functions.php:3602 functions.php:4650 +#: functions.php:3567 functions.php:3614 functions.php:4662 #: modules/pref-feeds.php:655 modules/pref-feeds.php:842 #: modules/pref-filters.php:255 modules/pref-labels.php:234 #: modules/pref-users.php:208 msgid "Select:" msgstr "Sélectionner :" -#: functions.php:3556 functions.php:3603 modules/pref-feeds.php:656 +#: functions.php:3568 functions.php:3615 modules/pref-feeds.php:656 #: modules/pref-feeds.php:843 modules/pref-filters.php:256 #: modules/pref-labels.php:235 modules/pref-users.php:209 msgid "All" msgstr "Tout" -#: functions.php:3557 functions.php:3561 functions.php:3604 functions.php:3607 +#: functions.php:3569 functions.php:3573 functions.php:3616 functions.php:3619 #: tt-rss.php:165 msgid "Unread" msgstr "Non lus" -#: functions.php:3558 functions.php:3605 modules/pref-feeds.php:657 +#: functions.php:3570 functions.php:3617 modules/pref-feeds.php:657 #: modules/pref-feeds.php:844 modules/pref-filters.php:257 #: modules/pref-labels.php:236 modules/pref-users.php:210 msgid "None" msgstr "Aucun" -#: functions.php:3560 +#: functions.php:3572 msgid "Toggle" msgstr "Marquages spéciaux " -#: functions.php:3562 functions.php:3608 tt-rss.php:164 +#: functions.php:3574 functions.php:3620 tt-rss.php:164 msgid "Starred" msgstr "Remarquables" -#: functions.php:3563 +#: functions.php:3575 msgid "Published" msgstr "Publiés" -#: functions.php:3566 localized_schema.php:15 +#: functions.php:3578 localized_schema.php:15 msgid "Mark as read" msgstr "Marquer comme lu" -#: functions.php:3567 +#: functions.php:3579 msgid "Selection" msgstr "La sélection" -#: functions.php:3568 +#: functions.php:3580 msgid "This page" msgstr "Cette page" -#: functions.php:3570 +#: functions.php:3582 msgid "Above active article" msgstr "Au-dessus de l'article courant" -#: functions.php:3571 +#: functions.php:3583 msgid "Below active article" msgstr "En dessous de l'article courant" -#: functions.php:3573 +#: functions.php:3585 msgid "Entire feed" msgstr "Tout le flux" -#: functions.php:3581 +#: functions.php:3593 msgid "Next page" msgstr "Page suivante" -#: functions.php:3582 +#: functions.php:3594 msgid "Previous page" msgstr "Page précédente" -#: functions.php:3583 +#: functions.php:3595 msgid "First page" msgstr "Première page" -#: functions.php:3593 functions.php:3619 +#: functions.php:3605 functions.php:3631 msgid "Convert to label" msgstr "Convertir en intitulé" -#: functions.php:3607 +#: functions.php:3619 msgid "Toggle:" msgstr "Marquages spéciaux :" -#: functions.php:3610 +#: functions.php:3622 msgid "Mark as read:" msgstr "Marquer comme lu :" -#: functions.php:3611 +#: functions.php:3623 msgid "Page" msgstr "Page" -#: functions.php:3612 modules/pref-filters.php:263 +#: functions.php:3624 modules/pref-filters.php:263 msgid "Feed" msgstr "Flux" -#: functions.php:3658 +#: functions.php:3670 msgid "Generated feed" msgstr "Flux généré" -#: functions.php:3994 +#: functions.php:4006 msgid "No feeds to display." msgstr "Aucun flux à afficher." -#: functions.php:4011 +#: functions.php:4023 msgid "Tags" msgstr "Étiquettes" -#: functions.php:4236 +#: functions.php:4248 msgid " - by " msgstr "- par " -#: functions.php:4285 +#: functions.php:4297 msgid "no tags" msgstr "aucune étiquette" -#: functions.php:4356 +#: functions.php:4368 msgid "Feed not found." msgstr "Flux non trouvé." -#: functions.php:4418 +#: functions.php:4430 msgid "" "Could not display feed (query failed). Please check label match syntax or " "local configuration." @@ -328,12 +309,12 @@ msgstr "" "Impossible d'afficher le flux (la requête l'a pas abouti). Veuillez vérifier " "la syntaxe de son intitulé ou la configuration locale." -#: functions.php:4616 +#: functions.php:4628 #, fuzzy msgid "Show article" msgstr "Marquer comme remarquable" -#: functions.php:4713 +#: functions.php:4725 msgid "No articles found." msgstr "Aucun article trouvé." @@ -1956,5 +1937,22 @@ msgstr "Détails de l'utilisateur" msgid "Reset password" msgstr "Réinitialiser le mot de passe" +#~ msgid "New headlines for last 24 hours, as of " +#~ msgstr "Nouveaux en-têtes dans les dernières 24 heures, à compter de " + +#~ msgid "" +#~ "You have been sent this email because you have enabled daily digests in " +#~ "Tiny Tiny RSS at " +#~ msgstr "" +#~ "Vous recevez ce courrier électronique parce que vous avez activé la " +#~ "synthèse quotidienne dans TIny Tiny RSS sur " + +#~ msgid "" +#~ "To unsubscribe, visit your configuration options or contact instance " +#~ "owner.\n" +#~ msgstr "" +#~ "Pour vous désinscrire, modifiez votre configuration ou contactez " +#~ "l'administrateur de votre TIny Tiny RSS.\n" + #~ msgid "  Update" #~ msgstr "  Mettre à jour" diff --git a/locale/pt_BR/LC_MESSAGES/messages.mo b/locale/pt_BR/LC_MESSAGES/messages.mo index 9b26ddc428e5e7b854875344bd0529822a4c917e..75306e9f9f3c48c01abde34eb8622afe4a06a1a7 100644 GIT binary patch delta 21 ccmcbYaW7*-rXq*2fr6otm5JHrLdCa209?rjod5s; delta 21 ccmcbYaW7*-rXq)trGlY}m674*LdCa209_6Tpa1{> diff --git a/locale/pt_BR/LC_MESSAGES/messages.po b/locale/pt_BR/LC_MESSAGES/messages.po index 9d6406a5..ae71d93e 100644 --- a/locale/pt_BR/LC_MESSAGES/messages.po +++ b/locale/pt_BR/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: tt-rss 1.2.14.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-29 14:21+0300\n" +"POT-Creation-Date: 2007-10-30 12:46+0300\n" "PO-Revision-Date: 2007-10-24 00:47-0200\n" "Last-Translator: Marcelo Jorge VIeira (metal) \n" "Language-Team: Portuguese/Brazil\n" @@ -140,16 +140,16 @@ msgstr "" "Sua versão do MySQL não é atualmente suportada. Por favor acesse \n" "\t\to site oficial para mais informações." -#: functions.php:2286 functions.php:2625 functions.php:2985 functions.php:3760 +#: functions.php:2286 functions.php:2625 functions.php:2985 functions.php:3772 msgid "Starred articles" msgstr "" -#: functions.php:2295 functions.php:2627 functions.php:2987 functions.php:3767 +#: functions.php:2295 functions.php:2627 functions.php:2987 functions.php:3779 #: modules/pref-feeds.php:1068 msgid "Published articles" msgstr "" -#: functions.php:2304 functions.php:2629 functions.php:2989 functions.php:3745 +#: functions.php:2304 functions.php:2629 functions.php:2989 functions.php:3757 msgid "Fresh articles" msgstr "" @@ -158,8 +158,8 @@ msgstr "" msgid "All feeds" msgstr "Todos os feeds" -#: functions.php:2576 functions.php:2615 functions.php:2963 functions.php:3924 -#: functions.php:3954 modules/pref-feeds.php:880 +#: functions.php:2576 functions.php:2615 functions.php:2963 functions.php:3936 +#: functions.php:3966 modules/pref-feeds.php:880 msgid "Uncategorized" msgstr "Não Categorizado" @@ -179,149 +179,134 @@ msgstr "" msgid "Searched for" msgstr "" -#: functions.php:3271 -msgid "New headlines for last 24 hours, as of " -msgstr "" - -#: functions.php:3322 -msgid "" -"You have been sent this email because you have enabled daily digests in Tiny " -"Tiny RSS at " -msgstr "" - -#: functions.php:3324 -msgid "" -"To unsubscribe, visit your configuration options or contact instance owner.\n" -msgstr "" - -#: functions.php:3555 functions.php:3602 functions.php:4650 +#: functions.php:3567 functions.php:3614 functions.php:4662 #: modules/pref-feeds.php:655 modules/pref-feeds.php:842 #: modules/pref-filters.php:255 modules/pref-labels.php:234 #: modules/pref-users.php:208 msgid "Select:" msgstr "Selecione:" -#: functions.php:3556 functions.php:3603 modules/pref-feeds.php:656 +#: functions.php:3568 functions.php:3615 modules/pref-feeds.php:656 #: modules/pref-feeds.php:843 modules/pref-filters.php:256 #: modules/pref-labels.php:235 modules/pref-users.php:209 msgid "All" msgstr "Todos" -#: functions.php:3557 functions.php:3561 functions.php:3604 functions.php:3607 +#: functions.php:3569 functions.php:3573 functions.php:3616 functions.php:3619 #: tt-rss.php:165 msgid "Unread" msgstr "Não Lido" -#: functions.php:3558 functions.php:3605 modules/pref-feeds.php:657 +#: functions.php:3570 functions.php:3617 modules/pref-feeds.php:657 #: modules/pref-feeds.php:844 modules/pref-filters.php:257 #: modules/pref-labels.php:236 modules/pref-users.php:210 msgid "None" msgstr "Nenhum" -#: functions.php:3560 +#: functions.php:3572 msgid "Toggle" msgstr "" -#: functions.php:3562 functions.php:3608 tt-rss.php:164 +#: functions.php:3574 functions.php:3620 tt-rss.php:164 msgid "Starred" msgstr "Favoritos" -#: functions.php:3563 +#: functions.php:3575 msgid "Published" msgstr "Publicado" -#: functions.php:3566 localized_schema.php:15 +#: functions.php:3578 localized_schema.php:15 msgid "Mark as read" msgstr "Marcar como lido" -#: functions.php:3567 +#: functions.php:3579 msgid "Selection" msgstr "Seleção" -#: functions.php:3568 +#: functions.php:3580 msgid "This page" msgstr "" -#: functions.php:3570 +#: functions.php:3582 msgid "Above active article" msgstr "" -#: functions.php:3571 +#: functions.php:3583 msgid "Below active article" msgstr "" -#: functions.php:3573 +#: functions.php:3585 msgid "Entire feed" msgstr "" -#: functions.php:3581 +#: functions.php:3593 msgid "Next page" msgstr "Próxima página" -#: functions.php:3582 +#: functions.php:3594 msgid "Previous page" msgstr "Página anterior" -#: functions.php:3583 +#: functions.php:3595 msgid "First page" msgstr "Primeira página" -#: functions.php:3593 functions.php:3619 +#: functions.php:3605 functions.php:3631 msgid "Convert to label" msgstr "" -#: functions.php:3607 +#: functions.php:3619 msgid "Toggle:" msgstr "" -#: functions.php:3610 +#: functions.php:3622 msgid "Mark as read:" msgstr "Marcar como lido:" -#: functions.php:3611 +#: functions.php:3623 msgid "Page" msgstr "Página" -#: functions.php:3612 modules/pref-filters.php:263 +#: functions.php:3624 modules/pref-filters.php:263 msgid "Feed" msgstr "Feed" -#: functions.php:3658 +#: functions.php:3670 msgid "Generated feed" msgstr "" -#: functions.php:3994 +#: functions.php:4006 msgid "No feeds to display." msgstr "Sem Feeds para exibir." -#: functions.php:4011 +#: functions.php:4023 msgid "Tags" msgstr "Tags" -#: functions.php:4236 +#: functions.php:4248 msgid " - by " msgstr " - por " -#: functions.php:4285 +#: functions.php:4297 msgid "no tags" msgstr "sem tags" -#: functions.php:4356 +#: functions.php:4368 msgid "Feed not found." msgstr "Feed não encontrado." -#: functions.php:4418 +#: functions.php:4430 msgid "" "Could not display feed (query failed). Please check label match syntax or " "local configuration." msgstr "" -#: functions.php:4616 +#: functions.php:4628 #, fuzzy msgid "Show article" msgstr "Favoritos" -#: functions.php:4713 +#: functions.php:4725 msgid "No articles found." msgstr "" diff --git a/locale/ru_RU/LC_MESSAGES/messages.mo b/locale/ru_RU/LC_MESSAGES/messages.mo index 28efb9c4d65f8567dab9466206335d4f971f95e4..5aab32d31c51114a4ecb9ea04f2e7bf904d9a388 100644 GIT binary patch delta 6586 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 delta 6698 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\n" "Language-Team: Русский \n" @@ -140,16 +140,16 @@ msgid "" "\t\tofficial site for more information." msgstr "" -#: functions.php:2286 functions.php:2625 functions.php:2985 functions.php:3760 +#: functions.php:2286 functions.php:2625 functions.php:2985 functions.php:3772 msgid "Starred articles" msgstr "Отмеченные" -#: functions.php:2295 functions.php:2627 functions.php:2987 functions.php:3767 +#: functions.php:2295 functions.php:2627 functions.php:2987 functions.php:3779 #: modules/pref-feeds.php:1068 msgid "Published articles" msgstr "Опубликованные" -#: functions.php:2304 functions.php:2629 functions.php:2989 functions.php:3745 +#: functions.php:2304 functions.php:2629 functions.php:2989 functions.php:3757 #, fuzzy msgid "Fresh articles" msgstr "Отмеченные" @@ -159,8 +159,8 @@ msgstr "Отмеченные" msgid "All feeds" msgstr "Все каналы" -#: functions.php:2576 functions.php:2615 functions.php:2963 functions.php:3924 -#: functions.php:3954 modules/pref-feeds.php:880 +#: functions.php:2576 functions.php:2615 functions.php:2963 functions.php:3936 +#: functions.php:3966 modules/pref-feeds.php:880 msgid "Uncategorized" msgstr "Нет категории" @@ -180,151 +180,136 @@ msgstr "Результаты поиска" msgid "Searched for" msgstr "Поиск" -#: functions.php:3271 -msgid "New headlines for last 24 hours, as of " -msgstr "Новые заголовки за последние 24 часа, на " - -#: functions.php:3322 -msgid "" -"You have been sent this email because you have enabled daily digests in Tiny " -"Tiny RSS at " -msgstr "" - -#: functions.php:3324 -msgid "" -"To unsubscribe, visit your configuration options or contact instance owner.\n" -msgstr "" - -#: functions.php:3555 functions.php:3602 functions.php:4650 +#: functions.php:3567 functions.php:3614 functions.php:4662 #: modules/pref-feeds.php:655 modules/pref-feeds.php:842 #: modules/pref-filters.php:255 modules/pref-labels.php:234 #: modules/pref-users.php:208 msgid "Select:" msgstr "Выбрать:" -#: functions.php:3556 functions.php:3603 modules/pref-feeds.php:656 +#: functions.php:3568 functions.php:3615 modules/pref-feeds.php:656 #: modules/pref-feeds.php:843 modules/pref-filters.php:256 #: modules/pref-labels.php:235 modules/pref-users.php:209 msgid "All" msgstr "Все" -#: functions.php:3557 functions.php:3561 functions.php:3604 functions.php:3607 +#: functions.php:3569 functions.php:3573 functions.php:3616 functions.php:3619 #: tt-rss.php:165 msgid "Unread" msgstr "Новые" -#: functions.php:3558 functions.php:3605 modules/pref-feeds.php:657 +#: functions.php:3570 functions.php:3617 modules/pref-feeds.php:657 #: modules/pref-feeds.php:844 modules/pref-filters.php:257 #: modules/pref-labels.php:236 modules/pref-users.php:210 msgid "None" msgstr "Ничего" -#: functions.php:3560 +#: functions.php:3572 msgid "Toggle" msgstr "Изменить:" -#: functions.php:3562 functions.php:3608 tt-rss.php:164 +#: functions.php:3574 functions.php:3620 tt-rss.php:164 msgid "Starred" msgstr "Отмеченные" -#: functions.php:3563 +#: functions.php:3575 msgid "Published" msgstr "Опубликован" -#: functions.php:3566 localized_schema.php:15 +#: functions.php:3578 localized_schema.php:15 msgid "Mark as read" msgstr "Как прочитанные" -#: functions.php:3567 +#: functions.php:3579 #, fuzzy msgid "Selection" msgstr "Выбрать:" -#: functions.php:3568 +#: functions.php:3580 msgid "This page" msgstr "Эту страницу" -#: functions.php:3570 +#: functions.php:3582 msgid "Above active article" msgstr "" -#: functions.php:3571 +#: functions.php:3583 #, fuzzy msgid "Below active article" msgstr "Отфильтровать статью" -#: functions.php:3573 +#: functions.php:3585 msgid "Entire feed" msgstr "Весь канал" -#: functions.php:3581 +#: functions.php:3593 msgid "Next page" msgstr "След. стр." -#: functions.php:3582 +#: functions.php:3594 msgid "Previous page" msgstr "Пред. cтр." -#: functions.php:3583 +#: functions.php:3595 msgid "First page" msgstr "На первую" -#: functions.php:3593 functions.php:3619 +#: functions.php:3605 functions.php:3631 msgid "Convert to label" msgstr "Превратить в метку" -#: functions.php:3607 +#: functions.php:3619 msgid "Toggle:" msgstr "Изменить:" -#: functions.php:3610 +#: functions.php:3622 msgid "Mark as read:" msgstr "Пометить как прочит.:" -#: functions.php:3611 +#: functions.php:3623 msgid "Page" msgstr "Страница" -#: functions.php:3612 modules/pref-filters.php:263 +#: functions.php:3624 modules/pref-filters.php:263 msgid "Feed" msgstr "Канал" -#: functions.php:3658 +#: functions.php:3670 msgid "Generated feed" msgstr "" -#: functions.php:3994 +#: functions.php:4006 msgid "No feeds to display." msgstr "Нет каналов для отображения." -#: functions.php:4011 +#: functions.php:4023 msgid "Tags" msgstr "Теги" -#: functions.php:4236 +#: functions.php:4248 msgid " - by " msgstr ", автор - " -#: functions.php:4285 +#: functions.php:4297 msgid "no tags" msgstr "нет тегов" -#: functions.php:4356 +#: functions.php:4368 msgid "Feed not found." msgstr "Канал не найден." -#: functions.php:4418 +#: functions.php:4430 msgid "" "Could not display feed (query failed). Please check label match syntax or " "local configuration." msgstr "" -#: functions.php:4616 +#: functions.php:4628 #, fuzzy msgid "Show article" msgstr "Отмеченные" -#: functions.php:4713 +#: functions.php:4725 msgid "No articles found." msgstr "Статей не найдено." @@ -1871,6 +1856,9 @@ msgstr "Подробнее..." msgid "Reset password" msgstr "Сбросить пароль" +#~ msgid "New headlines for last 24 hours, as of " +#~ msgstr "Новые заголовки за последние 24 часа, на " + #~ msgid "  Update" #~ msgstr "  ÐžÐ±Ð½Ð¾Ð²Ð¸Ñ‚ÑŒ" diff --git a/locale/zh_CN/LC_MESSAGES/messages.mo b/locale/zh_CN/LC_MESSAGES/messages.mo index fd9d4f181a0c4634c937b4c6f5702c493fcbe357..73dee5e96af1024dcc0a3411b67f5816ce86f60a 100644 GIT binary patch delta 8233 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 bdSOww>k)-lhFl0Kj2e5wzcBgU73Ka9GIMg? delta 8695 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 BBEtXx diff --git a/locale/zh_CN/LC_MESSAGES/messages.po b/locale/zh_CN/LC_MESSAGES/messages.po index 5a83e889..26b59268 100644 --- a/locale/zh_CN/LC_MESSAGES/messages.po +++ b/locale/zh_CN/LC_MESSAGES/messages.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Tiny Tiny RSS1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-29 14:21+0300\n" +"POT-Creation-Date: 2007-10-30 12:46+0300\n" "PO-Revision-Date: 2007-08-19 19:03+0800\n" "Last-Translator: sluke \n" "Language-Team: hicode.org \n" @@ -136,16 +136,16 @@ msgstr "" "不支持你的MySQL版本. 请访问 \n" "\t\t官方网站获取更多信息。" -#: functions.php:2286 functions.php:2625 functions.php:2985 functions.php:3760 +#: functions.php:2286 functions.php:2625 functions.php:2985 functions.php:3772 msgid "Starred articles" msgstr "星级文章" -#: functions.php:2295 functions.php:2627 functions.php:2987 functions.php:3767 +#: functions.php:2295 functions.php:2627 functions.php:2987 functions.php:3779 #: modules/pref-feeds.php:1068 msgid "Published articles" msgstr "已发布文章" -#: functions.php:2304 functions.php:2629 functions.php:2989 functions.php:3745 +#: functions.php:2304 functions.php:2629 functions.php:2989 functions.php:3757 #, fuzzy msgid "Fresh articles" msgstr "星级文章" @@ -155,8 +155,8 @@ msgstr "星级文章" msgid "All feeds" msgstr "所有feed" -#: functions.php:2576 functions.php:2615 functions.php:2963 functions.php:3924 -#: functions.php:3954 modules/pref-feeds.php:880 +#: functions.php:2576 functions.php:2615 functions.php:2963 functions.php:3936 +#: functions.php:3966 modules/pref-feeds.php:880 msgid "Uncategorized" msgstr "未分类" @@ -176,150 +176,135 @@ msgstr "搜索结果" msgid "Searched for" msgstr "搜索" -#: functions.php:3271 -msgid "New headlines for last 24 hours, as of " -msgstr "24小时最新提要,截至" - -#: functions.php:3322 -msgid "" -"You have been sent this email because you have enabled daily digests in Tiny " -"Tiny RSS at " -msgstr "由于您启用了Tiny Tiny RSS每日文摘,会收到此邮件。" - -#: functions.php:3324 -msgid "" -"To unsubscribe, visit your configuration options or contact instance owner.\n" -msgstr "若要退订,访问你的配置选项或联络管理员。\n" - -#: functions.php:3555 functions.php:3602 functions.php:4650 +#: functions.php:3567 functions.php:3614 functions.php:4662 #: modules/pref-feeds.php:655 modules/pref-feeds.php:842 #: modules/pref-filters.php:255 modules/pref-labels.php:234 #: modules/pref-users.php:208 msgid "Select:" msgstr "选择:" -#: functions.php:3556 functions.php:3603 modules/pref-feeds.php:656 +#: functions.php:3568 functions.php:3615 modules/pref-feeds.php:656 #: modules/pref-feeds.php:843 modules/pref-filters.php:256 #: modules/pref-labels.php:235 modules/pref-users.php:209 msgid "All" msgstr "所有" -#: functions.php:3557 functions.php:3561 functions.php:3604 functions.php:3607 +#: functions.php:3569 functions.php:3573 functions.php:3616 functions.php:3619 #: tt-rss.php:165 msgid "Unread" msgstr "未读" -#: functions.php:3558 functions.php:3605 modules/pref-feeds.php:657 +#: functions.php:3570 functions.php:3617 modules/pref-feeds.php:657 #: modules/pref-feeds.php:844 modules/pref-filters.php:257 #: modules/pref-labels.php:236 modules/pref-users.php:210 msgid "None" msgstr "无" -#: functions.php:3560 +#: functions.php:3572 msgid "Toggle" msgstr "触发开关" -#: functions.php:3562 functions.php:3608 tt-rss.php:164 +#: functions.php:3574 functions.php:3620 tt-rss.php:164 msgid "Starred" msgstr "星级" -#: functions.php:3563 +#: functions.php:3575 msgid "Published" msgstr "已发布" -#: functions.php:3566 localized_schema.php:15 +#: functions.php:3578 localized_schema.php:15 msgid "Mark as read" msgstr "标记为已读" -#: functions.php:3567 +#: functions.php:3579 msgid "Selection" msgstr "选择:" -#: functions.php:3568 +#: functions.php:3580 msgid "This page" msgstr "本页" -#: functions.php:3570 +#: functions.php:3582 msgid "Above active article" msgstr "" -#: functions.php:3571 +#: functions.php:3583 #, fuzzy msgid "Below active article" msgstr "过滤文章" -#: functions.php:3573 +#: functions.php:3585 msgid "Entire feed" msgstr "输入feed" -#: functions.php:3581 +#: functions.php:3593 msgid "Next page" msgstr "下页" -#: functions.php:3582 +#: functions.php:3594 msgid "Previous page" msgstr "上页" -#: functions.php:3583 +#: functions.php:3595 msgid "First page" msgstr "首页" -#: functions.php:3593 functions.php:3619 +#: functions.php:3605 functions.php:3631 msgid "Convert to label" msgstr "转换标签" -#: functions.php:3607 +#: functions.php:3619 msgid "Toggle:" msgstr "触发:" -#: functions.php:3610 +#: functions.php:3622 msgid "Mark as read:" msgstr "标记为已读:" -#: functions.php:3611 +#: functions.php:3623 msgid "Page" msgstr "页" -#: functions.php:3612 modules/pref-filters.php:263 +#: functions.php:3624 modules/pref-filters.php:263 msgid "Feed" msgstr "Feed" -#: functions.php:3658 +#: functions.php:3670 msgid "Generated feed" msgstr "产生feed" -#: functions.php:3994 +#: functions.php:4006 msgid "No feeds to display." msgstr "无feed显示。" -#: functions.php:4011 +#: functions.php:4023 msgid "Tags" msgstr "标签" -#: functions.php:4236 +#: functions.php:4248 msgid " - by " msgstr ", 由 - " -#: functions.php:4285 +#: functions.php:4297 msgid "no tags" msgstr "无标签" -#: functions.php:4356 +#: functions.php:4368 msgid "Feed not found." msgstr "未找到Feed." -#: functions.php:4418 +#: functions.php:4430 msgid "" "Could not display feed (query failed). Please check label match syntax or " "local configuration." msgstr "无法显示feed(查询失败); 请核对标签匹配语法或本地配置." -#: functions.php:4616 +#: functions.php:4628 #, fuzzy msgid "Show article" msgstr "星级文章" -#: functions.php:4713 +#: functions.php:4725 msgid "No articles found." msgstr "未找到文章。" @@ -1887,5 +1872,18 @@ msgstr "用户详细" msgid "Reset password" msgstr "重置密码" +#~ msgid "New headlines for last 24 hours, as of " +#~ msgstr "24小时最新提要,截至" + +#~ msgid "" +#~ "You have been sent this email because you have enabled daily digests in " +#~ "Tiny Tiny RSS at " +#~ msgstr "由于您启用了Tiny Tiny RSS每日文摘,会收到此邮件。" + +#~ msgid "" +#~ "To unsubscribe, visit your configuration options or contact instance " +#~ "owner.\n" +#~ msgstr "若要退订,访问你的配置选项或联络管理员。\n" + #~ msgid "  Update" #~ msgstr "  æ›´æ–°" diff --git a/templates/digest_template.txt b/templates/digest_template.txt new file mode 100644 index 00000000..aa56fb3a --- /dev/null +++ b/templates/digest_template.txt @@ -0,0 +1,14 @@ + +New headlines for last 24 hours, as of ${CUR_DATE} ${CUR_TIME} +============================================================== + +${FEED_TITLE} + + +* ${ARTICLE_TITLE} - ${ARTICLE_UPDATED} + ${ARTICLE_LINK} + + +-- +To unsubscribe, visit your configuration options or contact instance owner. + diff --git a/templates/digest_template_html.txt b/templates/digest_template_html.txt new file mode 100644 index 00000000..4b85f8ba --- /dev/null +++ b/templates/digest_template_html.txt @@ -0,0 +1,14 @@ + +

New headlines for last 24 hours, as of ${CUR_DATE} ${CUR_TIME}

+ +

${FEED_TITLE}

+ + + + +

To unsubscribe, visit your configuration options or contact instance owner.

+ -- 2.39.2